diff --git a/RELEASES.md b/RELEASES.md index 9de9eb67bba1b..5bc302305c71c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -47,8 +47,8 @@ Stabilized APIs - [`core::num::Saturating`](https://doc.rust-lang.org/stable/std/num/struct.Saturating.html) - [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStdout%3E-for-Stdio) - [`impl From for std::process::Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) -- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) -- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CStderr%3E-for-Stdio) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedHandle%3E-for-ChildStderr) +- [`impl From for std::process::Child{Stdin, Stdout, Stderr}`](https://doc.rust-lang.org/stable/std/process/struct.ChildStderr.html#impl-From%3COwnedFd%3E-for-ChildStderr) - [`std::ffi::OsString::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.from_encoded_bytes_unchecked) - [`std::ffi::OsString::into_encoded_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.into_encoded_bytes) - [`std::ffi::OsStr::from_encoded_bytes_unchecked`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.from_encoded_bytes_unchecked) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index eaf5e938d3cf9..6c99044d0aa4e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2191,7 +2191,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(field_name) = find_best_match_for_name(&available_field_names, field.ident.name, None) { - err.span_suggestion( + err.span_label(field.ident.span, "unknown field"); + err.span_suggestion_verbose( field.ident.span, "a field with a similar name exists", field_name, @@ -2420,35 +2421,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, ) { let Some(output_ty) = self.get_impl_future_output_ty(ty) else { + err.span_label(field_ident.span, "unknown field"); return; }; - let mut add_label = true; - if let ty::Adt(def, _) = output_ty.kind() { - // no field access on enum type - if !def.is_enum() { - if def - .non_enum_variant() - .fields - .iter() - .any(|field| field.ident(self.tcx) == field_ident) - { - add_label = false; - err.span_label( - field_ident.span, - "field not available in `impl Future`, but it is available in its `Output`", - ); - err.span_suggestion_verbose( - base.span.shrink_to_hi(), - "consider `await`ing on the `Future` and access the field of its `Output`", - ".await", - Applicability::MaybeIncorrect, - ); - } - } + let ty::Adt(def, _) = output_ty.kind() else { + err.span_label(field_ident.span, "unknown field"); + return; + }; + // no field access on enum type + if def.is_enum() { + err.span_label(field_ident.span, "unknown field"); + return; } - if add_label { - err.span_label(field_ident.span, format!("field not found in `{ty}`")); + if !def.non_enum_variant().fields.iter().any(|field| field.ident(self.tcx) == field_ident) { + err.span_label(field_ident.span, "unknown field"); + return; } + err.span_label( + field_ident.span, + "field not available in `impl Future`, but it is available in its `Output`", + ); + err.span_suggestion_verbose( + base.span.shrink_to_hi(), + "consider `await`ing on the `Future` and access the field of its `Output`", + ".await", + Applicability::MaybeIncorrect, + ); } fn ban_nonexisting_field( @@ -2471,16 +2469,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::RawPtr(..) => { self.suggest_first_deref_field(&mut err, expr, base, ident); } - ty::Adt(def, _) if !def.is_enum() => { - self.suggest_fields_on_recordish(&mut err, expr, def, ident); - } ty::Param(param_ty) => { + err.span_label(ident.span, "unknown field"); self.point_at_param_definition(&mut err, param_ty); } ty::Alias(ty::Opaque, _) => { self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); } - _ => {} + _ => { + err.span_label(ident.span, "unknown field"); + } } self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { @@ -2633,34 +2631,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(param_span, format!("type parameter '{param_name}' declared here")); } - fn suggest_fields_on_recordish( - &self, - err: &mut Diagnostic, - expr: &hir::Expr<'_>, - def: ty::AdtDef<'tcx>, - field: Ident, - ) { - let available_field_names = self.available_field_names(def.non_enum_variant(), expr, &[]); - if let Some(suggested_field_name) = - find_best_match_for_name(&available_field_names, field.name, None) - { - err.span_suggestion( - field.span, - "a field with a similar name exists", - suggested_field_name, - Applicability::MaybeIncorrect, - ); - } else { - err.span_label(field.span, "unknown field"); - if !available_field_names.is_empty() { - err.note(format!( - "available fields are: {}", - self.name_series_display(available_field_names), - )); - } - } - } - fn maybe_suggest_array_indexing( &self, err: &mut Diagnostic, @@ -2669,6 +2639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: Ident, len: ty::Const<'tcx>, ) { + err.span_label(field.span, "unknown field"); if let (Some(len), Ok(user_index)) = (len.try_eval_target_usize(self.tcx, self.param_env), field.as_str().parse::()) && let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) @@ -2691,6 +2662,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { base: &hir::Expr<'_>, field: Ident, ) { + err.span_label(field.span, "unknown field"); if let Ok(base) = self.tcx.sess.source_map().span_to_snippet(base.span) { let msg = format!("`{base}` is a raw pointer; try dereferencing it"); let suggestion = format!("(*{base}).{field}"); @@ -2709,7 +2681,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = type_error_struct!( self.tcx().sess, - field.span, + span, expr_t, E0609, "no field `{field}` on type `{expr_t}`", @@ -2717,10 +2689,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // try to add a suggestion in case the field is a nested field of a field of the Adt let mod_id = self.tcx.parent_module(id).to_def_id(); - if let Some((fields, args)) = - self.get_field_candidates_considering_privacy(span, expr_t, mod_id) + let (ty, unwrap) = if let ty::Adt(def, args) = expr_t.kind() + && (self.tcx.is_diagnostic_item(sym::Result, def.did()) + || self.tcx.is_diagnostic_item(sym::Option, def.did())) + && let Some(arg) = args.get(0) + && let Some(ty) = arg.as_type() { - let candidate_fields: Vec<_> = fields + (ty, "unwrap().") + } else { + (expr_t, "") + }; + for (found_fields, args) in + self.get_field_candidates_considering_privacy(span, ty, mod_id, id) + { + let field_names = found_fields.iter().map(|field| field.name).collect::>(); + let candidate_fields: Vec<_> = found_fields + .into_iter() .filter_map(|candidate_field| { self.check_for_nested_field_satisfying( span, @@ -2729,15 +2713,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args, vec![], mod_id, + id, ) }) .map(|mut field_path| { field_path.pop(); field_path .iter() - .map(|id| id.name.to_ident_string()) - .collect::>() - .join(".") + .map(|id| format!("{}.", id.name.to_ident_string())) + .collect::() }) .collect::>(); @@ -2750,9 +2734,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if len > 1 { "some" } else { "one" }, if len > 1 { "have" } else { "has" }, ), - candidate_fields.iter().map(|path| format!("{path}.")), + candidate_fields.iter().map(|path| format!("{unwrap}{path}")), Applicability::MaybeIncorrect, ); + } else { + if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) { + err.span_suggestion_verbose( + field.span, + "a field with a similar name exists", + format!("{unwrap}{}", field_name), + Applicability::MaybeIncorrect, + ); + } else if !field_names.is_empty() { + let is = if field_names.len() == 1 { " is" } else { "s are" }; + err.note(format!( + "available field{is}: {}", + self.name_series_display(field_names), + )); + } } } err @@ -2781,33 +2780,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, base_ty: Ty<'tcx>, mod_id: DefId, - ) -> Option<(impl Iterator + 'tcx, GenericArgsRef<'tcx>)> { + hir_id: hir::HirId, + ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); - for (base_t, _) in self.autoderef(span, base_ty) { - match base_t.kind() { - ty::Adt(base_def, args) if !base_def.is_enum() => { - let tcx = self.tcx; - let fields = &base_def.non_enum_variant().fields; - // Some struct, e.g. some that impl `Deref`, have all private fields - // because you're expected to deref them to access the _real_ fields. - // This, for example, will help us suggest accessing a field through a `Box`. - if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { - continue; + self.autoderef(span, base_ty) + .filter_map(move |(base_t, _)| { + match base_t.kind() { + ty::Adt(base_def, args) if !base_def.is_enum() => { + let tcx = self.tcx; + let fields = &base_def.non_enum_variant().fields; + // Some struct, e.g. some that impl `Deref`, have all private fields + // because you're expected to deref them to access the _real_ fields. + // This, for example, will help us suggest accessing a field through a `Box`. + if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { + return None; + } + return Some(( + fields + .iter() + .filter(move |field| { + field.vis.is_accessible_from(mod_id, tcx) + && self.is_field_suggestable(field, hir_id, span) + }) + // For compile-time reasons put a limit on number of fields we search + .take(100) + .collect::>(), + *args, + )); } - return Some(( - fields - .iter() - .filter(move |field| field.vis.is_accessible_from(mod_id, tcx)) - // For compile-time reasons put a limit on number of fields we search - .take(100), - args, - )); + _ => None, } - _ => {} - } - } - None + }) + .collect() } /// This method is called after we have encountered a missing field error to recursively @@ -2820,6 +2825,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { subst: GenericArgsRef<'tcx>, mut field_path: Vec, mod_id: DefId, + hir_id: HirId, ) -> Option> { debug!( "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}", @@ -2835,20 +2841,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let field_ty = candidate_field.ty(self.tcx, subst); if matches(candidate_field, field_ty) { return Some(field_path); - } else if let Some((nested_fields, subst)) = - self.get_field_candidates_considering_privacy(span, field_ty, mod_id) - { - // recursively search fields of `candidate_field` if it's a ty::Adt - for field in nested_fields { - if let Some(field_path) = self.check_for_nested_field_satisfying( - span, - matches, - field, - subst, - field_path.clone(), - mod_id, - ) { - return Some(field_path); + } else { + for (nested_fields, subst) in + self.get_field_candidates_considering_privacy(span, field_ty, mod_id, hir_id) + { + // recursively search fields of `candidate_field` if it's a ty::Adt + for field in nested_fields { + if let Some(field_path) = self.check_for_nested_field_satisfying( + span, + matches, + field, + subst, + field_path.clone(), + mod_id, + hir_id, + ) { + return Some(field_path); + } } } } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 804d92a498ebb..6956778f974c1 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -1983,69 +1983,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: Ident, return_type: Option>, ) { - if let SelfSource::MethodCall(expr) = source - && let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id() - && let Some((fields, args)) = - self.get_field_candidates_considering_privacy(span, actual, mod_id) - { - let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); + if let SelfSource::MethodCall(expr) = source { + let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); + for (fields, args) in + self.get_field_candidates_considering_privacy(span, actual, mod_id, expr.hir_id) + { + let call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id)); - let lang_items = self.tcx.lang_items(); - let never_mention_traits = [ - lang_items.clone_trait(), - lang_items.deref_trait(), - lang_items.deref_mut_trait(), - self.tcx.get_diagnostic_item(sym::AsRef), - self.tcx.get_diagnostic_item(sym::AsMut), - self.tcx.get_diagnostic_item(sym::Borrow), - self.tcx.get_diagnostic_item(sym::BorrowMut), - ]; - let candidate_fields: Vec<_> = fields - .filter_map(|candidate_field| { - self.check_for_nested_field_satisfying( - span, - &|_, field_ty| { - self.lookup_probe_for_diagnostic( - item_name, - field_ty, - call_expr, - ProbeScope::TraitsInScope, - return_type, - ) - .is_ok_and(|pick| { - !never_mention_traits - .iter() - .flatten() - .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id) - }) - }, - candidate_field, - args, - vec![], - mod_id, - ) - }) - .map(|field_path| { - field_path - .iter() - .map(|id| id.name.to_ident_string()) - .collect::>() - .join(".") - }) - .collect(); + let lang_items = self.tcx.lang_items(); + let never_mention_traits = [ + lang_items.clone_trait(), + lang_items.deref_trait(), + lang_items.deref_mut_trait(), + self.tcx.get_diagnostic_item(sym::AsRef), + self.tcx.get_diagnostic_item(sym::AsMut), + self.tcx.get_diagnostic_item(sym::Borrow), + self.tcx.get_diagnostic_item(sym::BorrowMut), + ]; + let candidate_fields: Vec<_> = fields + .iter() + .filter_map(|candidate_field| { + self.check_for_nested_field_satisfying( + span, + &|_, field_ty| { + self.lookup_probe_for_diagnostic( + item_name, + field_ty, + call_expr, + ProbeScope::TraitsInScope, + return_type, + ) + .is_ok_and(|pick| { + !never_mention_traits + .iter() + .flatten() + .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id) + }) + }, + candidate_field, + args, + vec![], + mod_id, + expr.hir_id, + ) + }) + .map(|field_path| { + field_path + .iter() + .map(|id| id.name.to_ident_string()) + .collect::>() + .join(".") + }) + .collect(); - let len = candidate_fields.len(); - if len > 0 { - err.span_suggestions( - item_name.span.shrink_to_lo(), - format!( - "{} of the expressions' fields {} a method of the same name", - if len > 1 { "some" } else { "one" }, - if len > 1 { "have" } else { "has" }, - ), - candidate_fields.iter().map(|path| format!("{path}.")), - Applicability::MaybeIncorrect, - ); + let len = candidate_fields.len(); + if len > 0 { + err.span_suggestions( + item_name.span.shrink_to_lo(), + format!( + "{} of the expressions' fields {} a method of the same name", + if len > 1 { "some" } else { "one" }, + if len > 1 { "have" } else { "has" }, + ), + candidate_fields.iter().map(|path| format!("{path}.")), + Applicability::MaybeIncorrect, + ); + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 7ca33ae41c0ce..4824df3f26062 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -397,7 +397,11 @@ fn impl_intersection_has_negative_obligation( ) -> bool { debug!("negative_impl(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id); - let ref infcx = tcx.infer_ctxt().intercrate(true).with_next_trait_solver(true).build(); + // N.B. We don't need to use intercrate mode here because we're trying to prove + // the *existence* of a negative goal, not the non-existence of a positive goal. + // Without this, we over-eagerly register coherence ambiguity candidates when + // impl candidates do exist. + let ref infcx = tcx.infer_ctxt().with_next_trait_solver(true).build(); let universe = infcx.universe(); let impl1_header = fresh_impl_header(infcx, impl1_def_id); @@ -542,14 +546,14 @@ fn try_prove_negated_where_clause<'tcx>( }; // FIXME(with_negative_coherence): the infcx has region contraints from equating - // the impl headers as requirements. Given that the only region constraints we - // get are involving inference regions in the root, it shouldn't matter, but - // still sus. + // the impl headers as requirements. // - // We probably should just throw away the region obligations registered up until - // now, or ideally use them as assumptions when proving the region obligations - // that we get from proving the negative predicate below. + // We ideally should use these region constraints as assumptions when proving + // the region obligations that we get from proving the negative predicate below. let ref infcx = root_infcx.fork(); + let _ = infcx.take_registered_region_obligations(); + let _ = infcx.take_and_reset_region_constraints(); + let ocx = ObligationCtxt::new(infcx); ocx.register_obligation(Obligation::new( diff --git a/config.example.toml b/config.example.toml index e5df28a49af6c..170856bd97dbd 100644 --- a/config.example.toml +++ b/config.example.toml @@ -42,18 +42,15 @@ change-id = 116881 # Unless you're developing for a target where Rust CI doesn't build a compiler # toolchain or changing LLVM locally, you probably want to leave this enabled. # -# Set this to `"if-available"` if you are not sure whether you're on a tier 1 -# target. All tier 1 targets are currently supported; -# -# We also currently only support this when building LLVM for the build triple. -# -# Set this to `"if-unchanged"` to only download if the llvm-project have not -# been modified. (If there are no changes or if built from tarball source, -# the logic is the same as "if-available") +# Set this to `"if-unchanged"` to download only if the llvm-project has not +# been modified. You can also use this if you are unsure whether you're on a +# tier 1 target. All tier 1 targets are currently supported. + +# Currently, we only support this when building LLVM for the build triple. # # Note that many of the LLVM options are not currently supported for # downloading. Currently only the "assertions" option can be toggled. -#download-ci-llvm = if rust.channel == "dev" { "if-available" } else { false } +#download-ci-llvm = if rust.channel == "dev" { "if-unchanged" } else { false } # Indicates whether the LLVM build is a Release or Debug build #optimize = true diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index e7110aebdea16..7fcf2ee358c46 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -95,7 +95,7 @@ use crate::fmt; use crate::panic::UnwindSafe; use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed}; use crate::sync::LazyLock; -use crate::sys_common::backtrace::{lock, output_filename}; +use crate::sys_common::backtrace::{lock, output_filename, set_image_base}; use crate::vec::Vec; /// A captured OS thread stack backtrace. @@ -327,6 +327,7 @@ impl Backtrace { let _lock = lock(); let mut frames = Vec::new(); let mut actual_start = None; + set_image_base(); unsafe { backtrace_rs::trace_unsynchronized(|frame| { frames.push(BacktraceFrame { diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 55aafc3db330a..6c7494a6a6ff9 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -507,6 +507,16 @@ impl Seek for BufReader { ) }) } + + /// Seeks relative to the current position. + /// + /// If the new position lies within the buffer, the buffer will not be + /// flushed, allowing for more efficient seeks. This method does not return + /// the location of the underlying reader, so the caller must track this + /// information themselves if it is required. + fn seek_relative(&mut self, offset: i64) -> io::Result<()> { + self.seek_relative(offset) + } } impl SizeHint for BufReader { diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 7d70a0bac24fd..ff5b4e76d440a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1957,6 +1957,36 @@ pub trait Seek { fn stream_position(&mut self) -> Result { self.seek(SeekFrom::Current(0)) } + + /// Seeks relative to the current position. + /// + /// This is equivalent to `self.seek(SeekFrom::Current(offset))` but + /// doesn't return the new position which can allow some implementations + /// such as [`BufReader`] to perform more efficient seeks. + /// + /// # Example + /// + /// ```no_run + /// #![feature(seek_seek_relative)] + /// use std::{ + /// io::{self, Seek}, + /// fs::File, + /// }; + /// + /// fn main() -> io::Result<()> { + /// let mut f = File::open("foo.txt")?; + /// f.seek_relative(10)?; + /// assert_eq!(f.stream_position()?, 10); + /// Ok(()) + /// } + /// ``` + /// + /// [`BufReader`]: crate::io::BufReader + #[unstable(feature = "seek_seek_relative", issue = "117374")] + fn seek_relative(&mut self, offset: i64) -> Result<()> { + self.seek(SeekFrom::Current(offset))?; + Ok(()) + } } /// Enumeration of possible methods to seek within an I/O object. diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 84e2c5d8d7f70..adfe721cfa9ad 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -64,6 +64,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: let mut first_omit = true; // Start immediately if we're not using a short backtrace. let mut start = print_fmt != PrintFmt::Short; + set_image_base(); backtrace_rs::trace_unsynchronized(|frame| { if print_fmt == PrintFmt::Short && idx > MAX_NB_FRAMES { return false; @@ -213,3 +214,14 @@ pub fn output_filename( } fmt::Display::fmt(&file.display(), fmt) } + +#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] +pub fn set_image_base() { + let image_base = crate::os::fortanix_sgx::mem::image_base(); + backtrace_rs::set_image_base(crate::ptr::invalid_mut(image_base as _)); +} + +#[cfg(not(all(target_vendor = "fortanix", target_env = "sgx")))] +pub fn set_image_base() { + // nothing to do for platforms other than SGX +} diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml index b98b13119e8ad..b27b524b873b7 100644 --- a/src/bootstrap/defaults/config.compiler.toml +++ b/src/bootstrap/defaults/config.compiler.toml @@ -17,4 +17,4 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml index f362c4111f107..087544397f5ea 100644 --- a/src/bootstrap/defaults/config.library.toml +++ b/src/bootstrap/defaults/config.library.toml @@ -13,4 +13,4 @@ lto = "off" [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml index 79424f28d27b7..6e6c366002792 100644 --- a/src/bootstrap/defaults/config.tools.toml +++ b/src/bootstrap/defaults/config.tools.toml @@ -21,4 +21,4 @@ compiler-docs = true [llvm] # Will download LLVM from CI if available on your platform. -download-ci-llvm = "if-available" +download-ci-llvm = "if-unchanged" diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 51e4195827fc6..c253dd2c6aad3 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1005,6 +1005,13 @@ pub fn rustc_cargo_env( .env("CFG_RELEASE_CHANNEL", &builder.config.channel) .env("CFG_VERSION", builder.rust_version()); + // Some tools like Cargo detect their own git information in build scripts. When omit-git-hash + // is enabled in config.toml, we pass this environment variable to tell build scripts to avoid + // detecting git information on their own. + if builder.config.omit_git_hash { + cargo.env("CFG_OMIT_GIT_HASH", "1"); + } + if let Some(backend) = builder.config.default_codegen_backend() { cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend); } diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 0a9175aa3ea5c..fa8b0b20cec45 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2113,6 +2113,8 @@ impl Config { match download_ci_llvm { None => self.channel == "dev" && llvm::is_ci_llvm_available(&self, asserts), Some(StringOrBool::Bool(b)) => b, + // FIXME: "if-available" is deprecated. Remove this block later (around mid 2024) + // to not break builds between the recent-to-old checkouts. Some(StringOrBool::String(s)) if s == "if-available" => { llvm::is_ci_llvm_available(&self, asserts) } diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs index 59bd52a94dc83..a8106ca8ff923 100644 --- a/src/bootstrap/src/tests/config.rs +++ b/src/bootstrap/src/tests/config.rs @@ -24,19 +24,19 @@ fn download_ci_llvm() { } let parse_llvm = |s| parse(s).llvm_from_ci; - let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\""); + let if_unchanged = parse_llvm("llvm.download-ci-llvm = \"if-unchanged\""); assert!(parse_llvm("llvm.download-ci-llvm = true")); assert!(!parse_llvm("llvm.download-ci-llvm = false")); - assert_eq!(parse_llvm(""), if_available); - assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available); + assert_eq!(parse_llvm(""), if_unchanged); + assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged); assert!(!parse_llvm("rust.channel = \"stable\"")); assert!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\"")); assert!(parse_llvm( - "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-available\"" + "llvm.assertions = true \r\n build.build = \"x86_64-unknown-linux-gnu\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" )); assert!(!parse_llvm( - "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-available\"" + "llvm.assertions = true \r\n build.build = \"aarch64-apple-darwin\" \r\n llvm.download-ci-llvm = \"if-unchanged\"" )); } diff --git a/src/ci/run.sh b/src/ci/run.sh index ce0dd6018af82..fa786c6c7e784 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -145,7 +145,7 @@ else # LLVM continuously on at least some builders to ensure it works, though. # (And PGO is its own can of worms). if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-available" + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-unchanged" else # When building for CI we want to use the static C++ Standard library # included with LLVM, since a dynamic libstdcpp may not be available. diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index cbb4d5765ca3f..77164ed4117a9 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -58,7 +58,7 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe" # Disable downloading CI LLVM on this builder; - # setting up clang-cl just above conflicts with the default if-available option. + # setting up clang-cl just above conflicts with the default if-unchanged option. ciCommandSetEnv NO_DOWNLOAD_CI_LLVM 1 fi diff --git a/src/tools/suggest-tests/src/lib.rs b/src/tools/suggest-tests/src/lib.rs index 44cd3c7f6a84d..1c1d9d0333ddb 100644 --- a/src/tools/suggest-tests/src/lib.rs +++ b/src/tools/suggest-tests/src/lib.rs @@ -33,13 +33,15 @@ pub fn get_suggestions>(modified_files: &[T]) -> Vec { let mut suggestions = Vec::new(); // static suggestions - for sug in STATIC_SUGGESTIONS.iter() { - let glob = Pattern::new(&sug.0).expect("Found invalid glob pattern!"); - - for file in modified_files { - if glob.matches(file.as_ref()) { - suggestions.extend_from_slice(&sug.1); - } + for (globs, sugs) in STATIC_SUGGESTIONS.iter() { + let globs = globs + .iter() + .map(|glob| Pattern::new(glob).expect("Found invalid glob pattern!")) + .collect::>(); + let matches_some_glob = |file: &str| globs.iter().any(|glob| glob.matches(file)); + + if modified_files.iter().map(AsRef::as_ref).any(matches_some_glob) { + suggestions.extend_from_slice(sugs); } } diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs index a84e78254f269..fbd265ea42a2e 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -2,23 +2,34 @@ use crate::{sug, Suggestion}; // FIXME: perhaps this could use `std::lazy` when it is stablizied macro_rules! static_suggestions { - ($( $glob:expr => [ $( $suggestion:expr ),* ] ),*) => { - pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy)>> - = ::once_cell::unsync::Lazy::new(|| vec![ $( ($glob, vec![ $($suggestion),* ]) ),*]); + ($( [ $( $glob:expr ),* $(,)? ] => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => { + pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy, Vec)>> + = ::once_cell::unsync::Lazy::new(|| vec![ $( (vec![ $($glob),* ], vec![ $($suggestion),* ]) ),*]); } } static_suggestions! { - "*.md" => [ - sug!("test", 0, ["linkchecker"]) + ["*.md"] => [ + sug!("test", 0, ["linkchecker"]), ], - "compiler/*" => [ + ["compiler/*"] => [ sug!("check"), - sug!("test", 1, ["tests/ui", "tests/run-make"]) + sug!("test", 1, ["tests/ui", "tests/run-make"]), ], - "src/librustdoc/*" => [ - sug!("test", 1, ["rustdoc"]) - ] + ["compiler/rustc_mir_transform/*"] => [ + sug!("test", 1, ["mir-opt"]), + ], + + [ + "compiler/rustc_mir_transform/src/coverage/*", + "compiler/rustc_codegen_llvm/src/coverageinfo/*", + ] => [ + sug!("test", 1, ["coverage"]), + ], + + ["src/librustdoc/*"] => [ + sug!("test", 1, ["rustdoc"]), + ], } diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs index 4919e0a051dcb..4a3195174df49 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.rs @@ -23,6 +23,7 @@ fn await_on_struct_similar() { let x = S { awai: 42 }; x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| HELP a field with a similar name exists //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP set `edition = "2021"` in `Cargo.toml` @@ -41,6 +42,7 @@ fn await_on_63533(x: Pin<&mut dyn Future>) { fn await_on_apit(x: impl Future) { x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP set `edition = "2021"` in `Cargo.toml` //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr index 409eb179e83a0..dd863ca541c9e 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await-cargo.stderr @@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: set `edition = "2021"` in `Cargo.toml` = note: for more on editions, read https://doc.rust-lang.org/edition-guide +help: a field with a similar name exists + | +LL | x.awai; + | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7 | LL | x.await; | ^^^^^ unknown field @@ -29,10 +33,10 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:43:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: set `edition = "2021"` in `Cargo.toml` diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.rs b/tests/ui/async-await/suggest-switching-edition-on-await.rs index 9852e8fc918fe..10e245796ee3c 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -21,6 +21,7 @@ fn await_on_struct_similar() { let x = S { awai: 42 }; x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| HELP a field with a similar name exists //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP pass `--edition 2021` to `rustc` @@ -39,6 +40,7 @@ fn await_on_63533(x: Pin<&mut dyn Future>) { fn await_on_apit(x: impl Future) { x.await; //~^ ERROR no field `await` on type + //~| NOTE unknown field //~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| HELP pass `--edition 2021` to `rustc` //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide diff --git a/tests/ui/async-await/suggest-switching-edition-on-await.stderr b/tests/ui/async-await/suggest-switching-edition-on-await.stderr index ef3334381b715..0ed256b059ffe 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -12,14 +12,18 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await.rs:22:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide +help: a field with a similar name exists + | +LL | x.awai; + | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await.rs:31:7 + --> $DIR/suggest-switching-edition-on-await.rs:32:7 | LL | x.await; | ^^^^^ unknown field @@ -29,10 +33,10 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await.rs:40:7 + --> $DIR/suggest-switching-edition-on-await.rs:41:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: pass `--edition 2021` to `rustc` diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs index 0e16d12a18114..3acf0d8d39ab9 100644 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs +++ b/tests/ui/coherence/coherence-negative-outlives-lifetimes.rs @@ -1,5 +1,5 @@ // revisions: stock with_negative_coherence -//[with_negative_coherence] known-bug: unknown +//[with_negative_coherence] check-pass #![feature(negative_impls)] #![cfg_attr(with_negative_coherence, feature(with_negative_coherence))] diff --git a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr b/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr deleted file mode 100644 index 097cc4e0fe3e6..0000000000000 --- a/tests/ui/coherence/coherence-negative-outlives-lifetimes.with_negative_coherence.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0119]: conflicting implementations of trait `MyTrait<'_>` for type `&_` - --> $DIR/coherence-negative-outlives-lifetimes.rs:14:1 - | -LL | impl<'a, T: MyPredicate<'a>> MyTrait<'a> for T {} - | ---------------------------------------------- first implementation here -LL | impl<'a, T> MyTrait<'a> for &'a T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/coherence-overlap-with-regions.rs b/tests/ui/coherence/coherence-overlap-with-regions.rs index 9945c8e6cfd7b..32f01f4180103 100644 --- a/tests/ui/coherence/coherence-overlap-with-regions.rs +++ b/tests/ui/coherence/coherence-overlap-with-regions.rs @@ -1,10 +1,4 @@ -// known-bug: unknown - -// This fails because we currently perform negative coherence in coherence mode. -// This means that when looking for a negative predicate, we also assemble a -// coherence-unknowable predicate. Since confirming the negative impl has region -// obligations, we don't prefer the impl over the unknowable predicate -// unconditionally and instead flounder. +// check-pass #![feature(negative_impls)] #![feature(rustc_attrs)] diff --git a/tests/ui/coherence/coherence-overlap-with-regions.stderr b/tests/ui/coherence/coherence-overlap-with-regions.stderr deleted file mode 100644 index fd25f0978bad2..0000000000000 --- a/tests/ui/coherence/coherence-overlap-with-regions.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0119]: conflicting implementations of trait `Bar` for type `&_` - --> $DIR/coherence-overlap-with-regions.rs:20:1 - | -LL | impl Bar for T {} - | ---------------------- first implementation here -LL | impl Bar for &T where T: 'static {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&_` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/negative-coherence-considering-regions.rs b/tests/ui/coherence/negative-coherence-considering-regions.rs index 597a597262846..e7dab91073dcf 100644 --- a/tests/ui/coherence/negative-coherence-considering-regions.rs +++ b/tests/ui/coherence/negative-coherence-considering-regions.rs @@ -1,5 +1,5 @@ // revisions: any_lt static_lt -//[static_lt] known-bug: unknown +//[static_lt] check-pass // This fails because we currently perform negative coherence in coherence mode. // This means that when looking for a negative predicate, we also assemble a diff --git a/tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr b/tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr deleted file mode 100644 index 87e7be2aa44a9..0000000000000 --- a/tests/ui/coherence/negative-coherence-considering-regions.static_lt.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0119]: conflicting implementations of trait `Bar` for type `&'static _` - --> $DIR/negative-coherence-considering-regions.rs:26:1 - | -LL | impl Bar for T where T: Foo {} - | ------------------------------ first implementation here -... -LL | impl Bar for &'static T {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `&'static _` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr new file mode 100644 index 0000000000000..34f3904443c31 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.explicit.stderr @@ -0,0 +1,19 @@ +error: conflicting implementations of trait `FnMarker` for type `fn(&_)` + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:21:1 + | +LL | impl FnMarker for fn(T) {} + | ------------------------------------------- first implementation here +LL | impl FnMarker for fn(&T) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(&_)` + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #56105 + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details +note: the lint level is defined here + --> $DIR/negative-coherence-placeholder-region-constraints-on-unification.rs:4:11 + | +LL | #![forbid(coherence_leak_check)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs new file mode 100644 index 0000000000000..26d9d84d8f0c9 --- /dev/null +++ b/tests/ui/coherence/negative-coherence-placeholder-region-constraints-on-unification.rs @@ -0,0 +1,25 @@ +// revisions: explicit implicit +//[implicit] check-pass + +#![forbid(coherence_leak_check)] +#![feature(negative_impls, with_negative_coherence)] + +pub trait Marker {} + +#[cfg(implicit)] +impl !Marker for &T {} + +#[cfg(explicit)] +impl<'a, T: ?Sized + 'a> !Marker for &'a T {} + +trait FnMarker {} + +// Unifying these two impls below results in a `T: '!0` obligation +// that we shouldn't need to care about. Ideally, we'd treat that +// as an assumption when proving `&'!0 T: Marker`... +impl FnMarker for fn(T) {} +impl FnMarker for fn(&T) {} +//[explicit]~^ ERROR conflicting implementations of trait `FnMarker` for type `fn(&_)` +//[explicit]~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +fn main() {} diff --git a/tests/ui/derived-errors/issue-30580.stderr b/tests/ui/derived-errors/issue-30580.stderr index 7bd0eaf77a95d..4e60368c387cf 100644 --- a/tests/ui/derived-errors/issue-30580.stderr +++ b/tests/ui/derived-errors/issue-30580.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `c` on type `&Foo` --> $DIR/issue-30580.rs:12:11 | LL | b.c; - | ^ help: a field with a similar name exists: `a` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | b.a; + | ~ error: aborting due to previous error diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs index 6040f3f30a7b5..ffc37b260a6bc 100644 --- a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.rs @@ -29,7 +29,7 @@ fn main() { doc_hidden_fields::B::default().hey; //~^ ERROR no field `hey` on type `B` //~| NOTE unknown field - //~| NOTE available fields are: `bye` + //~| NOTE available field is: `bye` C::default().hey; //~^ ERROR no field `hey` on type `C` diff --git a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr index b7fe3b79b475b..55f6d0fa32380 100644 --- a/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-doc-hidden-fields.stderr @@ -12,7 +12,7 @@ error[E0609]: no field `hey` on type `B` LL | doc_hidden_fields::B::default().hey; | ^^^ unknown field | - = note: available fields are: `bye` + = note: available field is: `bye` error[E0609]: no field `hey` on type `C` --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18 diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr index 7066d29760e7c..473c9a339fc25 100644 --- a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -5,9 +5,13 @@ LL | environment!(); | -------------- in this macro invocation ... LL | const CRATE: Crate = Crate { fiel: () }; - | ^^^^ help: a field with a similar name exists: `field` + | ^^^^ unknown field | = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info) +help: a field with a similar name exists + | +LL | const CRATE: Crate = Crate { field: () }; + | ~~~~~ error[E0609]: no field `field` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:24:16 diff --git a/tests/ui/did_you_mean/issue-36798.stderr b/tests/ui/did_you_mean/issue-36798.stderr index 98876e305ca09..9f82d4c44cf0a 100644 --- a/tests/ui/did_you_mean/issue-36798.stderr +++ b/tests/ui/did_you_mean/issue-36798.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:7:7 | LL | f.baz; - | ^^^ help: a field with a similar name exists: `bar` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | f.bar; + | ~~~ error: aborting due to previous error diff --git a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr index 2ed0a09240062..4f216568979ab 100644 --- a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `zz` on type `Foo` LL | f.zz; | ^^ unknown field | - = note: available fields are: `bar` + = note: available field is: `bar` error: aborting due to previous error diff --git a/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr index c20bbce3f24a9..d60db01a4653d 100644 --- a/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr +++ b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `Demo` has no field named `inocently_mispellable` --> $DIR/issue-42599_available_fields_note.rs:16:39 | LL | Self { secret_integer: 2, inocently_mispellable: () } - | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + | ^^^^^^^^^^^^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | Self { secret_integer: 2, innocently_misspellable: () } + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0560]: struct `Demo` has no field named `egregiously_nonexistent_field` --> $DIR/issue-42599_available_fields_note.rs:21:39 @@ -16,7 +21,12 @@ error[E0609]: no field `inocently_mispellable` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:32:41 | LL | let innocent_field_misaccess = demo.inocently_mispellable; - | ^^^^^^^^^^^^^^^^^^^^^ help: a field with a similar name exists: `innocently_misspellable` + | ^^^^^^^^^^^^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let innocent_field_misaccess = demo.innocently_misspellable; + | ~~~~~~~~~~~~~~~~~~~~~~~ error[E0609]: no field `egregiously_nonexistent_field` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 diff --git a/tests/ui/error-codes/E0609.stderr b/tests/ui/error-codes/E0609.stderr index 797e95d02dda3..cad857553da30 100644 --- a/tests/ui/error-codes/E0609.stderr +++ b/tests/ui/error-codes/E0609.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `foo` on type `Foo` LL | let _ = x.foo; | ^^^ unknown field | - = note: available fields are: `x` + = note: available field is: `x` error[E0609]: no field `1` on type `Bar` --> $DIR/E0609.rs:11:7 diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr index b21b6fdfcf1f2..4dd9848cf07b6 100644 --- a/tests/ui/error-codes/ex-E0612.stderr +++ b/tests/ui/error-codes/ex-E0612.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `1` on type `Foo` --> $DIR/ex-E0612.rs:5:6 | LL | y.1; - | ^ help: a field with a similar name exists: `0` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | y.0; + | ~ error: aborting due to previous error diff --git a/tests/ui/issues/issue-11004.stderr b/tests/ui/issues/issue-11004.stderr index b5831e42e399f..ea141e61df8d3 100644 --- a/tests/ui/issues/issue-11004.stderr +++ b/tests/ui/issues/issue-11004.stderr @@ -3,7 +3,8 @@ error[E0609]: no field `x` on type `*mut A` | LL | let x : i32 = n.x; | --^ - | | + | | | + | | unknown field | help: `n` is a raw pointer; try dereferencing it: `(*n).x` error[E0609]: no field `y` on type `*mut A` @@ -11,7 +12,8 @@ error[E0609]: no field `y` on type `*mut A` | LL | let y : f64 = n.y; | --^ - | | + | | | + | | unknown field | help: `n` is a raw pointer; try dereferencing it: `(*n).y` error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-13847.stderr b/tests/ui/issues/issue-13847.stderr index 52b8dc049702a..ded927693b201 100644 --- a/tests/ui/issues/issue-13847.stderr +++ b/tests/ui/issues/issue-13847.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `is_failure` on type `!` --> $DIR/issue-13847.rs:2:12 | LL | return.is_failure - | ^^^^^^^^^^ + | ^^^^^^^^^^ unknown field error: aborting due to previous error diff --git a/tests/ui/issues/issue-14721.stderr b/tests/ui/issues/issue-14721.stderr index 49ebb2976e8ad..f07bc7ad4f18b 100644 --- a/tests/ui/issues/issue-14721.stderr +++ b/tests/ui/issues/issue-14721.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `desc` on type `&str` --> $DIR/issue-14721.rs:3:24 | LL | println!("{}", foo.desc); - | ^^^^ + | ^^^^ unknown field error: aborting due to previous error diff --git a/tests/ui/issues/issue-19244-1.stderr b/tests/ui/issues/issue-19244-1.stderr index 1eb530542c02b..3358cac82e069 100644 --- a/tests/ui/issues/issue-19244-1.stderr +++ b/tests/ui/issues/issue-19244-1.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `1` on type `(usize,)` --> $DIR/issue-19244-1.rs:4:24 | LL | let a: [isize; TUP.1]; - | ^ + | ^ unknown field error: aborting due to previous error diff --git a/tests/ui/issues/issue-19244-2.stderr b/tests/ui/issues/issue-19244-2.stderr index 54529fdf5ba72..71655457f9018 100644 --- a/tests/ui/issues/issue-19244-2.stderr +++ b/tests/ui/issues/issue-19244-2.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct` LL | let a: [isize; STRUCT.nonexistent_field]; | ^^^^^^^^^^^^^^^^^ unknown field | - = note: available fields are: `field` + = note: available field is: `field` error: aborting due to previous error diff --git a/tests/ui/issues/issue-23253.stderr b/tests/ui/issues/issue-23253.stderr index be5714cd91a2b..44f01c1c16738 100644 --- a/tests/ui/issues/issue-23253.stderr +++ b/tests/ui/issues/issue-23253.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `a` on type `Foo` --> $DIR/issue-23253.rs:4:14 | LL | Foo::Bar.a; - | ^ + | ^ unknown field error: aborting due to previous error diff --git a/tests/ui/issues/issue-24365.stderr b/tests/ui/issues/issue-24365.stderr index f9eead8a4f213..3f6ed0231d8b5 100644 --- a/tests/ui/issues/issue-24365.stderr +++ b/tests/ui/issues/issue-24365.stderr @@ -2,19 +2,19 @@ error[E0609]: no field `b` on type `Foo` --> $DIR/issue-24365.rs:10:22 | LL | println!("{}", a.b); - | ^ + | ^ unknown field error[E0609]: no field `attr_name_idx` on type `&Attribute` --> $DIR/issue-24365.rs:17:18 | LL | let z = (&x).attr_name_idx; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unknown field error[E0609]: no field `attr_name_idx` on type `Attribute` --> $DIR/issue-24365.rs:18:15 | LL | let y = x.attr_name_idx; - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-31011.stderr b/tests/ui/issues/issue-31011.stderr index 58c170409fd44..4971e3357b4b3 100644 --- a/tests/ui/issues/issue-31011.stderr +++ b/tests/ui/issues/issue-31011.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `trace` on type `&T` --> $DIR/issue-31011.rs:3:17 | LL | if $ctx.trace { - | ^^^^^ + | ^^^^^ unknown field ... LL | fn wrap(context: &T) -> () | - type parameter 'T' declared here diff --git a/tests/ui/issues/issue-33525.stderr b/tests/ui/issues/issue-33525.stderr index f8d703dc3b169..ee9f4d4c3016d 100644 --- a/tests/ui/issues/issue-33525.stderr +++ b/tests/ui/issues/issue-33525.stderr @@ -8,13 +8,13 @@ error[E0609]: no field `lorem` on type `&'static str` --> $DIR/issue-33525.rs:3:8 | LL | "".lorem; - | ^^^^^ + | ^^^^^ unknown field error[E0609]: no field `ipsum` on type `&'static str` --> $DIR/issue-33525.rs:4:8 | LL | "".ipsum; - | ^^^^^ + | ^^^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr index 5e1b816defda3..0aa1ae7222f57 100644 --- a/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr +++ b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `00` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 | LL | let _condemned = justice.00; - | ^^ help: a field with a similar name exists: `0` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | let _condemned = justice.0; + | ~ error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 diff --git a/tests/ui/mismatched_types/cast-rfc0401.stderr b/tests/ui/mismatched_types/cast-rfc0401.stderr index d63cec489176b..142a52aef13d0 100644 --- a/tests/ui/mismatched_types/cast-rfc0401.stderr +++ b/tests/ui/mismatched_types/cast-rfc0401.stderr @@ -18,7 +18,7 @@ error[E0609]: no field `f` on type `fn() {main}` --> $DIR/cast-rfc0401.rs:65:18 | LL | let _ = main.f as *const u32; - | ^ + | ^ unknown field error[E0605]: non-primitive cast: `*const u8` as `&u8` --> $DIR/cast-rfc0401.rs:29:13 diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr index df555463f9884..2dc17189a702e 100644 --- a/tests/ui/offset-of/offset-of-self.stderr +++ b/tests/ui/offset-of/offset-of-self.stderr @@ -54,6 +54,8 @@ error[E0609]: no field `Self` on type `S` | LL | offset_of!(S, Self); | ^^^^ + | + = note: available fields are: `v`, `w` error[E0616]: field `v` of struct `T` is private --> $DIR/offset-of-self.rs:41:30 @@ -66,6 +68,8 @@ error[E0609]: no field `self` on type `S` | LL | offset_of!(S, self); | ^^^^ + | + = note: available fields are: `v`, `w` error[E0609]: no field `self` on type `u8` --> $DIR/offset-of-self.rs:56:21 diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr index 7090efc5014b3..d67d270ef7b93 100644 --- a/tests/ui/parser/float-field.stderr +++ b/tests/ui/parser/float-field.stderr @@ -274,7 +274,7 @@ error[E0609]: no field `1e1` on type `(u8, u8)` --> $DIR/float-field.rs:9:9 | LL | s.1.1e1; - | ^^^ + | ^^^ unknown field error[E0609]: no field `0x1e1` on type `S` --> $DIR/float-field.rs:24:7 @@ -336,13 +336,13 @@ error[E0609]: no field `f32` on type `(u8, u8)` --> $DIR/float-field.rs:44:9 | LL | s.1.f32; - | ^^^ + | ^^^ unknown field error[E0609]: no field `1e1` on type `(u8, u8)` --> $DIR/float-field.rs:46:7 | LL | s.1.1e1f32; - | ^^^^^^^^ + | ^^^^^^^^ unknown field error: aborting due to 55 previous errors diff --git a/tests/ui/rmeta/rmeta_meta_main.stderr b/tests/ui/rmeta/rmeta_meta_main.stderr index 0c6ed9afd3587..a4af319e339d1 100644 --- a/tests/ui/rmeta/rmeta_meta_main.stderr +++ b/tests/ui/rmeta/rmeta_meta_main.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `Foo` has no field named `field2` --> $DIR/rmeta_meta_main.rs:13:19 | LL | let _ = Foo { field2: 42 }; - | ^^^^^^ help: a field with a similar name exists: `field` + | ^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = Foo { field: 42 }; + | ~~~~~ error: aborting due to previous error diff --git a/tests/ui/structs/struct-fields-hints-no-dupe.stderr b/tests/ui/structs/struct-fields-hints-no-dupe.stderr index 1a88f269347c2..e109980e0bbae 100644 --- a/tests/ui/structs/struct-fields-hints-no-dupe.stderr +++ b/tests/ui/structs/struct-fields-hints-no-dupe.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints-no-dupe.rs:10:9 | LL | bar : 42, - | ^^^ help: a field with a similar name exists: `barr` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | barr : 42, + | ~~~~ error: aborting due to previous error diff --git a/tests/ui/structs/struct-fields-hints.stderr b/tests/ui/structs/struct-fields-hints.stderr index 3b8a2b5c7bad0..ed3650e5298d2 100644 --- a/tests/ui/structs/struct-fields-hints.stderr +++ b/tests/ui/structs/struct-fields-hints.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `A` has no field named `bar` --> $DIR/struct-fields-hints.rs:10:9 | LL | bar : 42, - | ^^^ help: a field with a similar name exists: `car` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | car : 42, + | ~~~ error: aborting due to previous error diff --git a/tests/ui/structs/struct-fields-typo.stderr b/tests/ui/structs/struct-fields-typo.stderr index 6949a0a4a6828..aef0e0e8e5ca5 100644 --- a/tests/ui/structs/struct-fields-typo.stderr +++ b/tests/ui/structs/struct-fields-typo.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `baa` on type `BuildData` --> $DIR/struct-fields-typo.rs:11:17 | LL | let x = foo.baa; - | ^^^ help: a field with a similar name exists: `bar` + | ^^^ unknown field + | +help: a field with a similar name exists + | +LL | let x = foo.bar; + | ~~~ error: aborting due to previous error diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr index a91e47657ab91..78bb018cb4be7 100644 --- a/tests/ui/structs/struct-pat-derived-error.stderr +++ b/tests/ui/structs/struct-pat-derived-error.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `d` on type `&A` --> $DIR/struct-pat-derived-error.rs:8:31 | LL | let A { x, y } = self.d; - | ^ help: a field with a similar name exists: `b` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | let A { x, y } = self.b; + | ~ error[E0026]: struct `A` does not have fields named `x`, `y` --> $DIR/struct-pat-derived-error.rs:8:17 diff --git a/tests/ui/structs/suggest-private-fields.stderr b/tests/ui/structs/suggest-private-fields.stderr index d628bd1620833..f67a4ed78e290 100644 --- a/tests/ui/structs/suggest-private-fields.stderr +++ b/tests/ui/structs/suggest-private-fields.stderr @@ -2,7 +2,12 @@ error[E0560]: struct `B` has no field named `aa` --> $DIR/suggest-private-fields.rs:15:9 | LL | aa: 20, - | ^^ help: a field with a similar name exists: `a` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | a: 20, + | ~ error[E0560]: struct `B` has no field named `bb` --> $DIR/suggest-private-fields.rs:17:9 @@ -16,13 +21,23 @@ error[E0560]: struct `A` has no field named `aa` --> $DIR/suggest-private-fields.rs:22:9 | LL | aa: 20, - | ^^ help: a field with a similar name exists: `a` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | a: 20, + | ~ error[E0560]: struct `A` has no field named `bb` --> $DIR/suggest-private-fields.rs:24:9 | LL | bb: 20, - | ^^ help: a field with a similar name exists: `b` + | ^^ unknown field + | +help: a field with a similar name exists + | +LL | b: 20, + | ~ error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr index ca9abc7e90689..1bab075dc9c1c 100644 --- a/tests/ui/suggestions/call-on-missing.stderr +++ b/tests/ui/suggestions/call-on-missing.stderr @@ -13,7 +13,7 @@ error[E0609]: no field `i` on type `fn() -> Foo {foo}` --> $DIR/call-on-missing.rs:16:9 | LL | foo.i; - | ^ + | ^ unknown field | help: use parentheses to call this function | @@ -62,7 +62,7 @@ LL | fn type_param Foo>(t: T) { | - type parameter 'T' declared here ... LL | t.i; - | ^ + | ^ unknown field | help: use parentheses to call this type parameter | diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr index cc991b915d339..65353ed923e0e 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -4,7 +4,6 @@ error[E0609]: no field `c` on type `Foo` LL | let _test = &fooer.c; | ^ unknown field | - = note: available fields are: `first`, `_second`, `_third` help: one of the expressions' fields has a field of the same name | LL | let _test = &fooer.first.bar.c; @@ -16,7 +15,6 @@ error[E0609]: no field `test` on type `Foo` LL | let _test2 = fooer.test; | ^^^^ unknown field | - = note: available fields are: `first`, `_second`, `_third` help: one of the expressions' fields has a field of the same name | LL | let _test2 = fooer.first.bar.c.test; diff --git a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr index cafddbe262424..9f185f5dd52b3 100644 --- a/tests/ui/suggestions/parenthesized-deref-suggestion.stderr +++ b/tests/ui/suggestions/parenthesized-deref-suggestion.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `*const Session` --> $DIR/parenthesized-deref-suggestion.rs:7:30 | LL | (sess as *const Session).opts; - | ^^^^ + | ^^^^ unknown field | help: `(sess as *const Session)` is a raw pointer; try dereferencing it | @@ -14,7 +14,8 @@ error[E0609]: no field `0` on type `[u32; 1]` | LL | (x as [u32; 1]).0; | ----------------^ - | | + | | | + | | unknown field | help: instead of using tuple indexing, use array indexing: `(x as [u32; 1])[0]` error: aborting due to 2 previous errors diff --git a/tests/ui/suggestions/private-field.stderr b/tests/ui/suggestions/private-field.stderr index c38c795e07ae8..0db426588bd2f 100644 --- a/tests/ui/suggestions/private-field.stderr +++ b/tests/ui/suggestions/private-field.stderr @@ -4,7 +4,7 @@ error[E0609]: no field `cap` on type `S` LL | dbg!(s.cap) | ^^^ unknown field | - = note: available fields are: `val` + = note: available field is: `val` error: aborting due to previous error diff --git a/tests/ui/suggestions/suggest-field-through-deref.fixed b/tests/ui/suggestions/suggest-field-through-deref.fixed new file mode 100644 index 0000000000000..07ba3aa911f4e --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.fixed @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code)] +use std::sync::Arc; +struct S { + long_name: (), + foo: (), +} +fn main() { + let x = Arc::new(S { long_name: (), foo: () }); + let _ = x.long_name; //~ ERROR no field `longname` + let y = S { long_name: (), foo: () }; + let _ = y.long_name; //~ ERROR no field `longname` + let a = Some(Arc::new(S { long_name: (), foo: () })); + let _ = a.unwrap().long_name; //~ ERROR no field `longname` + let b = Some(S { long_name: (), foo: () }); + let _ = b.unwrap().long_name; //~ ERROR no field `long_name` + let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () })); + let _ = c.unwrap().long_name; //~ ERROR no field `longname` + let d = Ok::<_, ()>(S { long_name: (), foo: () }); + let _ = d.unwrap().long_name; //~ ERROR no field `long_name` +} diff --git a/tests/ui/suggestions/suggest-field-through-deref.rs b/tests/ui/suggestions/suggest-field-through-deref.rs new file mode 100644 index 0000000000000..6e24b425e9565 --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.rs @@ -0,0 +1,21 @@ +// run-rustfix +#![allow(dead_code)] +use std::sync::Arc; +struct S { + long_name: (), + foo: (), +} +fn main() { + let x = Arc::new(S { long_name: (), foo: () }); + let _ = x.longname; //~ ERROR no field `longname` + let y = S { long_name: (), foo: () }; + let _ = y.longname; //~ ERROR no field `longname` + let a = Some(Arc::new(S { long_name: (), foo: () })); + let _ = a.longname; //~ ERROR no field `longname` + let b = Some(S { long_name: (), foo: () }); + let _ = b.long_name; //~ ERROR no field `long_name` + let c = Ok::<_, ()>(Arc::new(S { long_name: (), foo: () })); + let _ = c.longname; //~ ERROR no field `longname` + let d = Ok::<_, ()>(S { long_name: (), foo: () }); + let _ = d.long_name; //~ ERROR no field `long_name` +} diff --git a/tests/ui/suggestions/suggest-field-through-deref.stderr b/tests/ui/suggestions/suggest-field-through-deref.stderr new file mode 100644 index 0000000000000..cc9fe2044c91e --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.stderr @@ -0,0 +1,69 @@ +error[E0609]: no field `longname` on type `Arc` + --> $DIR/suggest-field-through-deref.rs:10:15 + | +LL | let _ = x.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = x.long_name; + | ~~~~~~~~~ + +error[E0609]: no field `longname` on type `S` + --> $DIR/suggest-field-through-deref.rs:12:15 + | +LL | let _ = y.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = y.long_name; + | ~~~~~~~~~ + +error[E0609]: no field `longname` on type `Option>` + --> $DIR/suggest-field-through-deref.rs:14:15 + | +LL | let _ = a.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = a.unwrap().long_name; + | ~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `long_name` on type `Option` + --> $DIR/suggest-field-through-deref.rs:16:15 + | +LL | let _ = b.long_name; + | ^^^^^^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | let _ = b.unwrap().long_name; + | +++++++++ + +error[E0609]: no field `longname` on type `Result, ()>` + --> $DIR/suggest-field-through-deref.rs:18:15 + | +LL | let _ = c.longname; + | ^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = c.unwrap().long_name; + | ~~~~~~~~~~~~~~~~~~ + +error[E0609]: no field `long_name` on type `Result` + --> $DIR/suggest-field-through-deref.rs:20:15 + | +LL | let _ = d.long_name; + | ^^^^^^^^^ unknown field + | +help: one of the expressions' fields has a field of the same name + | +LL | let _ = d.unwrap().long_name; + | +++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/suggestions/too-many-field-suggestions.stderr b/tests/ui/suggestions/too-many-field-suggestions.stderr index 63ad6fdb16994..ac5c8cb60ccdc 100644 --- a/tests/ui/suggestions/too-many-field-suggestions.stderr +++ b/tests/ui/suggestions/too-many-field-suggestions.stderr @@ -25,7 +25,6 @@ error[E0609]: no field `field` on type `Thing` LL | t.field; | ^^^^^ unknown field | - = note: available fields are: `a0`, `a1`, `a2`, `a3`, `a4` ... and 5 others help: some of the expressions' fields have a field of the same name | LL | t.a0.field; diff --git a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr index 12466868f0028..fb3573ee2a4ee 100644 --- a/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr +++ b/tests/ui/suggestions/type-mismatch-struct-field-shorthand-2.stderr @@ -24,7 +24,12 @@ error[E0560]: struct `RGB` has no field named `c` --> $DIR/type-mismatch-struct-field-shorthand-2.rs:5:25 | LL | let _ = RGB { r, g, c }; - | ^ help: a field with a similar name exists: `b` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | let _ = RGB { r, g, b }; + | ~ error: aborting due to 3 previous errors diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr index 8d22f458a6c6e..ae2c275f52cd9 100644 --- a/tests/ui/tuple/index-invalid.stderr +++ b/tests/ui/tuple/index-invalid.stderr @@ -2,19 +2,19 @@ error[E0609]: no field `1` on type `(((),),)` --> $DIR/index-invalid.rs:2:22 | LL | let _ = (((),),).1.0; - | ^ + | ^ unknown field error[E0609]: no field `1` on type `((),)` --> $DIR/index-invalid.rs:4:24 | LL | let _ = (((),),).0.1; - | ^ + | ^ unknown field error[E0609]: no field `000` on type `(((),),)` --> $DIR/index-invalid.rs:6:22 | LL | let _ = (((),),).000.000; - | ^^^ + | ^^^ unknown field error: aborting due to 3 previous errors diff --git a/tests/ui/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr index a1bcdfaedbc60..a267e41b1bc32 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.stderr +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -2,7 +2,12 @@ error[E0609]: no field `0` on type `Point` --> $DIR/tuple-index-not-tuple.rs:6:12 | LL | origin.0; - | ^ help: a field with a similar name exists: `x` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | origin.x; + | ~ error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr index 7d7c5cd7892ea..96090435d06be 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,13 +2,18 @@ error[E0609]: no field `2` on type `Point` --> $DIR/tuple-index-out-of-bounds.rs:7:12 | LL | origin.2; - | ^ help: a field with a similar name exists: `0` + | ^ unknown field + | +help: a field with a similar name exists + | +LL | origin.0; + | ~ error[E0609]: no field `2` on type `({integer}, {integer})` --> $DIR/tuple-index-out-of-bounds.rs:12:11 | LL | tuple.2; - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr index 4be4c91dfc2c3..e1091c8f5ca00 100644 --- a/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr +++ b/tests/ui/typeck/issue-52082-type-param-shadows-existing-type.stderr @@ -5,7 +5,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:18 @@ -14,7 +14,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:25 @@ -23,7 +23,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `&Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:31:32 @@ -32,7 +32,7 @@ LL | fn equals_ref(a: &Point, b: &Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:11 @@ -41,7 +41,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `x` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:18 @@ -50,7 +50,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:25 @@ -59,7 +59,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error[E0609]: no field `y` on type `Point` --> $DIR/issue-52082-type-param-shadows-existing-type.rs:39:32 @@ -68,7 +68,7 @@ LL | fn equals_val(a: Point, b: Point) -> bool | ----- type parameter 'Point' declared here LL | { LL | a.x == b.x && a.y == b.y - | ^ + | ^ unknown field error: aborting due to 8 previous errors diff --git a/tests/ui/typeck/issue-53712.stderr b/tests/ui/typeck/issue-53712.stderr index db85919afcb55..7ed9cb103798e 100644 --- a/tests/ui/typeck/issue-53712.stderr +++ b/tests/ui/typeck/issue-53712.stderr @@ -3,7 +3,8 @@ error[E0609]: no field `0` on type `[{integer}; 5]` | LL | arr.0; | ----^ - | | + | | | + | | unknown field | help: instead of using tuple indexing, use array indexing: `arr[0]` error: aborting due to previous error diff --git a/tests/ui/typeck/issue-65611.stderr b/tests/ui/typeck/issue-65611.stderr index 003c630790d2c..2278450a6d8eb 100644 --- a/tests/ui/typeck/issue-65611.stderr +++ b/tests/ui/typeck/issue-65611.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `0` on type `&_` --> $DIR/issue-65611.rs:59:36 | LL | let x = buffer.last().unwrap().0.clone(); - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-87181/tuple-field.stderr b/tests/ui/typeck/issue-87181/tuple-field.stderr index 0a7d30b615a63..16afac4bd6bcc 100644 --- a/tests/ui/typeck/issue-87181/tuple-field.stderr +++ b/tests/ui/typeck/issue-87181/tuple-field.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `0` on type `fn(char, u16) -> Foo {Foo}` --> $DIR/tuple-field.rs:12:15 | LL | thing.bar.0; - | ^ + | ^ unknown field | help: use parentheses to construct this tuple struct | diff --git a/tests/ui/typeck/issue-96738.stderr b/tests/ui/typeck/issue-96738.stderr index 547cffffa2ee3..2bc8453dda74d 100644 --- a/tests/ui/typeck/issue-96738.stderr +++ b/tests/ui/typeck/issue-96738.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `nonexistent_field` on type `fn(_) -> Option<_> {Option:: --> $DIR/issue-96738.rs:3:10 | LL | Some.nonexistent_field; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/no-type-for-node-ice.stderr b/tests/ui/typeck/no-type-for-node-ice.stderr index b50241fb1a059..b990b5f951f25 100644 --- a/tests/ui/typeck/no-type-for-node-ice.stderr +++ b/tests/ui/typeck/no-type-for-node-ice.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `homura` on type `&'static str` --> $DIR/no-type-for-node-ice.rs:4:8 | LL | "".homura[""]; - | ^^^^^^ + | ^^^^^^ unknown field error: aborting due to previous error diff --git a/tests/ui/union/union-suggest-field.mirunsafeck.stderr b/tests/ui/union/union-suggest-field.mirunsafeck.stderr index 58b1f5cb0786a..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.mirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let u = U { principal: 0 }; + | ~~~~~~~~~ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let w = u.principal; + | ~~~~~~~~~ error[E0615]: attempted to take value of method `calculate` on type `U` --> $DIR/union-suggest-field.rs:21:15 diff --git a/tests/ui/union/union-suggest-field.thirunsafeck.stderr b/tests/ui/union/union-suggest-field.thirunsafeck.stderr index 58b1f5cb0786a..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.thirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -2,13 +2,23 @@ error[E0560]: union `U` has no field named `principle` --> $DIR/union-suggest-field.rs:13:17 | LL | let u = U { principle: 0 }; - | ^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let u = U { principal: 0 }; + | ~~~~~~~~~ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ help: a field with a similar name exists: `principal` + | ^^^^^^^^^^ unknown field + | +help: a field with a similar name exists + | +LL | let w = u.principal; + | ~~~~~~~~~ error[E0615]: attempted to take value of method `calculate` on type `U` --> $DIR/union-suggest-field.rs:21:15 diff --git a/tests/ui/unsafe/unsafe-fn-autoderef.stderr b/tests/ui/unsafe/unsafe-fn-autoderef.stderr index 20a88c356108d..f563118e8ac09 100644 --- a/tests/ui/unsafe/unsafe-fn-autoderef.stderr +++ b/tests/ui/unsafe/unsafe-fn-autoderef.stderr @@ -3,7 +3,8 @@ error[E0609]: no field `f` on type `*const Rec` | LL | return p.f; | --^ - | | + | | | + | | unknown field | help: `p` is a raw pointer; try dereferencing it: `(*p).f` error: aborting due to previous error