From d6337e65683ea982006ebfb4cf4881b1d3fe5aad Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 14 Oct 2023 16:20:32 -0700 Subject: [PATCH 01/17] Add Seek::seek_relative --- library/std/src/io/buffered/bufreader.rs | 10 +++++++++ library/std/src/io/mod.rs | 26 ++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 7097dfef88d4e..db4f479d45953 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -492,6 +492,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 e6431abcf8215..ba2c0e217deb1 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1957,6 +1957,32 @@ 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))`. + /// + /// # 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(()) + /// } + /// ``` + #[unstable(feature = "seek_seek_relative", issue = "none")] + 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. From bc058b6f45191a9c5af37856c3f5a4d4b2efec77 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 29 Oct 2023 19:11:18 -0700 Subject: [PATCH 02/17] Add tracking issue --- library/std/src/io/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index ba2c0e217deb1..9ee68a079bc4a 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1978,7 +1978,7 @@ pub trait Seek { /// Ok(()) /// } /// ``` - #[unstable(feature = "seek_seek_relative", issue = "none")] + #[unstable(feature = "seek_seek_relative", issue = "117374")] fn seek_relative(&mut self, offset: i64) -> Result<()> { self.seek(SeekFrom::Current(offset))?; Ok(()) From d9f7c9db02c023adfeba554971abbf11bb244994 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 4 Nov 2023 15:45:55 -0700 Subject: [PATCH 03/17] Improve documentation --- library/std/src/io/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 9ee68a079bc4a..bd6a989ee9610 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1960,7 +1960,9 @@ pub trait Seek { /// Seeks relative to the current position. /// - /// This is equivalent to `self.seek(SeekFrom::Current(offset))`. + /// 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 /// @@ -1978,6 +1980,8 @@ pub trait Seek { /// 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))?; From 3fdd84ab3ab664bcc6e56a3ff5853ce7945399e8 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 16 Nov 2023 13:25:49 +1100 Subject: [PATCH 04/17] Allow trailing commas in static suggestions --- src/tools/suggest-tests/src/static_suggestions.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs index a84e78254f269..6e196e626a84e 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -2,7 +2,7 @@ use crate::{sug, Suggestion}; // FIXME: perhaps this could use `std::lazy` when it is stablizied macro_rules! static_suggestions { - ($( $glob:expr => [ $( $suggestion:expr ),* ] ),*) => { + ($( $glob:expr => [ $( $suggestion:expr ),* $(,)? ] ),* $(,)? ) => { pub(crate) const STATIC_SUGGESTIONS: ::once_cell::unsync::Lazy)>> = ::once_cell::unsync::Lazy::new(|| vec![ $( ($glob, vec![ $($suggestion),* ]) ),*]); } @@ -10,15 +10,15 @@ macro_rules! static_suggestions { static_suggestions! { "*.md" => [ - sug!("test", 0, ["linkchecker"]) + sug!("test", 0, ["linkchecker"]), ], "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"]) - ] + sug!("test", 1, ["rustdoc"]), + ], } From 925111c2eb85681697155edbaf694f6693427a69 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 16 Nov 2023 13:18:40 +1100 Subject: [PATCH 05/17] Support multiple globs in static suggestions --- src/tools/suggest-tests/src/lib.rs | 16 +++++++++------- .../suggest-tests/src/static_suggestions.rs | 12 ++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) 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 6e196e626a84e..1dc02de6ea4dc 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -2,23 +2,23 @@ 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" => [ + ["*.md"] => [ sug!("test", 0, ["linkchecker"]), ], - "compiler/*" => [ + ["compiler/*"] => [ sug!("check"), sug!("test", 1, ["tests/ui", "tests/run-make"]), ], - "src/librustdoc/*" => [ + ["src/librustdoc/*"] => [ sug!("test", 1, ["rustdoc"]), ], } From 05322162abf3cc5bb66848b37af82d6442486a48 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 16 Nov 2023 13:24:35 +1100 Subject: [PATCH 06/17] Add test suggestions for `mir-opt` and `coverage` --- src/tools/suggest-tests/src/static_suggestions.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/tools/suggest-tests/src/static_suggestions.rs b/src/tools/suggest-tests/src/static_suggestions.rs index 1dc02de6ea4dc..fbd265ea42a2e 100644 --- a/src/tools/suggest-tests/src/static_suggestions.rs +++ b/src/tools/suggest-tests/src/static_suggestions.rs @@ -18,6 +18,17 @@ static_suggestions! { sug!("test", 1, ["tests/ui", "tests/run-make"]), ], + ["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"]), ], From dfa75391f8c401d0f1b40b0bf9799a07b53c58ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Oct 2023 02:06:06 +0000 Subject: [PATCH 07/17] Suggest field typo through derefs Take into account implicit dereferences when suggesting fields. ``` error[E0609]: no field `longname` on type `Arc` --> $DIR/suggest-field-through-deref.rs:10:15 | LL | let _ = x.longname; | ^^^^^^^^ help: a field with a similar name exists: `long_name` ``` CC https://github.com/rust-lang/rust/issues/78374#issuecomment-719564114 --- compiler/rustc_hir_typeck/src/expr.rs | 141 +++++++++--------- .../rustc_hir_typeck/src/method/suggest.rs | 125 ++++++++-------- ...uggest-switching-edition-on-await-cargo.rs | 2 - ...st-switching-edition-on-await-cargo.stderr | 10 +- .../suggest-switching-edition-on-await.rs | 2 - .../suggest-switching-edition-on-await.stderr | 10 +- .../dont-suggest-doc-hidden-fields.rs | 5 +- .../dont-suggest-doc-hidden-fields.stderr | 12 +- .../dont-suggest-hygienic-fields.stderr | 6 +- .../issue-36798_unknown_field.stderr | 4 +- .../issue-42599_available_fields_note.stderr | 2 +- .../error-codes/E0609-private-method.stderr | 2 +- tests/ui/error-codes/E0609.stderr | 6 +- tests/ui/infinite/infinite-autoderef.stderr | 2 +- tests/ui/issues/issue-19244-2.stderr | 4 +- ...73-zero-padded-tuple-struct-indices.stderr | 2 +- tests/ui/offset-of/offset-of-self.stderr | 4 + tests/ui/parser/float-field.stderr | 16 +- tests/ui/suggestions/call-on-missing.stderr | 2 +- .../field-access-considering-privacy.stderr | 2 +- ...present-in-subfield-recursion-limit.stderr | 2 +- ...-existent-field-present-in-subfield.stderr | 6 +- tests/ui/suggestions/private-field.stderr | 4 +- .../suggest-field-through-deref.fixed | 13 ++ .../suggest-field-through-deref.rs | 13 ++ .../suggest-field-through-deref.stderr | 15 ++ .../too-many-field-suggestions.stderr | 3 +- tests/ui/tuple/tuple-index-not-tuple.stderr | 2 +- tests/ui/typeck/issue-67971.stderr | 2 +- 29 files changed, 227 insertions(+), 192 deletions(-) create mode 100644 tests/ui/suggestions/suggest-field-through-deref.fixed create mode 100644 tests/ui/suggestions/suggest-field-through-deref.rs create mode 100644 tests/ui/suggestions/suggest-field-through-deref.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index eaf5e938d3cf9..b95c673f3ba28 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2471,9 +2471,6 @@ 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) => { self.point_at_param_definition(&mut err, param_ty); } @@ -2633,34 +2630,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, @@ -2709,7 +2678,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 +2686,12 @@ 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) + for (found_fields, args) in + self.get_field_candidates_considering_privacy(span, expr_t, mod_id, id) { - let candidate_fields: Vec<_> = fields + 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,6 +2700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { args, vec![], mod_id, + id, ) }) .map(|mut field_path| { @@ -2753,6 +2725,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidate_fields.iter().map(|path| format!("{path}.")), Applicability::MaybeIncorrect, ); + } else { + if let Some(field_name) = find_best_match_for_name(&field_names, field.name, None) { + err.span_suggestion( + field.span, + "a field with a similar name exists", + 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 +2768,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 +2813,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 +2829,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 3624b86b57563..8dc3927ce331b 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/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..051e6afd7a725 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 @@ -10,7 +10,6 @@ fn await_on_struct_missing() { let x = S; 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 @@ -32,7 +31,6 @@ fn await_on_struct_similar() { fn await_on_63533(x: Pin<&mut dyn 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..1b0912310e897 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 @@ -2,14 +2,14 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7 | LL | x.await; - | ^^^^^ 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 error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:23:7 | LL | x.await; | ^^^^^ help: a field with a similar name exists: `awai` @@ -19,17 +19,17 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide 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:32:7 | LL | x.await; - | ^^^^^ 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 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:40:7 | LL | x.await; | ^^^^^ 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..4b62713d1b23e 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -8,7 +8,6 @@ fn await_on_struct_missing() { let x = S; 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 @@ -30,7 +29,6 @@ fn await_on_struct_similar() { fn await_on_63533(x: Pin<&mut dyn 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..ddc44562d2cb6 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -2,14 +2,14 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` --> $DIR/suggest-switching-edition-on-await.rs:9:7 | LL | x.await; - | ^^^^^ 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 error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await.rs:22:7 + --> $DIR/suggest-switching-edition-on-await.rs:21:7 | LL | x.await; | ^^^^^ help: a field with a similar name exists: `awai` @@ -19,17 +19,17 @@ LL | x.await; = note: for more on editions, read https://doc.rust-lang.org/edition-guide 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:30:7 | LL | x.await; - | ^^^^^ 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 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:38:7 | LL | x.await; | ^^^^^ 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..36a7066e72e12 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 @@ -21,18 +21,15 @@ fn main() { // `doc(hidden)` because it's defined in this crate. A::default().hey; //~^ ERROR no field `hey` on type `A` - //~| NOTE unknown field //~| NOTE available fields are: `hello`, `bye` // Here we want to hide the field `hello` since it's marked // `doc(hidden)` and comes from an external crate. 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` - //~| NOTE unknown field //~| NOTE available fields are: `hello`, `bye` } 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..abded80066ac3 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 @@ -2,23 +2,23 @@ error[E0609]: no field `hey` on type `A` --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18 | LL | A::default().hey; - | ^^^ unknown field + | ^^^ | = note: available fields are: `hello`, `bye` error[E0609]: no field `hey` on type `B` - --> $DIR/dont-suggest-doc-hidden-fields.rs:29:37 + --> $DIR/dont-suggest-doc-hidden-fields.rs:28:37 | 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 + --> $DIR/dont-suggest-doc-hidden-fields.rs:32:18 | LL | C::default().hey; - | ^^^ unknown field + | ^^^ | = note: available fields are: `hello`, `bye` 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..414590873da21 100644 --- a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -13,13 +13,13 @@ error[E0609]: no field `field` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:24:16 | LL | let _ = ty.field; - | ^^^^^ unknown field + | ^^^^^ error[E0609]: no field `fieeld` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:25:16 | LL | let _ = ty.fieeld; - | ^^^^^^ unknown field + | ^^^^^^ error[E0026]: struct `Compound` does not have a field named `field` --> $DIR/dont-suggest-hygienic-fields.rs:27:20 @@ -42,7 +42,7 @@ error[E0609]: no field `0` on type `Component` --> $DIR/dont-suggest-hygienic-fields.rs:34:16 | LL | let _ = ty.0; - | ^ unknown field + | ^ error: aborting due to 6 previous errors 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..4854a9bdeb844 100644 --- a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -2,9 +2,9 @@ error[E0609]: no field `zz` on type `Foo` --> $DIR/issue-36798_unknown_field.rs:7:7 | 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..a4c3512eb411f 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 @@ -22,7 +22,7 @@ error[E0609]: no field `egregiously_nonexistent_field` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 | LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: available fields are: `favorite_integer`, `innocently_misspellable` diff --git a/tests/ui/error-codes/E0609-private-method.stderr b/tests/ui/error-codes/E0609-private-method.stderr index d2a11e9062740..a2bfcca5e0b8b 100644 --- a/tests/ui/error-codes/E0609-private-method.stderr +++ b/tests/ui/error-codes/E0609-private-method.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `method` on type `Foo` --> $DIR/E0609-private-method.rs:15:7 | LL | f.method; - | ^^^^^^ unknown field + | ^^^^^^ error: aborting due to previous error diff --git a/tests/ui/error-codes/E0609.stderr b/tests/ui/error-codes/E0609.stderr index 797e95d02dda3..78a61b92c5c8e 100644 --- a/tests/ui/error-codes/E0609.stderr +++ b/tests/ui/error-codes/E0609.stderr @@ -2,15 +2,15 @@ error[E0609]: no field `foo` on type `Foo` --> $DIR/E0609.rs:8:15 | 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 | LL | y.1; - | ^ unknown field + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 51b61e3a66bb4..1fa53beba6853 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -29,7 +29,7 @@ error[E0609]: no field `foo` on type `Foo` --> $DIR/infinite-autoderef.rs:24:9 | LL | Foo.foo; - | ^^^ unknown field + | ^^^ error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:9 diff --git a/tests/ui/issues/issue-19244-2.stderr b/tests/ui/issues/issue-19244-2.stderr index 54529fdf5ba72..933371d1e89d6 100644 --- a/tests/ui/issues/issue-19244-2.stderr +++ b/tests/ui/issues/issue-19244-2.stderr @@ -2,9 +2,9 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct` --> $DIR/issue-19244-2.rs:5:27 | 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-47073-zero-padded-tuple-struct-indices.stderr b/tests/ui/issues/issue-47073-zero-padded-tuple-struct-indices.stderr index 5e1b816defda3..193c5aaf72dd0 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 @@ -8,7 +8,7 @@ error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 | LL | let _punishment = justice.001; - | ^^^ unknown field + | ^^^ | = note: available fields are: `0`, `1` 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..a81992c338097 100644 --- a/tests/ui/parser/float-field.stderr +++ b/tests/ui/parser/float-field.stderr @@ -266,7 +266,7 @@ error[E0609]: no field `1e1` on type `S` --> $DIR/float-field.rs:6:7 | LL | s.1e1; - | ^^^ unknown field + | ^^^ | = note: available fields are: `0`, `1` @@ -280,7 +280,7 @@ error[E0609]: no field `0x1e1` on type `S` --> $DIR/float-field.rs:24:7 | LL | s.0x1e1; - | ^^^^^ unknown field + | ^^^^^ | = note: available fields are: `0`, `1` @@ -288,7 +288,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:25:7 | LL | s.0x1.; - | ^^^ unknown field + | ^^^ | = note: available fields are: `0`, `1` @@ -296,7 +296,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:28:7 | LL | s.0x1.1; - | ^^^ unknown field + | ^^^ | = note: available fields are: `0`, `1` @@ -304,7 +304,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:30:7 | LL | s.0x1.1e1; - | ^^^ unknown field + | ^^^ | = note: available fields are: `0`, `1` @@ -312,7 +312,7 @@ error[E0609]: no field `0x1e` on type `S` --> $DIR/float-field.rs:34:7 | LL | s.0x1e+1; - | ^^^^ unknown field + | ^^^^ | = note: available fields are: `0`, `1` @@ -320,7 +320,7 @@ error[E0609]: no field `0x1e` on type `S` --> $DIR/float-field.rs:35:7 | LL | s.0x1e-1; - | ^^^^ unknown field + | ^^^^ | = note: available fields are: `0`, `1` @@ -328,7 +328,7 @@ error[E0609]: no field `1e1` on type `S` --> $DIR/float-field.rs:42:7 | LL | s.1e1f32; - | ^^^^^^ unknown field + | ^^^^^^ | = note: available fields are: `0`, `1` diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr index ca9abc7e90689..2824343c9134b 100644 --- a/tests/ui/suggestions/call-on-missing.stderr +++ b/tests/ui/suggestions/call-on-missing.stderr @@ -35,7 +35,7 @@ error[E0609]: no field `i` on type `Box Foo>` --> $DIR/call-on-missing.rs:26:14 | LL | callable.i; - | ^ unknown field + | ^ | help: use parentheses to call this trait object | diff --git a/tests/ui/suggestions/field-access-considering-privacy.stderr b/tests/ui/suggestions/field-access-considering-privacy.stderr index cbf6f3d100258..5bbcfeea4747f 100644 --- a/tests/ui/suggestions/field-access-considering-privacy.stderr +++ b/tests/ui/suggestions/field-access-considering-privacy.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `TyCtxt<'tcx>` --> $DIR/field-access-considering-privacy.rs:29:13 | LL | tcx.opts; - | ^^^^ unknown field + | ^^^^ | help: one of the expressions' fields has a field of the same name | diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr index b294f4da7db33..f4010b39dc46c 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `f` on type `Foo` --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22 | LL | let test = fooer.f; - | ^ unknown field + | ^ | = note: available fields are: `first`, `second`, `third` 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..c3e4014503891 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -2,9 +2,8 @@ error[E0609]: no field `c` on type `Foo` --> $DIR/non-existent-field-present-in-subfield.rs:37:24 | 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; @@ -14,9 +13,8 @@ error[E0609]: no field `test` on type `Foo` --> $DIR/non-existent-field-present-in-subfield.rs:40:24 | 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/private-field.stderr b/tests/ui/suggestions/private-field.stderr index c38c795e07ae8..6a735a163b896 100644 --- a/tests/ui/suggestions/private-field.stderr +++ b/tests/ui/suggestions/private-field.stderr @@ -2,9 +2,9 @@ error[E0609]: no field `cap` on type `S` --> $DIR/private-field.rs:7:12 | 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..a0f20e563f358 --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.fixed @@ -0,0 +1,13 @@ +// 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` +} 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..729e5db05525e --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.rs @@ -0,0 +1,13 @@ +// 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` +} 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..649e28be51d10 --- /dev/null +++ b/tests/ui/suggestions/suggest-field-through-deref.stderr @@ -0,0 +1,15 @@ +error[E0609]: no field `longname` on type `Arc` + --> $DIR/suggest-field-through-deref.rs:10:15 + | +LL | let _ = x.longname; + | ^^^^^^^^ help: a field with a similar name exists: `long_name` + +error[E0609]: no field `longname` on type `S` + --> $DIR/suggest-field-through-deref.rs:12:15 + | +LL | let _ = y.longname; + | ^^^^^^^^ help: a field with a similar name exists: `long_name` + +error: aborting due to 2 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..b556bdda3f633 100644 --- a/tests/ui/suggestions/too-many-field-suggestions.stderr +++ b/tests/ui/suggestions/too-many-field-suggestions.stderr @@ -23,9 +23,8 @@ error[E0609]: no field `field` on type `Thing` --> $DIR/too-many-field-suggestions.rs:26:7 | 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/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr index a1bcdfaedbc60..cc94a61ae7fbb 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.stderr +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 | LL | Empty.0; - | ^ unknown field + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-67971.stderr b/tests/ui/typeck/issue-67971.stderr index d50ed9cf13bb4..4ae0f5d1c5c02 100644 --- a/tests/ui/typeck/issue-67971.stderr +++ b/tests/ui/typeck/issue-67971.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `sleep` on type `&mut S` --> $DIR/issue-67971.rs:5:9 | LL | ctx.sleep = 0; - | ^^^^^ unknown field + | ^^^^^ error[E0308]: mismatched types --> $DIR/issue-67971.rs:3:24 From 8bd8f3b090507f87c6458ed507ee36ddd4a00767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 24 Oct 2023 23:31:47 +0000 Subject: [PATCH 08/17] Suggest `unwrap()` on field not found for `Result`/`Option` When encountering a `Result` or `Option` where `T` has a field that's being accessed, suggest calling `.unwrap()` to get to the field. --- compiler/rustc_hir_typeck/src/expr.rs | 24 +++++--- ...st-switching-edition-on-await-cargo.stderr | 6 +- .../suggest-switching-edition-on-await.stderr | 6 +- tests/ui/derived-errors/issue-30580.stderr | 7 ++- tests/ui/did_you_mean/issue-36798.stderr | 7 ++- .../issue-42599_available_fields_note.stderr | 7 ++- tests/ui/error-codes/ex-E0612.stderr | 7 ++- ...73-zero-padded-tuple-struct-indices.stderr | 7 ++- tests/ui/structs/struct-fields-typo.stderr | 7 ++- .../structs/struct-pat-derived-error.stderr | 7 ++- .../suggest-field-through-deref.fixed | 8 +++ .../suggest-field-through-deref.rs | 8 +++ .../suggest-field-through-deref.stderr | 60 ++++++++++++++++++- tests/ui/tuple/tuple-index-not-tuple.stderr | 7 ++- .../ui/tuple/tuple-index-out-of-bounds.stderr | 7 ++- .../union-suggest-field.mirunsafeck.stderr | 7 ++- .../union-suggest-field.thirunsafeck.stderr | 7 ++- 17 files changed, 166 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index b95c673f3ba28..264b96af6dac2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2686,8 +2686,19 @@ 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(); + 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() + { + (ty, "unwrap().") + } else { + (expr_t, "") + }; for (found_fields, args) in - self.get_field_candidates_considering_privacy(span, expr_t, mod_id, id) + 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 @@ -2707,9 +2718,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { 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::>(); @@ -2722,15 +2732,15 @@ 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( + err.span_suggestion_verbose( field.span, "a field with a similar name exists", - field_name, + format!("{unwrap}{}", field_name), Applicability::MaybeIncorrect, ); } else if !field_names.is_empty() { 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 1b0912310e897..ebd117f506cd4 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,11 +12,15 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await-cargo.rs:23:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ | = 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:32:7 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 ddc44562d2cb6..82c5b107b0571 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -12,11 +12,15 @@ error[E0609]: no field `await` on type `await_on_struct_similar::S` --> $DIR/suggest-switching-edition-on-await.rs:21:7 | LL | x.await; - | ^^^^^ help: a field with a similar name exists: `awai` + | ^^^^^ | = 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:30:7 diff --git a/tests/ui/derived-errors/issue-30580.stderr b/tests/ui/derived-errors/issue-30580.stderr index 7bd0eaf77a95d..146ffd7dd6564 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` + | ^ + | +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/issue-36798.stderr b/tests/ui/did_you_mean/issue-36798.stderr index 98876e305ca09..354aef4047bd6 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` + | ^^^ + | +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-42599_available_fields_note.stderr b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr index a4c3512eb411f..d830564bc3769 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 @@ -16,7 +16,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` + | ^^^^^^^^^^^^^^^^^^^^^ + | +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/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr index b21b6fdfcf1f2..ee15147ba3e92 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` + | ^ + | +help: a field with a similar name exists + | +LL | y.0; + | ~ error: aborting due to previous error 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 193c5aaf72dd0..0edaeca8a8832 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` + | ^^ + | +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/structs/struct-fields-typo.stderr b/tests/ui/structs/struct-fields-typo.stderr index 6949a0a4a6828..8423e7a97a05c 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` + | ^^^ + | +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..f80c2383ef8d0 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` + | ^ + | +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/suggestions/suggest-field-through-deref.fixed b/tests/ui/suggestions/suggest-field-through-deref.fixed index a0f20e563f358..07ba3aa911f4e 100644 --- a/tests/ui/suggestions/suggest-field-through-deref.fixed +++ b/tests/ui/suggestions/suggest-field-through-deref.fixed @@ -10,4 +10,12 @@ fn main() { 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 index 729e5db05525e..6e24b425e9565 100644 --- a/tests/ui/suggestions/suggest-field-through-deref.rs +++ b/tests/ui/suggestions/suggest-field-through-deref.rs @@ -10,4 +10,12 @@ fn main() { 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 index 649e28be51d10..f12d53448d3ce 100644 --- a/tests/ui/suggestions/suggest-field-through-deref.stderr +++ b/tests/ui/suggestions/suggest-field-through-deref.stderr @@ -2,14 +2,68 @@ error[E0609]: no field `longname` on type `Arc` --> $DIR/suggest-field-through-deref.rs:10:15 | LL | let _ = x.longname; - | ^^^^^^^^ help: a field with a similar name exists: `long_name` + | ^^^^^^^^ + | +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; - | ^^^^^^^^ help: a field with a similar name exists: `long_name` + | ^^^^^^^^ + | +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; + | ^^^^^^^^ + | +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; + | ^^^^^^^^^ + | +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; + | ^^^^^^^^ + | +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; + | ^^^^^^^^^ + | +help: one of the expressions' fields has a field of the same name + | +LL | let _ = d.unwrap().long_name; + | +++++++++ -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0609`. diff --git a/tests/ui/tuple/tuple-index-not-tuple.stderr b/tests/ui/tuple/tuple-index-not-tuple.stderr index cc94a61ae7fbb..0f81f2a1bb88b 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` + | ^ + | +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..7fc8289aaa0ba 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,7 +2,12 @@ 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` + | ^ + | +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 diff --git a/tests/ui/union/union-suggest-field.mirunsafeck.stderr b/tests/ui/union/union-suggest-field.mirunsafeck.stderr index 58b1f5cb0786a..805f84da388bc 100644 --- a/tests/ui/union/union-suggest-field.mirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -8,7 +8,12 @@ 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` + | ^^^^^^^^^^ + | +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..805f84da388bc 100644 --- a/tests/ui/union/union-suggest-field.thirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -8,7 +8,12 @@ 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` + | ^^^^^^^^^^ + | +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 From 4f7dddd4a177c761f8576e6c1fedfd73db8bfe7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 9 Nov 2023 06:01:10 +0000 Subject: [PATCH 09/17] recover primary span label --- compiler/rustc_hir_typeck/src/expr.rs | 18 ++++++++++----- ...uggest-switching-edition-on-await-cargo.rs | 4 ++++ ...st-switching-edition-on-await-cargo.stderr | 14 ++++++------ .../suggest-switching-edition-on-await.rs | 4 ++++ .../suggest-switching-edition-on-await.stderr | 14 ++++++------ tests/ui/derived-errors/issue-30580.stderr | 2 +- .../dont-suggest-doc-hidden-fields.rs | 3 +++ .../dont-suggest-doc-hidden-fields.stderr | 10 ++++----- .../dont-suggest-hygienic-fields.stderr | 6 ++--- tests/ui/did_you_mean/issue-36798.stderr | 2 +- .../issue-36798_unknown_field.stderr | 2 +- .../issue-42599_available_fields_note.stderr | 4 ++-- .../error-codes/E0609-private-method.stderr | 2 +- tests/ui/error-codes/E0609.stderr | 4 ++-- tests/ui/error-codes/ex-E0612.stderr | 2 +- tests/ui/infinite/infinite-autoderef.stderr | 2 +- tests/ui/issues/issue-11004.stderr | 6 +++-- tests/ui/issues/issue-13847.stderr | 2 +- tests/ui/issues/issue-14721.stderr | 2 +- tests/ui/issues/issue-19244-1.stderr | 2 +- tests/ui/issues/issue-19244-2.stderr | 2 +- tests/ui/issues/issue-23253.stderr | 2 +- tests/ui/issues/issue-24365.stderr | 6 ++--- tests/ui/issues/issue-31011.stderr | 2 +- tests/ui/issues/issue-33525.stderr | 4 ++-- ...73-zero-padded-tuple-struct-indices.stderr | 4 ++-- tests/ui/mismatched_types/cast-rfc0401.stderr | 2 +- tests/ui/parser/float-field.stderr | 22 +++++++++---------- tests/ui/structs/struct-fields-typo.stderr | 2 +- .../structs/struct-pat-derived-error.stderr | 2 +- tests/ui/suggestions/call-on-missing.stderr | 6 ++--- .../field-access-considering-privacy.stderr | 2 +- ...present-in-subfield-recursion-limit.stderr | 2 +- ...-existent-field-present-in-subfield.stderr | 4 ++-- .../parenthesized-deref-suggestion.stderr | 5 +++-- tests/ui/suggestions/private-field.stderr | 2 +- .../suggest-field-through-deref.stderr | 12 +++++----- .../too-many-field-suggestions.stderr | 2 +- tests/ui/tuple/index-invalid.stderr | 6 ++--- tests/ui/tuple/tuple-index-not-tuple.stderr | 4 ++-- .../ui/tuple/tuple-index-out-of-bounds.stderr | 4 ++-- ...82-type-param-shadows-existing-type.stderr | 16 +++++++------- tests/ui/typeck/issue-53712.stderr | 3 ++- tests/ui/typeck/issue-65611.stderr | 2 +- tests/ui/typeck/issue-67971.stderr | 2 +- .../ui/typeck/issue-87181/tuple-field.stderr | 2 +- tests/ui/typeck/issue-96738.stderr | 2 +- tests/ui/typeck/no-type-for-node-ice.stderr | 2 +- .../union-suggest-field.mirunsafeck.stderr | 2 +- .../union-suggest-field.thirunsafeck.stderr | 2 +- tests/ui/unsafe/unsafe-fn-autoderef.stderr | 3 ++- 51 files changed, 131 insertions(+), 107 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 264b96af6dac2..c5a312a660511 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2418,9 +2418,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_ident: Ident, base: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, - ) { + ) -> bool { let Some(output_ty) = self.get_impl_future_output_ty(ty) else { - return; + return false; }; let mut add_label = true; if let ty::Adt(def, _) = output_ty.kind() { @@ -2449,6 +2449,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if add_label { err.span_label(field_ident.span, format!("field not found in `{ty}`")); } + true } fn ban_nonexisting_field( @@ -2464,20 +2465,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let mut err = self.no_such_field_err(ident, base_ty, base.hir_id); - match *base_ty.peel_refs().kind() { + let has_label = match *base_ty.peel_refs().kind() { ty::Array(_, len) => { self.maybe_suggest_array_indexing(&mut err, expr, base, ident, len); + false } ty::RawPtr(..) => { self.suggest_first_deref_field(&mut err, expr, base, ident); + false } ty::Param(param_ty) => { self.point_at_param_definition(&mut err, param_ty); + false } ty::Alias(ty::Opaque, _) => { - self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); + self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()) } - _ => {} + _ => false, + }; + + if !has_label { + err.span_label(ident.span, "unknown field"); } self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { 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 051e6afd7a725..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 @@ -10,6 +10,7 @@ fn await_on_struct_missing() { let x = S; 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 @@ -22,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` @@ -31,6 +33,7 @@ fn await_on_struct_similar() { fn await_on_63533(x: Pin<&mut dyn 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 @@ -39,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 ebd117f506cd4..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 @@ -2,17 +2,17 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7 | LL | x.await; - | ^^^^^ + | ^^^^^ 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 error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:23:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:24:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: set `edition = "2021"` in `Cargo.toml` @@ -23,20 +23,20 @@ LL | x.awai; | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:32:7 + --> $DIR/suggest-switching-edition-on-await-cargo.rs:34:7 | LL | x.await; - | ^^^^^ + | ^^^^^ 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 error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await-cargo.rs:40: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 4b62713d1b23e..10e245796ee3c 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.rs +++ b/tests/ui/async-await/suggest-switching-edition-on-await.rs @@ -8,6 +8,7 @@ fn await_on_struct_missing() { let x = S; 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 @@ -20,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` @@ -29,6 +31,7 @@ fn await_on_struct_similar() { fn await_on_63533(x: Pin<&mut dyn 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 @@ -37,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 82c5b107b0571..0ed256b059ffe 100644 --- a/tests/ui/async-await/suggest-switching-edition-on-await.stderr +++ b/tests/ui/async-await/suggest-switching-edition-on-await.stderr @@ -2,17 +2,17 @@ error[E0609]: no field `await` on type `await_on_struct_missing::S` --> $DIR/suggest-switching-edition-on-await.rs:9:7 | LL | x.await; - | ^^^^^ + | ^^^^^ 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 error[E0609]: no field `await` on type `await_on_struct_similar::S` - --> $DIR/suggest-switching-edition-on-await.rs:21:7 + --> $DIR/suggest-switching-edition-on-await.rs:22:7 | LL | x.await; - | ^^^^^ + | ^^^^^ unknown field | = note: to `.await` a `Future`, switch to Rust 2018 or later = help: pass `--edition 2021` to `rustc` @@ -23,20 +23,20 @@ LL | x.awai; | ~~~~ error[E0609]: no field `await` on type `Pin<&mut dyn Future>` - --> $DIR/suggest-switching-edition-on-await.rs:30:7 + --> $DIR/suggest-switching-edition-on-await.rs:32:7 | LL | x.await; - | ^^^^^ + | ^^^^^ 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 error[E0609]: no field `await` on type `impl Future` - --> $DIR/suggest-switching-edition-on-await.rs:38: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/derived-errors/issue-30580.stderr b/tests/ui/derived-errors/issue-30580.stderr index 146ffd7dd6564..4e60368c387cf 100644 --- a/tests/ui/derived-errors/issue-30580.stderr +++ b/tests/ui/derived-errors/issue-30580.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `c` on type `&Foo` --> $DIR/issue-30580.rs:12:11 | LL | b.c; - | ^ + | ^ unknown field | help: a field with a similar name exists | 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 36a7066e72e12..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 @@ -21,15 +21,18 @@ fn main() { // `doc(hidden)` because it's defined in this crate. A::default().hey; //~^ ERROR no field `hey` on type `A` + //~| NOTE unknown field //~| NOTE available fields are: `hello`, `bye` // Here we want to hide the field `hello` since it's marked // `doc(hidden)` and comes from an external crate. doc_hidden_fields::B::default().hey; //~^ ERROR no field `hey` on type `B` + //~| NOTE unknown field //~| NOTE available field is: `bye` C::default().hey; //~^ ERROR no field `hey` on type `C` + //~| NOTE unknown field //~| NOTE available fields are: `hello`, `bye` } 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 abded80066ac3..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 @@ -2,23 +2,23 @@ error[E0609]: no field `hey` on type `A` --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18 | LL | A::default().hey; - | ^^^ + | ^^^ unknown field | = note: available fields are: `hello`, `bye` error[E0609]: no field `hey` on type `B` - --> $DIR/dont-suggest-doc-hidden-fields.rs:28:37 + --> $DIR/dont-suggest-doc-hidden-fields.rs:29:37 | LL | doc_hidden_fields::B::default().hey; - | ^^^ + | ^^^ unknown field | = note: available field is: `bye` error[E0609]: no field `hey` on type `C` - --> $DIR/dont-suggest-doc-hidden-fields.rs:32:18 + --> $DIR/dont-suggest-doc-hidden-fields.rs:34:18 | LL | C::default().hey; - | ^^^ + | ^^^ unknown field | = note: available fields are: `hello`, `bye` 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 414590873da21..7066d29760e7c 100644 --- a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -13,13 +13,13 @@ error[E0609]: no field `field` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:24:16 | LL | let _ = ty.field; - | ^^^^^ + | ^^^^^ unknown field error[E0609]: no field `fieeld` on type `Compound` --> $DIR/dont-suggest-hygienic-fields.rs:25:16 | LL | let _ = ty.fieeld; - | ^^^^^^ + | ^^^^^^ unknown field error[E0026]: struct `Compound` does not have a field named `field` --> $DIR/dont-suggest-hygienic-fields.rs:27:20 @@ -42,7 +42,7 @@ error[E0609]: no field `0` on type `Component` --> $DIR/dont-suggest-hygienic-fields.rs:34:16 | LL | let _ = ty.0; - | ^ + | ^ unknown field error: aborting due to 6 previous errors diff --git a/tests/ui/did_you_mean/issue-36798.stderr b/tests/ui/did_you_mean/issue-36798.stderr index 354aef4047bd6..9f82d4c44cf0a 100644 --- a/tests/ui/did_you_mean/issue-36798.stderr +++ b/tests/ui/did_you_mean/issue-36798.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `baz` on type `Foo` --> $DIR/issue-36798.rs:7:7 | LL | f.baz; - | ^^^ + | ^^^ unknown field | help: a field with a similar name exists | 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 4854a9bdeb844..4f216568979ab 100644 --- a/tests/ui/did_you_mean/issue-36798_unknown_field.stderr +++ b/tests/ui/did_you_mean/issue-36798_unknown_field.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `zz` on type `Foo` --> $DIR/issue-36798_unknown_field.rs:7:7 | LL | f.zz; - | ^^ + | ^^ unknown field | = note: available field is: `bar` 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 d830564bc3769..bcd1a00a4bb58 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 @@ -16,7 +16,7 @@ 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; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ unknown field | help: a field with a similar name exists | @@ -27,7 +27,7 @@ error[E0609]: no field `egregiously_nonexistent_field` on type `Demo` --> $DIR/issue-42599_available_fields_note.rs:35:42 | LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field | = note: available fields are: `favorite_integer`, `innocently_misspellable` diff --git a/tests/ui/error-codes/E0609-private-method.stderr b/tests/ui/error-codes/E0609-private-method.stderr index a2bfcca5e0b8b..d2a11e9062740 100644 --- a/tests/ui/error-codes/E0609-private-method.stderr +++ b/tests/ui/error-codes/E0609-private-method.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `method` on type `Foo` --> $DIR/E0609-private-method.rs:15:7 | LL | f.method; - | ^^^^^^ + | ^^^^^^ unknown field error: aborting due to previous error diff --git a/tests/ui/error-codes/E0609.stderr b/tests/ui/error-codes/E0609.stderr index 78a61b92c5c8e..cad857553da30 100644 --- a/tests/ui/error-codes/E0609.stderr +++ b/tests/ui/error-codes/E0609.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `foo` on type `Foo` --> $DIR/E0609.rs:8:15 | LL | let _ = x.foo; - | ^^^ + | ^^^ unknown field | = note: available field is: `x` @@ -10,7 +10,7 @@ error[E0609]: no field `1` on type `Bar` --> $DIR/E0609.rs:11:7 | LL | y.1; - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr index ee15147ba3e92..4dd9848cf07b6 100644 --- a/tests/ui/error-codes/ex-E0612.stderr +++ b/tests/ui/error-codes/ex-E0612.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `1` on type `Foo` --> $DIR/ex-E0612.rs:5:6 | LL | y.1; - | ^ + | ^ unknown field | help: a field with a similar name exists | diff --git a/tests/ui/infinite/infinite-autoderef.stderr b/tests/ui/infinite/infinite-autoderef.stderr index 1fa53beba6853..51b61e3a66bb4 100644 --- a/tests/ui/infinite/infinite-autoderef.stderr +++ b/tests/ui/infinite/infinite-autoderef.stderr @@ -29,7 +29,7 @@ error[E0609]: no field `foo` on type `Foo` --> $DIR/infinite-autoderef.rs:24:9 | LL | Foo.foo; - | ^^^ + | ^^^ unknown field error[E0055]: reached the recursion limit while auto-dereferencing `Foo` --> $DIR/infinite-autoderef.rs:25:9 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 933371d1e89d6..71655457f9018 100644 --- a/tests/ui/issues/issue-19244-2.stderr +++ b/tests/ui/issues/issue-19244-2.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct` --> $DIR/issue-19244-2.rs:5:27 | LL | let a: [isize; STRUCT.nonexistent_field]; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ unknown field | = note: available field is: `field` 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 0edaeca8a8832..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,7 @@ error[E0609]: no field `00` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:8:30 | LL | let _condemned = justice.00; - | ^^ + | ^^ unknown field | help: a field with a similar name exists | @@ -13,7 +13,7 @@ error[E0609]: no field `001` on type `Verdict` --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 | LL | let _punishment = justice.001; - | ^^^ + | ^^^ unknown field | = note: available fields are: `0`, `1` 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/parser/float-field.stderr b/tests/ui/parser/float-field.stderr index a81992c338097..d67d270ef7b93 100644 --- a/tests/ui/parser/float-field.stderr +++ b/tests/ui/parser/float-field.stderr @@ -266,7 +266,7 @@ error[E0609]: no field `1e1` on type `S` --> $DIR/float-field.rs:6:7 | LL | s.1e1; - | ^^^ + | ^^^ unknown field | = note: available fields are: `0`, `1` @@ -274,13 +274,13 @@ 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 | LL | s.0x1e1; - | ^^^^^ + | ^^^^^ unknown field | = note: available fields are: `0`, `1` @@ -288,7 +288,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:25:7 | LL | s.0x1.; - | ^^^ + | ^^^ unknown field | = note: available fields are: `0`, `1` @@ -296,7 +296,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:28:7 | LL | s.0x1.1; - | ^^^ + | ^^^ unknown field | = note: available fields are: `0`, `1` @@ -304,7 +304,7 @@ error[E0609]: no field `0x1` on type `S` --> $DIR/float-field.rs:30:7 | LL | s.0x1.1e1; - | ^^^ + | ^^^ unknown field | = note: available fields are: `0`, `1` @@ -312,7 +312,7 @@ error[E0609]: no field `0x1e` on type `S` --> $DIR/float-field.rs:34:7 | LL | s.0x1e+1; - | ^^^^ + | ^^^^ unknown field | = note: available fields are: `0`, `1` @@ -320,7 +320,7 @@ error[E0609]: no field `0x1e` on type `S` --> $DIR/float-field.rs:35:7 | LL | s.0x1e-1; - | ^^^^ + | ^^^^ unknown field | = note: available fields are: `0`, `1` @@ -328,7 +328,7 @@ error[E0609]: no field `1e1` on type `S` --> $DIR/float-field.rs:42:7 | LL | s.1e1f32; - | ^^^^^^ + | ^^^^^^ unknown field | = note: available fields are: `0`, `1` @@ -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/structs/struct-fields-typo.stderr b/tests/ui/structs/struct-fields-typo.stderr index 8423e7a97a05c..aef0e0e8e5ca5 100644 --- a/tests/ui/structs/struct-fields-typo.stderr +++ b/tests/ui/structs/struct-fields-typo.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `baa` on type `BuildData` --> $DIR/struct-fields-typo.rs:11:17 | LL | let x = foo.baa; - | ^^^ + | ^^^ unknown field | help: a field with a similar name exists | diff --git a/tests/ui/structs/struct-pat-derived-error.stderr b/tests/ui/structs/struct-pat-derived-error.stderr index f80c2383ef8d0..78bb018cb4be7 100644 --- a/tests/ui/structs/struct-pat-derived-error.stderr +++ b/tests/ui/structs/struct-pat-derived-error.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `d` on type `&A` --> $DIR/struct-pat-derived-error.rs:8:31 | LL | let A { x, y } = self.d; - | ^ + | ^ unknown field | help: a field with a similar name exists | diff --git a/tests/ui/suggestions/call-on-missing.stderr b/tests/ui/suggestions/call-on-missing.stderr index 2824343c9134b..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 | @@ -35,7 +35,7 @@ error[E0609]: no field `i` on type `Box Foo>` --> $DIR/call-on-missing.rs:26:14 | LL | callable.i; - | ^ + | ^ unknown field | help: use parentheses to call this trait object | @@ -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/field-access-considering-privacy.stderr b/tests/ui/suggestions/field-access-considering-privacy.stderr index 5bbcfeea4747f..cbf6f3d100258 100644 --- a/tests/ui/suggestions/field-access-considering-privacy.stderr +++ b/tests/ui/suggestions/field-access-considering-privacy.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `TyCtxt<'tcx>` --> $DIR/field-access-considering-privacy.rs:29:13 | LL | tcx.opts; - | ^^^^ + | ^^^^ unknown field | help: one of the expressions' fields has a field of the same name | diff --git a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr index f4010b39dc46c..b294f4da7db33 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield-recursion-limit.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `f` on type `Foo` --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22 | LL | let test = fooer.f; - | ^ + | ^ unknown field | = note: available fields are: `first`, `second`, `third` 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 c3e4014503891..65353ed923e0e 100644 --- a/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr +++ b/tests/ui/suggestions/non-existent-field-present-in-subfield.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `c` on type `Foo` --> $DIR/non-existent-field-present-in-subfield.rs:37:24 | LL | let _test = &fooer.c; - | ^ + | ^ unknown field | help: one of the expressions' fields has a field of the same name | @@ -13,7 +13,7 @@ error[E0609]: no field `test` on type `Foo` --> $DIR/non-existent-field-present-in-subfield.rs:40:24 | LL | let _test2 = fooer.test; - | ^^^^ + | ^^^^ unknown field | help: one of the expressions' fields has a field of the same name | 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 6a735a163b896..0db426588bd2f 100644 --- a/tests/ui/suggestions/private-field.stderr +++ b/tests/ui/suggestions/private-field.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `cap` on type `S` --> $DIR/private-field.rs:7:12 | LL | dbg!(s.cap) - | ^^^ + | ^^^ unknown field | = note: available field is: `val` diff --git a/tests/ui/suggestions/suggest-field-through-deref.stderr b/tests/ui/suggestions/suggest-field-through-deref.stderr index f12d53448d3ce..cc9fe2044c91e 100644 --- a/tests/ui/suggestions/suggest-field-through-deref.stderr +++ b/tests/ui/suggestions/suggest-field-through-deref.stderr @@ -2,7 +2,7 @@ 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 | @@ -13,7 +13,7 @@ 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 | @@ -24,7 +24,7 @@ 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 | @@ -35,7 +35,7 @@ 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 | @@ -46,7 +46,7 @@ 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 | @@ -57,7 +57,7 @@ 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 | diff --git a/tests/ui/suggestions/too-many-field-suggestions.stderr b/tests/ui/suggestions/too-many-field-suggestions.stderr index b556bdda3f633..ac5c8cb60ccdc 100644 --- a/tests/ui/suggestions/too-many-field-suggestions.stderr +++ b/tests/ui/suggestions/too-many-field-suggestions.stderr @@ -23,7 +23,7 @@ error[E0609]: no field `field` on type `Thing` --> $DIR/too-many-field-suggestions.rs:26:7 | LL | t.field; - | ^^^^^ + | ^^^^^ unknown field | help: some of the expressions' fields have a field of the same name | 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 0f81f2a1bb88b..a267e41b1bc32 100644 --- a/tests/ui/tuple/tuple-index-not-tuple.stderr +++ b/tests/ui/tuple/tuple-index-not-tuple.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `0` on type `Point` --> $DIR/tuple-index-not-tuple.rs:6:12 | LL | origin.0; - | ^ + | ^ unknown field | help: a field with a similar name exists | @@ -13,7 +13,7 @@ error[E0609]: no field `0` on type `Empty` --> $DIR/tuple-index-not-tuple.rs:8:11 | LL | Empty.0; - | ^ + | ^ unknown field error: aborting due to 2 previous errors diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr index 7fc8289aaa0ba..96090435d06be 100644 --- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr +++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `2` on type `Point` --> $DIR/tuple-index-out-of-bounds.rs:7:12 | LL | origin.2; - | ^ + | ^ unknown field | help: a field with a similar name exists | @@ -13,7 +13,7 @@ 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-67971.stderr b/tests/ui/typeck/issue-67971.stderr index 4ae0f5d1c5c02..d50ed9cf13bb4 100644 --- a/tests/ui/typeck/issue-67971.stderr +++ b/tests/ui/typeck/issue-67971.stderr @@ -2,7 +2,7 @@ error[E0609]: no field `sleep` on type `&mut S` --> $DIR/issue-67971.rs:5:9 | LL | ctx.sleep = 0; - | ^^^^^ + | ^^^^^ unknown field error[E0308]: mismatched types --> $DIR/issue-67971.rs:3:24 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 805f84da388bc..709210493994c 100644 --- a/tests/ui/union/union-suggest-field.mirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ + | ^^^^^^^^^^ unknown field | help: a field with a similar name exists | diff --git a/tests/ui/union/union-suggest-field.thirunsafeck.stderr b/tests/ui/union/union-suggest-field.thirunsafeck.stderr index 805f84da388bc..709210493994c 100644 --- a/tests/ui/union/union-suggest-field.thirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -8,7 +8,7 @@ error[E0609]: no field `principial` on type `U` --> $DIR/union-suggest-field.rs:17:15 | LL | let w = u.principial; - | ^^^^^^^^^^ + | ^^^^^^^^^^ unknown field | help: a field with a similar name exists | 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 From 6a2d9b45c4c24ed431f07bc35c58e277cf864fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 15 Nov 2023 18:18:42 +0000 Subject: [PATCH 10/17] address review comment --- compiler/rustc_hir_typeck/src/expr.rs | 25 +++++++------------------ tests/ui/async-await/issue-61076.rs | 2 ++ tests/ui/async-await/issue-61076.stderr | 16 +++++++++++----- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index c5a312a660511..7e235ea7f463a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2418,11 +2418,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field_ident: Ident, base: &'tcx hir::Expr<'tcx>, ty: Ty<'tcx>, - ) -> bool { + ) { let Some(output_ty) = self.get_impl_future_output_ty(ty) else { - return false; + return; }; - let mut add_label = true; if let ty::Adt(def, _) = output_ty.kind() { // no field access on enum type if !def.is_enum() { @@ -2432,7 +2431,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .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`", @@ -2446,10 +2444,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - if add_label { - err.span_label(field_ident.span, format!("field not found in `{ty}`")); - } - true } fn ban_nonexisting_field( @@ -2465,29 +2459,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let mut err = self.no_such_field_err(ident, base_ty, base.hir_id); - let has_label = match *base_ty.peel_refs().kind() { + match *base_ty.peel_refs().kind() { ty::Array(_, len) => { self.maybe_suggest_array_indexing(&mut err, expr, base, ident, len); - false } ty::RawPtr(..) => { self.suggest_first_deref_field(&mut err, expr, base, ident); - false } ty::Param(param_ty) => { self.point_at_param_definition(&mut err, param_ty); - false } ty::Alias(ty::Opaque, _) => { - self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()) + self.suggest_await_on_field_access(&mut err, ident, base, base_ty.peel_refs()); } - _ => false, - }; - - if !has_label { - err.span_label(ident.span, "unknown field"); + _ => {} } + err.span_label(ident.span, "unknown field"); + self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs index cf6e5b4e436f2..ef6a7055c7843 100644 --- a/tests/ui/async-await/issue-61076.rs +++ b/tests/ui/async-await/issue-61076.rs @@ -71,10 +71,12 @@ async fn baz() -> Result<(), ()> { let _: i32 = tuple().0; //~ ERROR no field `0` //~^ HELP consider `await`ing on the `Future` //~| NOTE field not available in `impl Future` + //~| NOTE unknown field let _: i32 = struct_().a; //~ ERROR no field `a` //~^ HELP consider `await`ing on the `Future` //~| NOTE field not available in `impl Future` + //~| NOTE unknown field struct_().method(); //~ ERROR no method named //~^ NOTE method not found in `impl Future` diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr index 44de282988baa..13a0464fdb2dd 100644 --- a/tests/ui/async-await/issue-61076.stderr +++ b/tests/ui/async-await/issue-61076.stderr @@ -26,7 +26,10 @@ error[E0609]: no field `0` on type `impl Future` --> $DIR/issue-61076.rs:71:26 | LL | let _: i32 = tuple().0; - | ^ field not available in `impl Future`, but it is available in its `Output` + | ^ + | | + | field not available in `impl Future`, but it is available in its `Output` + | unknown field | help: consider `await`ing on the `Future` and access the field of its `Output` | @@ -34,10 +37,13 @@ LL | let _: i32 = tuple().await.0; | ++++++ error[E0609]: no field `a` on type `impl Future` - --> $DIR/issue-61076.rs:75:28 + --> $DIR/issue-61076.rs:76:28 | LL | let _: i32 = struct_().a; - | ^ field not available in `impl Future`, but it is available in its `Output` + | ^ + | | + | field not available in `impl Future`, but it is available in its `Output` + | unknown field | help: consider `await`ing on the `Future` and access the field of its `Output` | @@ -45,7 +51,7 @@ LL | let _: i32 = struct_().await.a; | ++++++ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope - --> $DIR/issue-61076.rs:79:15 + --> $DIR/issue-61076.rs:81:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` @@ -56,7 +62,7 @@ LL | struct_().await.method(); | ++++++ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:88:9 + --> $DIR/issue-61076.rs:90:9 | LL | match tuple() { | ------- this expression has type `impl Future` From 1ee37bf03f56b1760a6a866cfeb53b14c9692cdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 16 Nov 2023 17:00:40 +0000 Subject: [PATCH 11/17] let-chain fmt --- compiler/rustc_hir_typeck/src/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 7e235ea7f463a..00499041f2ed2 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2685,8 +2685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mod_id = self.tcx.parent_module(id).to_def_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()) - ) + || self.tcx.is_diagnostic_item(sym::Option, def.did())) && let Some(arg) = args.get(0) && let Some(ty) = arg.as_type() { From 19848d5db4b4f057a027f596a97cf8fcde8a5c75 Mon Sep 17 00:00:00 2001 From: Carl Scherer Date: Fri, 17 Nov 2023 22:43:30 +0100 Subject: [PATCH 12/17] Fix links for std::process::Child{Stdin, Stdout, Stderr} --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) From b408efed5ebdda89419fc41e70020c6e9fdf1c24 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Oct 2023 09:39:33 +0000 Subject: [PATCH 13/17] Remove mir::Const::from_anon_const --- compiler/rustc_middle/src/mir/consts.rs | 102 +------------------ compiler/rustc_middle/src/ty/consts.rs | 4 + compiler/rustc_mir_build/src/thir/cx/expr.rs | 26 ++++- 3 files changed, 29 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index a9d09709e8427..63c01f938821c 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -1,17 +1,16 @@ use std::fmt::{self, Debug, Display, Formatter}; use rustc_hir; -use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir}; +use rustc_hir::def_id::DefId; use rustc_session::RemapFileNameExt; use rustc_span::Span; use rustc_target::abi::{HasDataLayout, Size}; use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar}; use crate::mir::{pretty_print_const_value, Promoted}; +use crate::ty::GenericArgsRef; use crate::ty::ScalarInt; -use crate::ty::{self, print::pretty_print_const, List, Ty, TyCtxt}; -use crate::ty::{GenericArgs, GenericArgsRef}; +use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt}; /////////////////////////////////////////////////////////////////////////// /// Evaluated Constants @@ -399,101 +398,6 @@ impl<'tcx> Const<'tcx> { Self::Val(val, ty) } - /// Literals are converted to `Const::Val`, const generic parameters are eagerly - /// converted to a constant, everything else becomes `Unevaluated`. - #[instrument(skip(tcx), level = "debug", ret)] - pub fn from_anon_const( - tcx: TyCtxt<'tcx>, - def: LocalDefId, - param_env: ty::ParamEnv<'tcx>, - ) -> Self { - let body_id = match tcx.hir().get_by_def_id(def) { - hir::Node::AnonConst(ac) => ac.body, - _ => { - span_bug!(tcx.def_span(def), "from_anon_const can only process anonymous constants") - } - }; - - let expr = &tcx.hir().body(body_id).value; - debug!(?expr); - - // Unwrap a block, so that e.g. `{ P }` is recognised as a parameter. Const arguments - // currently have to be wrapped in curly brackets, so it's necessary to special-case. - let expr = match &expr.kind { - hir::ExprKind::Block(block, _) if block.stmts.is_empty() && block.expr.is_some() => { - block.expr.as_ref().unwrap() - } - _ => expr, - }; - debug!("expr.kind: {:?}", expr.kind); - - let ty = tcx.type_of(def).instantiate_identity(); - debug!(?ty); - - // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` - // does not provide the parents generics to anonymous constants. We still allow generic const - // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to - // ever try to substitute the generic parameters in their bodies. - // - // While this doesn't happen as these constants are always used as `ty::ConstKind::Param`, it does - // cause issues if we were to remove that special-case and try to evaluate the constant instead. - use hir::{def::DefKind::ConstParam, def::Res, ExprKind, Path, QPath}; - match expr.kind { - ExprKind::Path(QPath::Resolved(_, &Path { res: Res::Def(ConstParam, def_id), .. })) => { - // Find the name and index of the const parameter by indexing the generics of - // the parent item and construct a `ParamConst`. - let item_def_id = tcx.parent(def_id); - let generics = tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = tcx.item_name(def_id); - let ty_const = ty::Const::new_param(tcx, ty::ParamConst::new(index, name), ty); - debug!(?ty_const); - - return Self::Ty(ty_const); - } - _ => {} - } - - let hir_id = tcx.hir().local_def_id_to_hir_id(def); - let parent_args = if let Some(parent_hir_id) = tcx.hir().opt_parent_id(hir_id) - && let Some(parent_did) = parent_hir_id.as_owner() - { - GenericArgs::identity_for_item(tcx, parent_did) - } else { - List::empty() - }; - debug!(?parent_args); - - let did = def.to_def_id(); - let child_args = GenericArgs::identity_for_item(tcx, did); - let args = tcx.mk_args_from_iter(parent_args.into_iter().chain(child_args.into_iter())); - debug!(?args); - - let span = tcx.def_span(def); - let uneval = UnevaluatedConst::new(did, args); - debug!(?span, ?param_env); - - match tcx.const_eval_resolve(param_env, uneval, Some(span)) { - Ok(val) => { - debug!("evaluated const value"); - Self::Val(val, ty) - } - Err(_) => { - debug!("error encountered during evaluation"); - // Error was handled in `const_eval_resolve`. Here we just create a - // new unevaluated const and error hard later in codegen - Self::Unevaluated( - UnevaluatedConst { - def: did, - args: GenericArgs::identity_for_item(tcx, did), - promoted: None, - }, - ty, - ) - } - } - } - pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { match c.kind() { ty::ConstKind::Value(valtree) => { diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index af5ffc20d489c..97e7ccb801d92 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -207,6 +207,10 @@ impl<'tcx> Const<'tcx> { } } + // FIXME(const_generics): We currently have to special case parameters because `min_const_generics` + // does not provide the parents generics to anonymous constants. We still allow generic const + // parameters by themselves however, e.g. `N`. These constants would cause an ICE if we were to + // ever try to substitute the generic parameters in their bodies. match expr.kind { hir::ExprKind::Path(hir::QPath::Resolved( _, diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 50f57b28a983a..c33dad2ada814 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -645,15 +645,33 @@ impl<'tcx> Cx<'tcx> { out_expr: out_expr.map(|expr| self.mirror_expr(expr)), }, hir::InlineAsmOperand::Const { ref anon_const } => { - let value = - mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); + let value = mir::Const::Unevaluated( + mir::UnevaluatedConst { + def: anon_const.def_id.to_def_id(), + args: GenericArgs::identity_for_item( + self.tcx, + anon_const.def_id, + ), + promoted: None, + }, + tcx.type_of(anon_const.def_id).instantiate_identity(), + ); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = - mir::Const::from_anon_const(tcx, anon_const.def_id, self.param_env); + let value = mir::Const::Unevaluated( + mir::UnevaluatedConst { + def: anon_const.def_id.to_def_id(), + args: GenericArgs::identity_for_item( + self.tcx, + anon_const.def_id, + ), + promoted: None, + }, + tcx.type_of(anon_const.def_id).instantiate_identity(), + ); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::SymFn { value, span } From 4c0a9ef19751c864a0b0cd6030d25c98ca0b8dea Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 5 Oct 2023 09:43:55 +0000 Subject: [PATCH 14/17] make sure we still eagerly emit errors --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 6 ++++-- tests/ui/asm/const-error.rs | 12 ++++++++++++ tests/ui/asm/const-error.stderr | 9 +++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/ui/asm/const-error.rs create mode 100644 tests/ui/asm/const-error.stderr diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index c33dad2ada814..ea1965574ab4f 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -655,7 +655,8 @@ impl<'tcx> Cx<'tcx> { promoted: None, }, tcx.type_of(anon_const.def_id).instantiate_identity(), - ); + ) + .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::Const { value, span } @@ -671,7 +672,8 @@ impl<'tcx> Cx<'tcx> { promoted: None, }, tcx.type_of(anon_const.def_id).instantiate_identity(), - ); + ) + .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::SymFn { value, span } diff --git a/tests/ui/asm/const-error.rs b/tests/ui/asm/const-error.rs new file mode 100644 index 0000000000000..141af84b49b03 --- /dev/null +++ b/tests/ui/asm/const-error.rs @@ -0,0 +1,12 @@ +#![feature(asm_const)] + +// Test to make sure that we emit const errors eagerly for inline asm + +use std::arch::asm; + +fn test() { + unsafe { asm!("/* {} */", const 1 / 0); } + //~^ ERROR evaluation of +} + +fn main() {} diff --git a/tests/ui/asm/const-error.stderr b/tests/ui/asm/const-error.stderr new file mode 100644 index 0000000000000..c6913c27b7a29 --- /dev/null +++ b/tests/ui/asm/const-error.stderr @@ -0,0 +1,9 @@ +error[E0080]: evaluation of `test::::{constant#0}` failed + --> $DIR/const-error.rs:8:37 + | +LL | unsafe { asm!("/* {} */", const 1 / 0); } + | ^^^^^ attempt to divide `1_i32` by zero + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 6de5ea5422640d91cabd7bd408b443616e2f32d5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 17 Nov 2023 23:49:07 +0000 Subject: [PATCH 15/17] Review comment --- compiler/rustc_middle/src/mir/consts.rs | 11 ++++++++ compiler/rustc_mir_build/src/thir/cx/expr.rs | 28 ++++++-------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 63c01f938821c..2e366995aacb8 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -219,6 +219,17 @@ pub enum Const<'tcx> { } impl<'tcx> Const<'tcx> { + pub fn identity_unevaluated(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::EarlyBinder> { + ty::EarlyBinder::bind(Const::Unevaluated( + UnevaluatedConst { + def: def_id, + args: ty::GenericArgs::identity_for_item(tcx, def_id), + promoted: None, + }, + tcx.type_of(def_id).skip_binder(), + )) + } + #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index ea1965574ab4f..1e45cd975ecb9 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -645,34 +645,22 @@ impl<'tcx> Cx<'tcx> { out_expr: out_expr.map(|expr| self.mirror_expr(expr)), }, hir::InlineAsmOperand::Const { ref anon_const } => { - let value = mir::Const::Unevaluated( - mir::UnevaluatedConst { - def: anon_const.def_id.to_def_id(), - args: GenericArgs::identity_for_item( - self.tcx, - anon_const.def_id, - ), - promoted: None, - }, - tcx.type_of(anon_const.def_id).instantiate_identity(), + let value = mir::Const::identity_unevaluated( + tcx, + anon_const.def_id.to_def_id(), ) + .instantiate_identity() .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); InlineAsmOperand::Const { value, span } } hir::InlineAsmOperand::SymFn { ref anon_const } => { - let value = mir::Const::Unevaluated( - mir::UnevaluatedConst { - def: anon_const.def_id.to_def_id(), - args: GenericArgs::identity_for_item( - self.tcx, - anon_const.def_id, - ), - promoted: None, - }, - tcx.type_of(anon_const.def_id).instantiate_identity(), + let value = mir::Const::identity_unevaluated( + tcx, + anon_const.def_id.to_def_id(), ) + .instantiate_identity() .normalize(tcx, self.param_env); let span = tcx.def_span(anon_const.def_id); From 289ce572b399d55c3d97f5411dbe43817cd7e8e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 18 Nov 2023 00:40:11 +0000 Subject: [PATCH 16/17] tweak logic of "unknown field" label --- compiler/rustc_hir_typeck/src/expr.rs | 56 ++++++++++--------- tests/ui/async-await/issue-61076.rs | 2 - tests/ui/async-await/issue-61076.stderr | 16 ++---- .../dont-suggest-hygienic-fields.stderr | 6 +- .../issue-42599_available_fields_note.stderr | 7 ++- tests/ui/rmeta/rmeta_meta_main.stderr | 7 ++- .../struct-fields-hints-no-dupe.stderr | 7 ++- tests/ui/structs/struct-fields-hints.stderr | 7 ++- .../ui/structs/suggest-private-fields.stderr | 21 ++++++- ...e-mismatch-struct-field-shorthand-2.stderr | 7 ++- .../union-suggest-field.mirunsafeck.stderr | 7 ++- .../union-suggest-field.thirunsafeck.stderr | 7 ++- 12 files changed, 101 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 00499041f2ed2..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,30 +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; }; - 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) - { - 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 !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( @@ -2467,16 +2470,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_first_deref_field(&mut err, expr, base, 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"); + } } - err.span_label(ident.span, "unknown field"); - self.suggest_fn_call(&mut err, base, base_ty, |output_ty| { if let ty::Adt(def, _) = output_ty.kind() && !def.is_enum() @@ -2635,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) @@ -2657,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}"); diff --git a/tests/ui/async-await/issue-61076.rs b/tests/ui/async-await/issue-61076.rs index ef6a7055c7843..cf6e5b4e436f2 100644 --- a/tests/ui/async-await/issue-61076.rs +++ b/tests/ui/async-await/issue-61076.rs @@ -71,12 +71,10 @@ async fn baz() -> Result<(), ()> { let _: i32 = tuple().0; //~ ERROR no field `0` //~^ HELP consider `await`ing on the `Future` //~| NOTE field not available in `impl Future` - //~| NOTE unknown field let _: i32 = struct_().a; //~ ERROR no field `a` //~^ HELP consider `await`ing on the `Future` //~| NOTE field not available in `impl Future` - //~| NOTE unknown field struct_().method(); //~ ERROR no method named //~^ NOTE method not found in `impl Future` diff --git a/tests/ui/async-await/issue-61076.stderr b/tests/ui/async-await/issue-61076.stderr index 13a0464fdb2dd..44de282988baa 100644 --- a/tests/ui/async-await/issue-61076.stderr +++ b/tests/ui/async-await/issue-61076.stderr @@ -26,10 +26,7 @@ error[E0609]: no field `0` on type `impl Future` --> $DIR/issue-61076.rs:71:26 | LL | let _: i32 = tuple().0; - | ^ - | | - | field not available in `impl Future`, but it is available in its `Output` - | unknown field + | ^ field not available in `impl Future`, but it is available in its `Output` | help: consider `await`ing on the `Future` and access the field of its `Output` | @@ -37,13 +34,10 @@ LL | let _: i32 = tuple().await.0; | ++++++ error[E0609]: no field `a` on type `impl Future` - --> $DIR/issue-61076.rs:76:28 + --> $DIR/issue-61076.rs:75:28 | LL | let _: i32 = struct_().a; - | ^ - | | - | field not available in `impl Future`, but it is available in its `Output` - | unknown field + | ^ field not available in `impl Future`, but it is available in its `Output` | help: consider `await`ing on the `Future` and access the field of its `Output` | @@ -51,7 +45,7 @@ LL | let _: i32 = struct_().await.a; | ++++++ error[E0599]: no method named `method` found for opaque type `impl Future` in the current scope - --> $DIR/issue-61076.rs:81:15 + --> $DIR/issue-61076.rs:79:15 | LL | struct_().method(); | ^^^^^^ method not found in `impl Future` @@ -62,7 +56,7 @@ LL | struct_().await.method(); | ++++++ error[E0308]: mismatched types - --> $DIR/issue-61076.rs:90:9 + --> $DIR/issue-61076.rs:88:9 | LL | match tuple() { | ------- this expression has type `impl Future` 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-42599_available_fields_note.stderr b/tests/ui/did_you_mean/issue-42599_available_fields_note.stderr index bcd1a00a4bb58..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 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/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/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/union/union-suggest-field.mirunsafeck.stderr b/tests/ui/union/union-suggest-field.mirunsafeck.stderr index 709210493994c..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.mirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.mirunsafeck.stderr @@ -2,7 +2,12 @@ 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 diff --git a/tests/ui/union/union-suggest-field.thirunsafeck.stderr b/tests/ui/union/union-suggest-field.thirunsafeck.stderr index 709210493994c..efe4987bd0252 100644 --- a/tests/ui/union/union-suggest-field.thirunsafeck.stderr +++ b/tests/ui/union/union-suggest-field.thirunsafeck.stderr @@ -2,7 +2,12 @@ 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 From c653bb9a6b916c8e1c88dca974c937ed364a53cc Mon Sep 17 00:00:00 2001 From: klensy Date: Sat, 18 Nov 2023 12:42:05 +0300 Subject: [PATCH 17/17] jsondocck: bump jsonpath to 0.3, dropping few dup dependencies changes: https://github.com/freestrings/jsonpath/compare/v0.2.6...v0.3.0 self_cell: bump to 0.10.3 due to RUSTSEC-2023-0070 https://rustsec.org/advisories/RUSTSEC-2023-0070.html https://github.com/Voultapher/self_cell/issues/49 bump h2 to 0.3.22, dropping few dup crate versions https://github.com/hyperium/h2/blob/v0.3.22/CHANGELOG.md --- Cargo.lock | 143 +++++++++------------------------ src/tools/jsondocck/Cargo.toml | 2 +- 2 files changed, 41 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9fe70870140d8..ad9e4fcb2d1a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -193,12 +193,6 @@ dependencies = [ "object", ] -[[package]] -name = "array_tool" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f8cb5d814eb646a863c4f24978cff2880c4be96ad8cde2c0f0678732902e271" - [[package]] name = "arrayvec" version = "0.7.4" @@ -237,17 +231,6 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -356,7 +339,7 @@ version = "0.1.0" dependencies = [ "anyhow", "curl", - "indexmap 2.0.0", + "indexmap", "serde", "serde_json", "toml 0.5.11", @@ -739,7 +722,7 @@ dependencies = [ "getopts", "glob", "home", - "indexmap 2.0.0", + "indexmap", "lazycell", "libc", "miow", @@ -1245,26 +1228,13 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "env_logger" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -dependencies = [ - "atty", - "humantime 1.3.0", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" dependencies = [ - "humantime 2.1.0", + "humantime", "is-terminal", "log", "regex", @@ -1378,7 +1348,7 @@ dependencies = [ "intl-memoizer", "intl_pluralrules", "rustc-hash", - "self_cell", + "self_cell 0.10.3", "smallvec", "unic-langid", ] @@ -1608,7 +1578,7 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" dependencies = [ "compiler_builtins", "fallible-iterator", - "indexmap 2.0.0", + "indexmap", "rustc-std-workspace-alloc", "rustc-std-workspace-core", "stable_deref_trait", @@ -1644,9 +1614,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" +checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" dependencies = [ "bytes", "fnv", @@ -1654,7 +1624,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 1.9.3", + "indexmap", "slab", "tokio", "tokio-util", @@ -1675,12 +1645,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - [[package]] name = "hashbrown" version = "0.14.2" @@ -1700,15 +1664,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.2" @@ -1800,15 +1755,6 @@ dependencies = [ "libm", ] -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - [[package]] name = "humantime" version = "2.1.0" @@ -2014,16 +1960,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - [[package]] name = "indexmap" version = "2.0.0" @@ -2031,7 +1967,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" dependencies = [ "equivalent", - "hashbrown 0.14.2", + "hashbrown", "rustc-rayon", "serde", ] @@ -2117,7 +2053,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "rustix", "windows-sys 0.48.0", ] @@ -2193,12 +2129,10 @@ dependencies = [ [[package]] name = "jsonpath_lib" -version = "0.2.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61352ec23883402b7d30b3313c16cbabefb8907361c4eb669d990cbb87ceee5a" +checksum = "eaa63191d68230cccb81c5aa23abd53ed64d83337cacbb25a7b8c7979523774f" dependencies = [ - "array_tool", - "env_logger 0.7.1", "log", "serde", "serde_json", @@ -2416,7 +2350,7 @@ dependencies = [ "clap", "clap_complete", "elasticlunr-rs", - "env_logger 0.10.0", + "env_logger", "handlebars", "log", "memchr", @@ -2541,7 +2475,7 @@ dependencies = [ "aes", "colored", "ctrlc", - "env_logger 0.10.0", + "env_logger", "getrandom", "lazy_static", "libc", @@ -2645,7 +2579,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi", "libc", ] @@ -2664,8 +2598,8 @@ dependencies = [ "compiler_builtins", "crc32fast", "flate2", - "hashbrown 0.14.2", - "indexmap 2.0.0", + "hashbrown", + "indexmap", "memchr", "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -2750,11 +2684,11 @@ dependencies = [ "camino", "clap", "derive_builder", - "env_logger 0.10.0", + "env_logger", "fs_extra", "glob", "humansize", - "humantime 2.1.0", + "humantime", "log", "reqwest", "serde", @@ -3104,12 +3038,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe" -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -3357,7 +3285,7 @@ name = "rustbook" version = "0.1.0" dependencies = [ "clap", - "env_logger 0.10.0", + "env_logger", "mdbook", ] @@ -3741,7 +3669,7 @@ dependencies = [ "bitflags 1.3.2", "elsa", "ena", - "indexmap 2.0.0", + "indexmap", "itertools", "jobserver", "libc", @@ -4503,7 +4431,7 @@ dependencies = [ name = "rustc_serialize" version = "0.0.0" dependencies = [ - "indexmap 2.0.0", + "indexmap", "rustc_macros", "smallvec", "tempfile", @@ -4553,7 +4481,7 @@ dependencies = [ name = "rustc_span" version = "0.0.0" dependencies = [ - "indexmap 2.0.0", + "indexmap", "md-5", "rustc_arena", "rustc_data_structures", @@ -4712,7 +4640,7 @@ dependencies = [ "arrayvec", "askama", "expect-test", - "indexmap 2.0.0", + "indexmap", "itertools", "minifier", "once_cell", @@ -4902,9 +4830,18 @@ dependencies = [ [[package]] name = "self_cell" -version = "0.10.2" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.0.2", +] + +[[package]] +name = "self_cell" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" +checksum = "e388332cd64eb80cd595a00941baf513caffae8dce9cfd0467fc9c66397dade6" [[package]] name = "semver" @@ -4941,7 +4878,7 @@ version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ - "indexmap 2.0.0", + "indexmap", "itoa", "ryu", "serde", @@ -5121,8 +5058,8 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.14.2", - "hermit-abi 0.3.2", + "hashbrown", + "hermit-abi", "libc", "miniz_oxide", "object", @@ -5429,7 +5366,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4db52ee8fec06e119b692ef3dd2c4cf621a99204c1b8c47407870ed050305b9b" dependencies = [ "gimli", - "hashbrown 0.14.2", + "hashbrown", "object", "tracing", ] @@ -5601,7 +5538,7 @@ version = "0.19.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" dependencies = [ - "indexmap 2.0.0", + "indexmap", "serde", "serde_spanned", "toml_datetime", diff --git a/src/tools/jsondocck/Cargo.toml b/src/tools/jsondocck/Cargo.toml index ccabe6483d7a4..6326a9b1e79c3 100644 --- a/src/tools/jsondocck/Cargo.toml +++ b/src/tools/jsondocck/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -jsonpath_lib = "0.2" +jsonpath_lib = "0.3" getopts = "0.2" regex = "1.4" shlex = "1.0"