From 303203f992088d05d930b2d7e4bb826c2b611a53 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Mon, 28 Dec 2020 16:59:36 +0100 Subject: [PATCH 01/12] Mention Arc::make_mut and Rc::make_mut in the documentation of Cow --- library/alloc/src/borrow.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs index f801c1ac75b..adf996fc782 100644 --- a/library/alloc/src/borrow.rs +++ b/library/alloc/src/borrow.rs @@ -103,6 +103,11 @@ where /// is desired, `to_mut` will obtain a mutable reference to an owned /// value, cloning if necessary. /// +/// If you need reference-counting pointers, note that +/// [`Rc::make_mut`][crate::rc::Rc::make_mut] and +/// [`Arc::make_mut`][crate::sync::Arc::make_mut] can provide clone-on-write +/// functionality as well. +/// /// # Examples /// /// ``` From 87423fbc6af5aae2b5f6d0a11f2a0c60c7c22e98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 30 Dec 2020 22:52:04 +0100 Subject: [PATCH 02/12] bootstrap: clippy fixes addresses: clippy::or_fun_call clippy::single_char_add_str clippy::comparison_to_empty clippy::or_fun_call --- src/bootstrap/builder.rs | 2 +- src/bootstrap/channel.rs | 4 ++-- src/bootstrap/config.rs | 2 +- src/bootstrap/dist.rs | 8 ++++---- src/bootstrap/lib.rs | 4 ++-- src/bootstrap/sanity.rs | 6 +++++- src/bootstrap/setup.rs | 4 ++-- src/bootstrap/test.rs | 2 +- 8 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index c2abb01fa8c..ec9ce4c820c 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -1534,7 +1534,7 @@ impl Rustflags { fn arg(&mut self, arg: &str) -> &mut Self { assert_eq!(arg.split(' ').count(), 1); if !self.0.is_empty() { - self.0.push_str(" "); + self.0.push(' '); } self.0.push_str(arg); self diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 2b82f6c30b2..6e65be93fec 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -74,9 +74,9 @@ impl GitInfo { if let Some(ref inner) = self.inner { version.push_str(" ("); version.push_str(&inner.short_sha); - version.push_str(" "); + version.push(' '); version.push_str(&inner.commit_date); - version.push_str(")"); + version.push(')'); } version } diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index def8f215436..a8b1082edeb 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -334,7 +334,7 @@ impl Merge for TomlConfig { *x = Some(new); } } - }; + } do_merge(&mut self.build, build); do_merge(&mut self.install, install); do_merge(&mut self.llvm, llvm); diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 0a79d09b27f..dff9e12ee11 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1326,17 +1326,17 @@ impl Step for Extended { license += &builder.read(&builder.src.join("COPYRIGHT")); license += &builder.read(&builder.src.join("LICENSE-APACHE")); license += &builder.read(&builder.src.join("LICENSE-MIT")); - license.push_str("\n"); - license.push_str("\n"); + license.push('\n'); + license.push('\n'); let rtf = r"{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset0 Arial;}}\nowwrap\fs18"; let mut rtf = rtf.to_string(); - rtf.push_str("\n"); + rtf.push('\n'); for line in license.lines() { rtf.push_str(line); rtf.push_str("\\line "); } - rtf.push_str("}"); + rtf.push('}'); fn filter(contents: &str, marker: &str) -> String { let start = format!("tool-{}-start", marker); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index a47ddfbcc1f..88fdcfa2d43 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1083,7 +1083,7 @@ impl Build { if let Some(ref s) = self.config.description { version.push_str(" ("); version.push_str(s); - version.push_str(")"); + version.push(')'); } version } @@ -1144,7 +1144,7 @@ impl Build { && (dep != "profiler_builtins" || target .map(|t| self.config.profiler_enabled(t)) - .unwrap_or(self.config.any_profiler_enabled())) + .unwrap_or_else(|| self.config.any_profiler_enabled())) && (dep != "rustc_codegen_llvm" || self.config.llvm_enabled()) { list.push(*dep); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index acb941d9540..08acc3d671f 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -163,7 +163,11 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } - build.config.target_config.entry(*target).or_insert(Target::from_triple(&target.triple)); + build + .config + .target_config + .entry(*target) + .or_insert_with(|| Target::from_triple(&target.triple)); if target.contains("-none-") || target.contains("nvptx") { if build.no_std(*target) == Some(false) { diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 2d4484c562c..725147767db 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -89,7 +89,7 @@ pub fn setup(src_path: &Path, profile: Profile) { std::process::exit(1); } - let path = cfg_file.unwrap_or("config.toml".into()); + let path = cfg_file.unwrap_or_else(|| "config.toml".into()); let settings = format!( "# Includes one of the default files in src/bootstrap/defaults\n\ profile = \"{}\"\n\ @@ -156,7 +156,7 @@ pub fn interactive_path() -> io::Result { io::stdout().flush()?; let mut input = String::new(); io::stdin().read_line(&mut input)?; - if input == "" { + if input.is_empty() { eprintln!("EOF on stdin, when expecting answer to question. Giving up."); std::process::exit(1); } diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 859236804d3..66a18dfbeaa 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1135,7 +1135,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the // flag is respected, so providing an empty --test-args conflicts with // any following it. match p.strip_prefix(suite_path).ok().and_then(|p| p.to_str()) { - Some(s) if s != "" => Some(s), + Some(s) if !s.is_empty() => Some(s), _ => None, } }) From a2f277805c6ce130692fc652ccaf9a8a1bf8b28d Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Sat, 2 Jan 2021 09:58:23 +0000 Subject: [PATCH 03/12] Remove reverted change from relnotes --- RELEASES.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 8f04980e390..4409b6ad7b1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -45,7 +45,6 @@ Libraries - [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109] - [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997] -- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989] Stabilized APIs --------------- @@ -110,7 +109,6 @@ related tools. [76199]: https://github.com/rust-lang/rust/pull/76199 [76119]: https://github.com/rust-lang/rust/pull/76119 [75914]: https://github.com/rust-lang/rust/pull/75914 -[74989]: https://github.com/rust-lang/rust/pull/74989 [79004]: https://github.com/rust-lang/rust/pull/79004 [78676]: https://github.com/rust-lang/rust/pull/78676 [79904]: https://github.com/rust-lang/rust/issues/79904 From 203d5025bb70b21a0f75235a8cec23c0b1b571a1 Mon Sep 17 00:00:00 2001 From: LingMan Date: Sun, 3 Jan 2021 04:38:56 +0100 Subject: [PATCH 04/12] Use Option::filter instead of open-coding it --- .../infer/error_reporting/need_type_info.rs | 28 ++++++------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 373f0a602c0..e097264ec8a 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -43,22 +43,18 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> { } fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option> { - let ty_opt = self - .infcx + self.infcx .in_progress_typeck_results - .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id)); - match ty_opt { - Some(ty) => { - let ty = self.infcx.resolve_vars_if_possible(ty); - if ty.walk().any(|inner| { + .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id)) + .map(|ty| self.infcx.resolve_vars_if_possible(ty)) + .filter(|ty| { + ty.walk().any(|inner| { inner == self.target || match (inner.unpack(), self.target.unpack()) { (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => { + use ty::{Infer, TyVar}; match (inner_ty.kind(), target_ty.kind()) { - ( - &ty::Infer(ty::TyVar(a_vid)), - &ty::Infer(ty::TyVar(b_vid)), - ) => self + (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self .infcx .inner .borrow_mut() @@ -69,14 +65,8 @@ impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> { } _ => false, } - }) { - Some(ty) - } else { - None - } - } - None => None, - } + }) + }) } } From af7134e7de793ea3bba30bc350daef76ea9de755 Mon Sep 17 00:00:00 2001 From: LingMan Date: Sun, 3 Jan 2021 09:19:52 +0100 Subject: [PATCH 05/12] Move variable into the only branch where it is relevant At the `if` branch `filter` (the `let` binding) is `None` iff `filter` (the parameter) was `None`. We can branch on the parameter, move the binding into the `if`, and the complexity of handling `Option` largely dissolves. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 43f7b2a9928..4aaacdc593f 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1345,15 +1345,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { return &[]; } - // Do a reverse lookup beforehand to avoid touching the crate_num - // hash map in the loop below. - let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) { - Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)), - Some(None) => return &[], - None => None, - }; + if let Some(def_id) = filter { + // Do a reverse lookup beforehand to avoid touching the crate_num + // hash map in the loop below. + let filter = match self.reverse_translate_def_id(def_id) { + Some(def_id) => (def_id.krate.as_u32(), def_id.index), + None => return &[], + }; - if let Some(filter) = filter { if let Some(impls) = self.trait_impls.get(&filter) { tcx.arena.alloc_from_iter( impls.decode(self).map(|(idx, simplified_self_ty)| { From 514b0ce9d2a3ff4f527c9e542ff09f8b95216439 Mon Sep 17 00:00:00 2001 From: bool Date: Sun, 3 Jan 2021 19:54:54 +0200 Subject: [PATCH 06/12] Fixed documentation error --- library/core/src/hint.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 979a5f8cf50..313729581ac 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -91,7 +91,7 @@ pub const unsafe fn unreachable_unchecked() -> ! { /// }; /// /// // Back on our current thread, we wait for the value to be set -/// while live.load(Ordering::Acquire) { +/// while !live.load(Ordering::Acquire) { /// // The spin loop is a hint to the CPU that we're waiting, but probably /// // not for very long /// hint::spin_loop(); From 6d45d055a122a3a44a9e76baca02d440f5c7aef3 Mon Sep 17 00:00:00 2001 From: Jeremy Lin Date: Sun, 3 Jan 2021 13:59:02 -0800 Subject: [PATCH 07/12] Fix missing link for "fully qualified syntax" --- library/alloc/src/rc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 3115cc3d002..8183a582d33 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -238,6 +238,7 @@ //! [downgrade]: Rc::downgrade //! [upgrade]: Weak::upgrade //! [mutability]: core::cell#introducing-mutability-inside-of-something-immutable +//! [fully qualified syntax]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#fully-qualified-syntax-for-disambiguation-calling-methods-with-the-same-name #![stable(feature = "rust1", since = "1.0.0")] From 6a4b24e4dd98ded6eae4583e0201692140a85f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 4 Jan 2021 02:20:42 +0100 Subject: [PATCH 08/12] ./x.py clippy: allow the most noisy lints This silences the following clippy lints in ./x.py clippy: many_single_char_names (there are a lot of warnings caused by stdarch) collapsible_if (can reduce readability) type_complexity missing_safety_doc (there are almost 3K warnings issued) too_many_arguments needless_lifetimes (people want 'tcx lifetimes etc) wrong_self_convention (warns about from_..(), to_..(), into_..().. fns that do or do not take self by reference. --- src/bootstrap/check.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index f65b2b2c79f..72a979338a5 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -21,6 +21,16 @@ fn args(builder: &Builder<'_>) -> Vec { } if let Subcommand::Clippy { fix, .. } = builder.config.cmd { + // disable the most spammy clippy lints + let ignored_lints = vec![ + "many_single_char_names", // there are a lot in stdarch + "collapsible_if", + "type_complexity", + "missing_safety_doc", // almost 3K warnings + "too_many_arguments", + "needless_lifetimes", // people want to keep the lifetimes + "wrong_self_convention", + ]; let mut args = vec![]; if fix { #[rustfmt::skip] @@ -33,6 +43,7 @@ fn args(builder: &Builder<'_>) -> Vec { ])); } args.extend(strings(&["--", "--cap-lints", "warn"])); + args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint))); args } else { vec![] From e152582a2b5c214d705c6c60e12dc4d996491081 Mon Sep 17 00:00:00 2001 From: oliver <16816606+kw-fn@users.noreply.github.com> Date: Mon, 4 Jan 2021 04:50:24 +0000 Subject: [PATCH 09/12] doc -- list edit for consistency --- library/core/src/iter/adapters/zip.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs index 8cd4c775231..5766fd3c887 100644 --- a/library/core/src/iter/adapters/zip.rs +++ b/library/core/src/iter/adapters/zip.rs @@ -397,7 +397,7 @@ impl ZipFmt Date: Wed, 30 Dec 2020 23:07:41 +0000 Subject: [PATCH 10/12] Add check for array/usize mismatch in astconv --- Cargo.lock | 1 + compiler/rustc_hir/Cargo.toml | 1 + compiler/rustc_hir/src/hir.rs | 8 ++ compiler/rustc_middle/src/ty/mod.rs | 9 ++ compiler/rustc_typeck/src/astconv/generics.rs | 92 ++++++++++--------- .../const-generics/suggest_const_for_array.rs | 10 ++ .../suggest_const_for_array.stderr | 15 +++ 7 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 src/test/ui/const-generics/suggest_const_for_array.rs create mode 100644 src/test/ui/const-generics/suggest_const_for_array.stderr diff --git a/Cargo.lock b/Cargo.lock index 4676e4127e8..f4aa12e6564 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3745,6 +3745,7 @@ version = "0.0.0" dependencies = [ "rustc_ast", "rustc_data_structures", + "rustc_feature", "rustc_index", "rustc_macros", "rustc_serialize", diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index b24c208c76a..c14165454ed 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -9,6 +9,7 @@ doctest = false [dependencies] rustc_target = { path = "../rustc_target" } +rustc_feature = { path = "../rustc_feature" } rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 23999a8dca0..de49b03f5ce 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -290,6 +290,14 @@ impl GenericArg<'_> { GenericArg::Const(_) => "const", } } + + pub fn to_ord(&self, feats: &rustc_feature::Features) -> ast::ParamKindOrd { + match self { + GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime, + GenericArg::Type(_) => ast::ParamKindOrd::Type, + GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics }, + } + } } #[derive(Debug, HashStable_Generic)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1fe1400fabe..59a3ac94634 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -801,6 +801,15 @@ impl GenericParamDefKind { GenericParamDefKind::Const => "constant", } } + pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { + match self { + GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, + GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, + GenericParamDefKind::Const => { + ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + } + } + } } #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0feac036f00..2253e67c32c 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -11,7 +11,7 @@ use rustc_hir::GenericArg; use rustc_middle::ty::{ self, subst, subst::SubstsRef, GenericParamDef, GenericParamDefKind, Ty, TyCtxt, }; -use rustc_session::{lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, Session}; +use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS; use rustc_span::{symbol::kw, MultiSpan, Span}; use smallvec::SmallVec; @@ -20,62 +20,72 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was /// expected. fn generic_arg_mismatch_err( - sess: &Session, + tcx: TyCtxt<'_>, arg: &GenericArg<'_>, - kind: &'static str, + param: &GenericParamDef, possible_ordering_error: bool, help: Option<&str>, ) { + let sess = tcx.sess; let mut err = struct_span_err!( sess, arg.span(), E0747, "{} provided when a {} was expected", arg.descr(), - kind, + param.kind.descr(), ); - let unordered = sess.features_untracked().const_generics; - let kind_ord = match kind { - "lifetime" => ParamKindOrd::Lifetime, - "type" => ParamKindOrd::Type, - "constant" => ParamKindOrd::Const { unordered }, - // It's more concise to match on the string representation, though it means - // the match is non-exhaustive. - _ => bug!("invalid generic parameter kind {}", kind), - }; - - if let ParamKindOrd::Const { .. } = kind_ord { + if let GenericParamDefKind::Const { .. } = param.kind { if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg { err.help("const arguments cannot yet be inferred with `_`"); } } - let arg_ord = match arg { - GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, - GenericArg::Type(_) => ParamKindOrd::Type, - GenericArg::Const(_) => ParamKindOrd::Const { unordered }, - }; - - if matches!(arg, GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. })) - && matches!(kind_ord, ParamKindOrd::Const { .. }) - { - let suggestions = vec![ - (arg.span().shrink_to_lo(), String::from("{ ")), - (arg.span().shrink_to_hi(), String::from(" }")), - ]; - err.multipart_suggestion( - "if this generic argument was intended as a const parameter, \ + // Specific suggestion set for diagnostics + match (arg, ¶m.kind) { + ( + GenericArg::Type(hir::Ty { kind: hir::TyKind::Path { .. }, .. }), + GenericParamDefKind::Const { .. }, + ) => { + let suggestions = vec![ + (arg.span().shrink_to_lo(), String::from("{ ")), + (arg.span().shrink_to_hi(), String::from(" }")), + ]; + err.multipart_suggestion( + "if this generic argument was intended as a const parameter, \ try surrounding it with braces:", - suggestions, - Applicability::MaybeIncorrect, - ); + suggestions, + Applicability::MaybeIncorrect, + ); + } + ( + GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), + GenericParamDefKind::Const { .. }, + ) if tcx.type_of(param.def_id) == tcx.types.usize => { + let snippet = sess.source_map().span_to_snippet(tcx.hir().span(len.hir_id)); + if let Ok(snippet) = snippet { + err.span_suggestion( + arg.span(), + "array type provided where a `usize` was expected, try", + format!("{{ {} }}", snippet), + Applicability::MaybeIncorrect, + ); + } + } + _ => {} } + let kind_ord = param.kind.to_ord(tcx); + let arg_ord = arg.to_ord(&tcx.features()); + // This note is only true when generic parameters are strictly ordered by their kind. if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal { - let (first, last) = - if kind_ord < arg_ord { (kind, arg.descr()) } else { (arg.descr(), kind) }; + let (first, last) = if kind_ord < arg_ord { + (param.kind.descr(), arg.descr()) + } else { + (arg.descr(), param.kind.descr()) + }; err.note(&format!("{} arguments must be provided before {} arguments", first, last)); if let Some(help) = help { err.help(help); @@ -203,7 +213,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. substs.push(ctx.inferred_kind(None, param, infer_args)); - force_infer_lt = Some(arg); + force_infer_lt = Some((arg, param)); params.next(); } (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => { @@ -213,7 +223,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // ignore it. args.next(); } - (_, kind, _) => { + (_, _, _) => { // We expected one kind of parameter, but the user provided // another. This is an error. However, if we already know that // the arguments don't match up with the parameters, we won't issue @@ -256,9 +266,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { param_types_present.dedup(); Self::generic_arg_mismatch_err( - tcx.sess, + tcx, arg, - kind.descr(), + param, !args_iter.clone().is_sorted_by_key(|arg| match arg { GenericArg::Lifetime(_) => ParamKindOrd::Lifetime, GenericArg::Type(_) => ParamKindOrd::Type, @@ -315,9 +325,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let kind = arg.descr(); assert_eq!(kind, "lifetime"); - let provided = + let (provided_arg, param) = force_infer_lt.expect("lifetimes ought to have been inferred"); - Self::generic_arg_mismatch_err(tcx.sess, provided, kind, false, None); + Self::generic_arg_mismatch_err(tcx, provided_arg, param, false, None); } break; diff --git a/src/test/ui/const-generics/suggest_const_for_array.rs b/src/test/ui/const-generics/suggest_const_for_array.rs new file mode 100644 index 00000000000..f3e5a3186cd --- /dev/null +++ b/src/test/ui/const-generics/suggest_const_for_array.rs @@ -0,0 +1,10 @@ +#![crate_type = "lib"] + +fn example() {} + +fn other() { + example::<[usize; 3]>(); + //~^ ERROR type provided when a const + example::<[usize; 4+5]>(); + //~^ ERROR type provided when a const +} diff --git a/src/test/ui/const-generics/suggest_const_for_array.stderr b/src/test/ui/const-generics/suggest_const_for_array.stderr new file mode 100644 index 00000000000..a617bf2bb0d --- /dev/null +++ b/src/test/ui/const-generics/suggest_const_for_array.stderr @@ -0,0 +1,15 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:6:13 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:8:13 + | +LL | example::<[usize; 4+5]>(); + | ^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4+5 }` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. From 6002e78392541b61055f1fd32cbf310ac4409a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Mon, 4 Jan 2021 16:09:59 +0100 Subject: [PATCH 11/12] Builder: Warn if test file does not exist --- src/bootstrap/test.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 33e252a63c9..5caadca1dad 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1126,7 +1126,19 @@ note: if you're sure you want to do this, please open an issue as to why. In the Ok(path) => path, Err(_) => p, }) - .filter(|p| p.starts_with(suite_path) && (p.is_dir() || p.is_file())) + .filter(|p| p.starts_with(suite_path)) + .filter(|p| { + let exists = p.is_dir() || p.is_file(); + if !exists { + if let Some(p) = p.to_str() { + builder.info(&format!( + "Warning: Skipping \"{}\": not a regular file or directory", + p + )); + } + } + exists + }) .filter_map(|p| { // Since test suite paths are themselves directories, if we don't // specify a directory or file, we'll get an empty string here From 92d1b390438e1aefef6532463ddccc27ec3b2dda Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 Jan 2021 17:15:57 +0100 Subject: [PATCH 12/12] make sure that promoteds which fail to evaluate in dead const code behave correctly --- src/test/ui/consts/promotion.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/test/ui/consts/promotion.rs b/src/test/ui/consts/promotion.rs index e6f5c3d27ca..b6e7127a9b7 100644 --- a/src/test/ui/consts/promotion.rs +++ b/src/test/ui/consts/promotion.rs @@ -4,12 +4,23 @@ fn foo(_: &'static [&'static str]) {} fn bar(_: &'static [&'static str; 3]) {} -fn baz_i32(_: &'static i32) {} -fn baz_u32(_: &'static u32) {} +const fn baz_i32(_: &'static i32) {} +const fn baz_u32(_: &'static u32) {} + +const fn fail() -> i32 { 1/0 } +const C: i32 = { + // Promoted that fails to evaluate in dead code -- this must work + // (for backwards compatibility reasons). + if false { + baz_i32(&fail()); + } + 42 +}; fn main() { foo(&["a", "b", "c"]); bar(&["d", "e", "f"]); + assert_eq!(C, 42); // make sure that these do not cause trouble despite overflowing baz_u32(&(0-1));