diff --git a/Cargo.lock b/Cargo.lock index a094cd78429c6..633eeb3d3bd8e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3054,7 +3054,6 @@ name = "racer" version = "2.2.2" dependencies = [ "bitflags", - "clap 2.34.0", "derive_more", "env_logger 0.7.1", "humantime 2.0.1", @@ -3278,7 +3277,7 @@ dependencies = [ "difference", "env_logger 0.9.0", "futures 0.3.19", - "heck 0.3.1", + "heck 0.4.0", "home", "itertools", "jsonrpc-core", diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index c41a41980eb0b..8c1e865762ccd 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1064,11 +1064,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { dst: &'ll Value, cmp: &'ll Value, src: &'ll Value, - order: rustc_codegen_ssa::common::AtomicOrdering, + mut order: rustc_codegen_ssa::common::AtomicOrdering, failure_order: rustc_codegen_ssa::common::AtomicOrdering, weak: bool, ) -> &'ll Value { let weak = if weak { llvm::True } else { llvm::False }; + if llvm_util::get_version() < (13, 0, 0) { + use rustc_codegen_ssa::common::AtomicOrdering::*; + // Older llvm has the pre-C++17 restriction on + // success and failure memory ordering, + // requiring the former to be at least as strong as the latter. + // So, for llvm 12, we upgrade the success ordering to a stronger + // one if necessary. + match (order, failure_order) { + (Relaxed, Acquire) => order = Acquire, + (Release, Acquire) => order = AcquireRelease, + (_, SequentiallyConsistent) => order = SequentiallyConsistent, + _ => {} + } + } unsafe { llvm::LLVMRustBuildAtomicCmpXchg( self.llbuilder, diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 200253d575599..c56909ba18b14 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -226,7 +226,7 @@ pub trait PrettyPrinter<'tcx>: value.as_ref().skip_binder().print(self) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: F, @@ -773,18 +773,18 @@ pub trait PrettyPrinter<'tcx>: def_id: DefId, substs: &'tcx ty::List>, ) -> Result { - define_scoped_cx!(self); + let tcx = self.tcx(); // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx().bound_explicit_item_bounds(def_id); + let bounds = tcx.bound_explicit_item_bounds(def_id); let mut traits = FxIndexMap::default(); let mut fn_traits = FxIndexMap::default(); let mut is_sized = false; for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) { - let predicate = predicate.subst(self.tcx(), substs); + let predicate = predicate.subst(tcx, substs); let bound_predicate = predicate.kind(); match bound_predicate.skip_binder() { @@ -792,7 +792,7 @@ pub trait PrettyPrinter<'tcx>: let trait_ref = bound_predicate.rebind(pred.trait_ref); // Don't print + Sized, but rather + ?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { + if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { is_sized = true; continue; } @@ -801,7 +801,7 @@ pub trait PrettyPrinter<'tcx>: } ty::PredicateKind::Projection(pred) => { let proj_ref = bound_predicate.rebind(pred); - let trait_ref = proj_ref.required_poly_trait_ref(self.tcx()); + let trait_ref = proj_ref.required_poly_trait_ref(tcx); // Projection type entry -- the def-id for naming, and the ty. let proj_ty = (proj_ref.projection_def_id(), proj_ref.term()); @@ -817,148 +817,155 @@ pub trait PrettyPrinter<'tcx>: } } + write!(self, "impl ")?; + let mut first = true; // Insert parenthesis around (Fn(A, B) -> C) if the opaque ty has more than one other trait let paren_needed = fn_traits.len() > 1 || traits.len() > 0 || !is_sized; - p!("impl"); - for (fn_once_trait_ref, entry) in fn_traits { - // Get the (single) generic ty (the args) of this FnOnce trait ref. - let generics = self.tcx().generics_of(fn_once_trait_ref.def_id()); - let args = - generics.own_substs_no_defaults(self.tcx(), fn_once_trait_ref.skip_binder().substs); - - match (entry.return_ty, args[0].expect_ty()) { - // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded - // a return type. - (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { - let name = if entry.fn_trait_ref.is_some() { - "Fn" - } else if entry.fn_mut_trait_ref.is_some() { - "FnMut" - } else { - "FnOnce" - }; + write!(self, "{}", if first { "" } else { " + " })?; + write!(self, "{}", if paren_needed { "(" } else { "" })?; - p!( - write("{}", if first { " " } else { " + " }), - write("{}{}(", if paren_needed { "(" } else { "" }, name) - ); + self = self.wrap_binder(&fn_once_trait_ref, |trait_ref, mut cx| { + define_scoped_cx!(cx); + // Get the (single) generic ty (the args) of this FnOnce trait ref. + let generics = tcx.generics_of(trait_ref.def_id); + let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); + + match (entry.return_ty, args[0].expect_ty()) { + // We can only print `impl Fn() -> ()` if we have a tuple of args and we recorded + // a return type. + (Some(return_ty), arg_tys) if matches!(arg_tys.kind(), ty::Tuple(_)) => { + let name = if entry.fn_trait_ref.is_some() { + "Fn" + } else if entry.fn_mut_trait_ref.is_some() { + "FnMut" + } else { + "FnOnce" + }; - for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { - if idx > 0 { - p!(", "); + p!(write("{}(", name)); + + for (idx, ty) in arg_tys.tuple_fields().iter().enumerate() { + if idx > 0 { + p!(", "); + } + p!(print(ty)); } - p!(print(ty)); - } - p!(")"); - if let Term::Ty(ty) = return_ty.skip_binder() { - if !ty.is_unit() { - p!(" -> ", print(return_ty)); + p!(")"); + if let Term::Ty(ty) = return_ty.skip_binder() { + if !ty.is_unit() { + p!(" -> ", print(return_ty)); + } } - } - p!(write("{}", if paren_needed { ")" } else { "" })); + p!(write("{}", if paren_needed { ")" } else { "" })); - first = false; - } - // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the - // trait_refs we collected in the OpaqueFnEntry as normal trait refs. - _ => { - if entry.has_fn_once { - traits.entry(fn_once_trait_ref).or_default().extend( - // Group the return ty with its def id, if we had one. - entry - .return_ty - .map(|ty| (self.tcx().lang_items().fn_once_output().unwrap(), ty)), - ); - } - if let Some(trait_ref) = entry.fn_mut_trait_ref { - traits.entry(trait_ref).or_default(); + first = false; } - if let Some(trait_ref) = entry.fn_trait_ref { - traits.entry(trait_ref).or_default(); + // If we got here, we can't print as a `impl Fn(A, B) -> C`. Just record the + // trait_refs we collected in the OpaqueFnEntry as normal trait refs. + _ => { + if entry.has_fn_once { + traits.entry(fn_once_trait_ref).or_default().extend( + // Group the return ty with its def id, if we had one. + entry + .return_ty + .map(|ty| (tcx.lang_items().fn_once_output().unwrap(), ty)), + ); + } + if let Some(trait_ref) = entry.fn_mut_trait_ref { + traits.entry(trait_ref).or_default(); + } + if let Some(trait_ref) = entry.fn_trait_ref { + traits.entry(trait_ref).or_default(); + } } } - } + + Ok(cx) + })?; } // Print the rest of the trait types (that aren't Fn* family of traits) for (trait_ref, assoc_items) in traits { - p!( - write("{}", if first { " " } else { " + " }), - print(trait_ref.skip_binder().print_only_trait_name()) - ); + write!(self, "{}", if first { "" } else { " + " })?; + + self = self.wrap_binder(&trait_ref, |trait_ref, mut cx| { + define_scoped_cx!(cx); + p!(print(trait_ref.print_only_trait_name())); - let generics = self.tcx().generics_of(trait_ref.def_id()); - let args = generics.own_substs_no_defaults(self.tcx(), trait_ref.skip_binder().substs); + let generics = tcx.generics_of(trait_ref.def_id); + let args = generics.own_substs_no_defaults(tcx, trait_ref.substs); - if !args.is_empty() || !assoc_items.is_empty() { - let mut first = true; + if !args.is_empty() || !assoc_items.is_empty() { + let mut first = true; - for ty in args { - if first { - p!("<"); - first = false; - } else { - p!(", "); + for ty in args { + if first { + p!("<"); + first = false; + } else { + p!(", "); + } + p!(print(ty)); } - p!(print(trait_ref.rebind(*ty))); - } - for (assoc_item_def_id, term) in assoc_items { - // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, - // unless we can find out what generator return type it comes from. - let term = if let Some(ty) = term.skip_binder().ty() - && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind() - && Some(*item_def_id) == self.tcx().lang_items().generator_return() - { - if let ty::Generator(_, substs, _) = substs.type_at(0).kind() { - let return_ty = substs.as_generator().return_ty(); - if !return_ty.is_ty_infer() { - return_ty.into() + for (assoc_item_def_id, term) in assoc_items { + // Skip printing `<[generator@] as Generator<_>>::Return` from async blocks, + // unless we can find out what generator return type it comes from. + let term = if let Some(ty) = term.skip_binder().ty() + && let ty::Projection(ty::ProjectionTy { item_def_id, substs }) = ty.kind() + && Some(*item_def_id) == tcx.lang_items().generator_return() + { + if let ty::Generator(_, substs, _) = substs.type_at(0).kind() { + let return_ty = substs.as_generator().return_ty(); + if !return_ty.is_ty_infer() { + return_ty.into() + } else { + continue; + } } else { continue; } } else { - continue; - } - } else { - term.skip_binder() - }; + term.skip_binder() + }; - if first { - p!("<"); - first = false; - } else { - p!(", "); - } + if first { + p!("<"); + first = false; + } else { + p!(", "); + } - p!(write("{} = ", self.tcx().associated_item(assoc_item_def_id).name)); + p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name)); - match term { - Term::Ty(ty) => { - p!(print(ty)) - } - Term::Const(c) => { - p!(print(c)); - } - }; - } + match term { + Term::Ty(ty) => { + p!(print(ty)) + } + Term::Const(c) => { + p!(print(c)); + } + }; + } - if !first { - p!(">"); + if !first { + p!(">"); + } } - } - first = false; + first = false; + Ok(cx) + })?; } if !is_sized { - p!(write("{}?Sized", if first { " " } else { " + " })); + write!(self, "{}?Sized", if first { "" } else { " + " })?; } else if first { - p!(" Sized"); + write!(self, "Sized")?; } Ok(self) @@ -1869,7 +1876,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self.pretty_in_binder(value) } - fn wrap_binder Result>( + fn wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, @@ -2256,7 +2263,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { Ok(inner) } - pub fn pretty_wrap_binder Result>( + pub fn pretty_wrap_binder Result>( self, value: &ty::Binder<'tcx, T>, f: C, diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index 5684979eab777..79a13ce2fcac9 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -994,6 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, rcvr_ty, item_name, + args.map(|args| args.len()), source, out_of_scope_traits, &unsatisfied_predicates, @@ -1732,6 +1733,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, rcvr_ty: Ty<'tcx>, item_name: Ident, + inputs_len: Option, source: SelfSource<'tcx>, valid_out_of_scope_traits: Vec, unsatisfied_predicates: &[( @@ -1808,7 +1810,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not // implement the `AsRef` trait. let skip = skippable.contains(&did) - || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)); + || (("Pin::new" == *pre) && (sym::as_ref == item_name.name)) + || inputs_len.map_or(false, |inputs_len| pick.item.kind == ty::AssocKind::Fn && self.tcx.fn_sig(pick.item.def_id).skip_binder().inputs().len() != inputs_len); // Make sure the method is defined for the *actual* receiver: we don't // want to treat `Box` as a receiver if it only works because of // an autoderef to `&self` diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 329bb68672ee6..ea410849694ca 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -150,6 +150,19 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) { for binary in ["llvm-config", "FileCheck"] { builder.fix_bin_or_dylib(&llvm_root.join("bin").join(binary)); } + + // Update the timestamp of llvm-config to force rustc_llvm to be + // rebuilt. This is a hacky workaround for a deficiency in Cargo where + // the rerun-if-changed directive doesn't handle changes very well. + // https://github.com/rust-lang/cargo/issues/10791 + // Cargo only compares the timestamp of the file relative to the last + // time `rustc_llvm` build script ran. However, the timestamps of the + // files in the tarball are in the past, so it doesn't trigger a + // rebuild. + let now = filetime::FileTime::from_system_time(std::time::SystemTime::now()); + let llvm_config = llvm_root.join("bin/llvm-config"); + t!(filetime::set_file_times(&llvm_config, now, now)); + let llvm_lib = llvm_root.join("lib"); for entry in t!(fs::read_dir(&llvm_lib)) { let lib = t!(entry).path(); diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 8e0521d9ad6a1..5b37ecf19da94 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -629,11 +629,11 @@ kbd { color: #fff; border-bottom-color: #5c6773; } -div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, div.name:hover { background-color: #14191f; color: #ffb44c; } -div.files > .selected { +#source-sidebar div.files > .selected { background-color: #14191f; color: #ffb44c; } diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 071ad006ed350..ffb59f7762b6d 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -499,10 +499,10 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, div.name:hover { background-color: #444; } -div.files > .selected { +#source-sidebar div.files > .selected { background-color: #333; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 5c3789bf4630a..ba798ee2a0eea 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -483,10 +483,10 @@ kbd { #source-sidebar > .title { border-bottom-color: #ccc; } -div.files > a:hover, div.name:hover { +#source-sidebar div.files > a:hover, div.name:hover { background-color: #E0E0E0; } -div.files > .selected { +#source-sidebar div.files > .selected { background-color: #fff; } diff --git a/src/test/rustdoc-gui/sidebar-source-code-display.goml b/src/test/rustdoc-gui/sidebar-source-code-display.goml index 0066a38eaa540..8f53e8627ee1c 100644 --- a/src/test/rustdoc-gui/sidebar-source-code-display.goml +++ b/src/test/rustdoc-gui/sidebar-source-code-display.goml @@ -17,3 +17,102 @@ assert-css: (".sidebar > *:not(#sidebar-toggle)", {"visibility": "hidden", "opac click: "#sidebar-toggle" // Because of the transition CSS, we check by using `wait-for-css` instead of `assert-css`. wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) + +// Now we check the display of the sidebar items. +show-text: true + +// First we start with the light theme. +local-storage: {"rustdoc-theme": "light", "rustdoc-use-system-theme": "false"} +reload: +// Waiting for the sidebar to be displayed... +wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +assert-css: ( + "#source-sidebar .expand + .children a.selected", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(255, 255, 255)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(0, 0, 0)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children .folders .name" +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(0, 0, 0)", "background-color": "rgb(224, 224, 224)"}, +) + +// Now with the dark theme. +local-storage: {"rustdoc-theme": "dark", "rustdoc-use-system-theme": "false"} +reload: +// Waiting for the sidebar to be displayed... +wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +assert-css: ( + "#source-sidebar .expand + .children a.selected", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(51, 51, 51)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(221, 221, 221)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children .folders .name" +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(221, 221, 221)", "background-color": "rgb(68, 68, 68)"}, +) + +// And finally with the ayu theme. +local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"} +reload: +// Waiting for the sidebar to be displayed... +wait-for-css: ("#sidebar-toggle", {"visibility": "visible", "opacity": 1}) +assert-css: ( + "#source-sidebar .expand + .children a.selected", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children > .files a:not(.selected)" +assert-css: ( + "#source-sidebar .expand + .children > .files a:not(.selected)", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) +// Without hover. +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(197, 197, 197)", "background-color": "rgba(0, 0, 0, 0)"}, +) +// With hover. +move-cursor-to: "#source-sidebar .expand + .children .folders .name" +assert-css: ( + "#source-sidebar .expand + .children .folders .name", + {"color": "rgb(255, 180, 76)", "background-color": "rgb(20, 25, 31)"}, +) diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 43b7cb8cece36..e9b76b19dc407 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -22,7 +22,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { LL | | LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl for<'r, 's, 't0> Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:23:16 | diff --git a/src/test/ui/backtrace.rs b/src/test/ui/backtrace.rs index 05ccfcb5060cb..e2ac43fffc9ef 100644 --- a/src/test/ui/backtrace.rs +++ b/src/test/ui/backtrace.rs @@ -44,6 +44,7 @@ fn expected(fn_name: &str) -> String { format!(" backtrace::{}", fn_name) } +#[cfg(not(panic = "abort"))] fn contains_verbose_expected(s: &str, fn_name: &str) -> bool { // HACK(eddyb) work around the fact that verbosely demangled stack traces // (from `RUST_BACKTRACE=full`, or, as is the case here, panic-in-panic) diff --git a/src/test/ui/impl-trait/printing-binder.rs b/src/test/ui/impl-trait/printing-binder.rs new file mode 100644 index 0000000000000..273b5dcdb0985 --- /dev/null +++ b/src/test/ui/impl-trait/printing-binder.rs @@ -0,0 +1,14 @@ +trait Trait<'a> {} +impl Trait<'_> for T {} +fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + +fn whatever2() -> impl for<'c> Fn(&'c ()) { + |_: &()| {} +} + +fn main() { + let x: u32 = whatever(); + //~^ ERROR mismatched types + let x2: u32 = whatever2(); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/impl-trait/printing-binder.stderr b/src/test/ui/impl-trait/printing-binder.stderr new file mode 100644 index 0000000000000..5ffec8af10289 --- /dev/null +++ b/src/test/ui/impl-trait/printing-binder.stderr @@ -0,0 +1,31 @@ +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:10:18 + | +LL | fn whatever() -> impl for<'a> Trait<'a> + for<'b> Trait<'b> {} + | ------------------------------------------ the found opaque type +... +LL | let x: u32 = whatever(); + | --- ^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'a> Trait<'a> + for<'b> Trait<'b>` + +error[E0308]: mismatched types + --> $DIR/printing-binder.rs:12:19 + | +LL | fn whatever2() -> impl for<'c> Fn(&'c ()) { + | ----------------------- the found opaque type +... +LL | let x2: u32 = whatever2(); + | --- ^^^^^^^^^^^ expected `u32`, found opaque type + | | + | expected due to this + | + = note: expected type `u32` + found opaque type `impl for<'c> Fn(&'c ())` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs new file mode 100644 index 0000000000000..acb897571d64e --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.rs @@ -0,0 +1,15 @@ +// https://github.com/rust-lang/rust/issues/96834 +// +// This test case verifies that rustc does not make an unhelpful suggestion: +// +// help: consider wrapping the receiver expression with the appropriate type +// | +// 14 | Pin::new(&mut a).set(0, 3); +// | +++++++++++++ + +// +// We can tell that it isn't helpful, because `Pin::set` takes two parameters (including +// the receiver), but the function call on line 14 supplies three. +fn main() { + let mut a = [0u8; 1]; + a.set(0, 3); //~ERROR +} diff --git a/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr new file mode 100644 index 0000000000000..677aa031bf7d6 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-pin-array-dot-set.stderr @@ -0,0 +1,9 @@ +error[E0599]: no method named `set` found for array `[u8; 1]` in the current scope + --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7 + | +LL | a.set(0, 3); + | ^^^ help: there is an associated function with a similar name: `get` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/tools/rls b/src/tools/rls index 27f4044df03d1..ece09b88c0365 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 27f4044df03d15c7c38a483c3e4635cf4f51807d +Subproject commit ece09b88c0365947af79c0ffdeea02bc6c1eec25 diff --git a/x.py b/x.py index 4f64ea9fae8b8..0289056fdcb16 100755 --- a/x.py +++ b/x.py @@ -1,5 +1,25 @@ -#!/usr/bin/env python +#!/usr/bin/env bash +# Modern Linux and macOS systems commonly only have a thing called `python3` and +# not `python`, while Windows commonly does not have `python3`, so we cannot +# directly use python in the shebang and have it consistently work. Instead we +# embed some bash to look for a python to run the rest of the script. +# +# On Windows, `py -3` sometimes works. We need to try it first because `python3` +# sometimes tries to launch the app store on Windows. +'''': +for PYTHON in "py -3" python3 python python2; do + if command -v $PYTHON >/dev/null; then + exec $PYTHON "$0" "$@" + break + fi +done +echo "$0: error: did not find python installed" >&2 +exit 1 +''' + +# The rest of this file is Python. +# # This file is only a "symlink" to bootstrap.py, all logic should go there. import os @@ -7,11 +27,12 @@ # If this is python2, check if python3 is available and re-execute with that # interpreter. +# +# `./x.py` would not normally benefit from this because the bash above tries +# python3 before 2, but this matters if someone ran `python x.py` and their +# system's `python` is python2. if sys.version_info.major < 3: try: - # On Windows, `py -3` sometimes works. - # Try this first, because 'python3' sometimes tries to launch the app - # store on Windows os.execvp("py", ["py", "-3"] + sys.argv) except OSError: try: