1
Fork 0

Suggest field typo through derefs

Take into account implicit dereferences when suggesting fields.

```
error[E0609]: no field `longname` on type `Arc<S>`
  --> $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
This commit is contained in:
Esteban Küber 2023-10-24 02:06:06 +00:00
parent 1be1e84872
commit dfa75391f8
29 changed files with 227 additions and 192 deletions

View file

@ -2471,9 +2471,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::RawPtr(..) => { ty::RawPtr(..) => {
self.suggest_first_deref_field(&mut err, expr, base, ident); 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) => { ty::Param(param_ty) => {
self.point_at_param_definition(&mut err, 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")); 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( fn maybe_suggest_array_indexing(
&self, &self,
err: &mut Diagnostic, err: &mut Diagnostic,
@ -2709,7 +2678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let mut err = type_error_struct!( let mut err = type_error_struct!(
self.tcx().sess, self.tcx().sess,
field.span, span,
expr_t, expr_t,
E0609, E0609,
"no field `{field}` on type `{expr_t}`", "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 // 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 mod_id = self.tcx.parent_module(id).to_def_id();
if let Some((fields, args)) = for (found_fields, args) in
self.get_field_candidates_considering_privacy(span, expr_t, mod_id) 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::<Vec<_>>();
let candidate_fields: Vec<_> = found_fields
.into_iter()
.filter_map(|candidate_field| { .filter_map(|candidate_field| {
self.check_for_nested_field_satisfying( self.check_for_nested_field_satisfying(
span, span,
@ -2729,6 +2700,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
args, args,
vec![], vec![],
mod_id, mod_id,
id,
) )
}) })
.map(|mut field_path| { .map(|mut field_path| {
@ -2753,6 +2725,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
candidate_fields.iter().map(|path| format!("{path}.")), candidate_fields.iter().map(|path| format!("{path}.")),
Applicability::MaybeIncorrect, 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 err
@ -2781,33 +2768,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
span: Span, span: Span,
base_ty: Ty<'tcx>, base_ty: Ty<'tcx>,
mod_id: DefId, mod_id: DefId,
) -> Option<(impl Iterator<Item = &'tcx ty::FieldDef> + 'tcx, GenericArgsRef<'tcx>)> { hir_id: hir::HirId,
) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
for (base_t, _) in self.autoderef(span, base_ty) { self.autoderef(span, base_ty)
match base_t.kind() { .filter_map(move |(base_t, _)| {
ty::Adt(base_def, args) if !base_def.is_enum() => { match base_t.kind() {
let tcx = self.tcx; ty::Adt(base_def, args) if !base_def.is_enum() => {
let fields = &base_def.non_enum_variant().fields; let tcx = self.tcx;
// Some struct, e.g. some that impl `Deref`, have all private fields let fields = &base_def.non_enum_variant().fields;
// because you're expected to deref them to access the _real_ fields. // Some struct, e.g. some that impl `Deref`, have all private fields
// This, for example, will help us suggest accessing a field through a `Box<T>`. // because you're expected to deref them to access the _real_ fields.
if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { // This, for example, will help us suggest accessing a field through a `Box<T>`.
continue; 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::<Vec<_>>(),
*args,
));
} }
return Some(( _ => None,
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,
));
} }
_ => {} })
} .collect()
}
None
} }
/// This method is called after we have encountered a missing field error to recursively /// 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>, subst: GenericArgsRef<'tcx>,
mut field_path: Vec<Ident>, mut field_path: Vec<Ident>,
mod_id: DefId, mod_id: DefId,
hir_id: HirId,
) -> Option<Vec<Ident>> { ) -> Option<Vec<Ident>> {
debug!( debug!(
"check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}", "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); let field_ty = candidate_field.ty(self.tcx, subst);
if matches(candidate_field, field_ty) { if matches(candidate_field, field_ty) {
return Some(field_path); return Some(field_path);
} else if let Some((nested_fields, subst)) = } else {
self.get_field_candidates_considering_privacy(span, field_ty, mod_id) 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 { // recursively search fields of `candidate_field` if it's a ty::Adt
if let Some(field_path) = self.check_for_nested_field_satisfying( for field in nested_fields {
span, if let Some(field_path) = self.check_for_nested_field_satisfying(
matches, span,
field, matches,
subst, field,
field_path.clone(), subst,
mod_id, field_path.clone(),
) { mod_id,
return Some(field_path); hir_id,
) {
return Some(field_path);
}
} }
} }
} }

View file

@ -1983,69 +1983,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
item_name: Ident, item_name: Ident,
return_type: Option<Ty<'tcx>>, return_type: Option<Ty<'tcx>>,
) { ) {
if let SelfSource::MethodCall(expr) = source if let SelfSource::MethodCall(expr) = source {
&& let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id() let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
&& let Some((fields, args)) = for (fields, args) in
self.get_field_candidates_considering_privacy(span, actual, mod_id) 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 call_expr = self.tcx.hir().expect_expr(self.tcx.hir().parent_id(expr.hir_id));
let lang_items = self.tcx.lang_items(); let lang_items = self.tcx.lang_items();
let never_mention_traits = [ let never_mention_traits = [
lang_items.clone_trait(), lang_items.clone_trait(),
lang_items.deref_trait(), lang_items.deref_trait(),
lang_items.deref_mut_trait(), lang_items.deref_mut_trait(),
self.tcx.get_diagnostic_item(sym::AsRef), self.tcx.get_diagnostic_item(sym::AsRef),
self.tcx.get_diagnostic_item(sym::AsMut), self.tcx.get_diagnostic_item(sym::AsMut),
self.tcx.get_diagnostic_item(sym::Borrow), self.tcx.get_diagnostic_item(sym::Borrow),
self.tcx.get_diagnostic_item(sym::BorrowMut), self.tcx.get_diagnostic_item(sym::BorrowMut),
]; ];
let candidate_fields: Vec<_> = fields let candidate_fields: Vec<_> = fields
.filter_map(|candidate_field| { .iter()
self.check_for_nested_field_satisfying( .filter_map(|candidate_field| {
span, self.check_for_nested_field_satisfying(
&|_, field_ty| { span,
self.lookup_probe_for_diagnostic( &|_, field_ty| {
item_name, self.lookup_probe_for_diagnostic(
field_ty, item_name,
call_expr, field_ty,
ProbeScope::TraitsInScope, call_expr,
return_type, ProbeScope::TraitsInScope,
) return_type,
.is_ok_and(|pick| { )
!never_mention_traits .is_ok_and(|pick| {
.iter() !never_mention_traits
.flatten() .iter()
.any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id) .flatten()
}) .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
}, })
candidate_field, },
args, candidate_field,
vec![], args,
mod_id, vec![],
) mod_id,
}) expr.hir_id,
.map(|field_path| { )
field_path })
.iter() .map(|field_path| {
.map(|id| id.name.to_ident_string()) field_path
.collect::<Vec<String>>() .iter()
.join(".") .map(|id| id.name.to_ident_string())
}) .collect::<Vec<String>>()
.collect(); .join(".")
})
.collect();
let len = candidate_fields.len(); let len = candidate_fields.len();
if len > 0 { if len > 0 {
err.span_suggestions( err.span_suggestions(
item_name.span.shrink_to_lo(), item_name.span.shrink_to_lo(),
format!( format!(
"{} of the expressions' fields {} a method of the same name", "{} of the expressions' fields {} a method of the same name",
if len > 1 { "some" } else { "one" }, if len > 1 { "some" } else { "one" },
if len > 1 { "have" } else { "has" }, if len > 1 { "have" } else { "has" },
), ),
candidate_fields.iter().map(|path| format!("{path}.")), candidate_fields.iter().map(|path| format!("{path}.")),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
}
} }
} }
} }

View file

@ -10,7 +10,6 @@ fn await_on_struct_missing() {
let x = S; let x = S;
x.await; x.await;
//~^ ERROR no field `await` on type //~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP set `edition = "2021"` in `Cargo.toml` //~| HELP set `edition = "2021"` in `Cargo.toml`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide //~| 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<Output = ()>>) { fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
x.await; x.await;
//~^ ERROR no field `await` on type //~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP set `edition = "2021"` in `Cargo.toml` //~| HELP set `edition = "2021"` in `Cargo.toml`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide

View file

@ -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 --> $DIR/suggest-switching-edition-on-await-cargo.rs:11:7
| |
LL | x.await; LL | x.await;
| ^^^^^ unknown field | ^^^^^
| |
= note: to `.await` a `Future`, switch to Rust 2018 or later = note: to `.await` a `Future`, switch to Rust 2018 or later
= help: set `edition = "2021"` in `Cargo.toml` = help: set `edition = "2021"` in `Cargo.toml`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide = 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` 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; LL | x.await;
| ^^^^^ help: a field with a similar name exists: `awai` | ^^^^^ 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 = note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>` error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
--> $DIR/suggest-switching-edition-on-await-cargo.rs:33:7 --> $DIR/suggest-switching-edition-on-await-cargo.rs:32:7
| |
LL | x.await; LL | x.await;
| ^^^^^ unknown field | ^^^^^
| |
= note: to `.await` a `Future`, switch to Rust 2018 or later = note: to `.await` a `Future`, switch to Rust 2018 or later
= help: set `edition = "2021"` in `Cargo.toml` = help: set `edition = "2021"` in `Cargo.toml`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide = note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0609]: no field `await` on type `impl Future<Output = ()>` error[E0609]: no field `await` on type `impl Future<Output = ()>`
--> $DIR/suggest-switching-edition-on-await-cargo.rs:42:7 --> $DIR/suggest-switching-edition-on-await-cargo.rs:40:7
| |
LL | x.await; LL | x.await;
| ^^^^^ | ^^^^^

View file

@ -8,7 +8,6 @@ fn await_on_struct_missing() {
let x = S; let x = S;
x.await; x.await;
//~^ ERROR no field `await` on type //~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP pass `--edition 2021` to `rustc` //~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide //~| 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<Output = ()>>) { fn await_on_63533(x: Pin<&mut dyn Future<Output = ()>>) {
x.await; x.await;
//~^ ERROR no field `await` on type //~^ ERROR no field `await` on type
//~| NOTE unknown field
//~| NOTE to `.await` a `Future`, switch to Rust 2018 //~| NOTE to `.await` a `Future`, switch to Rust 2018
//~| HELP pass `--edition 2021` to `rustc` //~| HELP pass `--edition 2021` to `rustc`
//~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide //~| NOTE for more on editions, read https://doc.rust-lang.org/edition-guide

View file

@ -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 --> $DIR/suggest-switching-edition-on-await.rs:9:7
| |
LL | x.await; LL | x.await;
| ^^^^^ unknown field | ^^^^^
| |
= note: to `.await` a `Future`, switch to Rust 2018 or later = note: to `.await` a `Future`, switch to Rust 2018 or later
= help: pass `--edition 2021` to `rustc` = help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide = 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` 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; LL | x.await;
| ^^^^^ help: a field with a similar name exists: `awai` | ^^^^^ 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 = note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>` error[E0609]: no field `await` on type `Pin<&mut dyn Future<Output = ()>>`
--> $DIR/suggest-switching-edition-on-await.rs:31:7 --> $DIR/suggest-switching-edition-on-await.rs:30:7
| |
LL | x.await; LL | x.await;
| ^^^^^ unknown field | ^^^^^
| |
= note: to `.await` a `Future`, switch to Rust 2018 or later = note: to `.await` a `Future`, switch to Rust 2018 or later
= help: pass `--edition 2021` to `rustc` = help: pass `--edition 2021` to `rustc`
= note: for more on editions, read https://doc.rust-lang.org/edition-guide = note: for more on editions, read https://doc.rust-lang.org/edition-guide
error[E0609]: no field `await` on type `impl Future<Output = ()>` error[E0609]: no field `await` on type `impl Future<Output = ()>`
--> $DIR/suggest-switching-edition-on-await.rs:40:7 --> $DIR/suggest-switching-edition-on-await.rs:38:7
| |
LL | x.await; LL | x.await;
| ^^^^^ | ^^^^^

View file

@ -21,18 +21,15 @@ fn main() {
// `doc(hidden)` because it's defined in this crate. // `doc(hidden)` because it's defined in this crate.
A::default().hey; A::default().hey;
//~^ ERROR no field `hey` on type `A` //~^ ERROR no field `hey` on type `A`
//~| NOTE unknown field
//~| NOTE available fields are: `hello`, `bye` //~| NOTE available fields are: `hello`, `bye`
// Here we want to hide the field `hello` since it's marked // Here we want to hide the field `hello` since it's marked
// `doc(hidden)` and comes from an external crate. // `doc(hidden)` and comes from an external crate.
doc_hidden_fields::B::default().hey; doc_hidden_fields::B::default().hey;
//~^ ERROR no field `hey` on type `B` //~^ ERROR no field `hey` on type `B`
//~| NOTE unknown field //~| NOTE available field is: `bye`
//~| NOTE available fields are: `bye`
C::default().hey; C::default().hey;
//~^ ERROR no field `hey` on type `C` //~^ ERROR no field `hey` on type `C`
//~| NOTE unknown field
//~| NOTE available fields are: `hello`, `bye` //~| NOTE available fields are: `hello`, `bye`
} }

View file

@ -2,23 +2,23 @@ error[E0609]: no field `hey` on type `A`
--> $DIR/dont-suggest-doc-hidden-fields.rs:22:18 --> $DIR/dont-suggest-doc-hidden-fields.rs:22:18
| |
LL | A::default().hey; LL | A::default().hey;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `hello`, `bye` = note: available fields are: `hello`, `bye`
error[E0609]: no field `hey` on type `B` 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; 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` 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; LL | C::default().hey;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `hello`, `bye` = note: available fields are: `hello`, `bye`

View file

@ -13,13 +13,13 @@ error[E0609]: no field `field` on type `Compound`
--> $DIR/dont-suggest-hygienic-fields.rs:24:16 --> $DIR/dont-suggest-hygienic-fields.rs:24:16
| |
LL | let _ = ty.field; LL | let _ = ty.field;
| ^^^^^ unknown field | ^^^^^
error[E0609]: no field `fieeld` on type `Compound` error[E0609]: no field `fieeld` on type `Compound`
--> $DIR/dont-suggest-hygienic-fields.rs:25:16 --> $DIR/dont-suggest-hygienic-fields.rs:25:16
| |
LL | let _ = ty.fieeld; LL | let _ = ty.fieeld;
| ^^^^^^ unknown field | ^^^^^^
error[E0026]: struct `Compound` does not have a field named `field` error[E0026]: struct `Compound` does not have a field named `field`
--> $DIR/dont-suggest-hygienic-fields.rs:27:20 --> $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 --> $DIR/dont-suggest-hygienic-fields.rs:34:16
| |
LL | let _ = ty.0; LL | let _ = ty.0;
| ^ unknown field | ^
error: aborting due to 6 previous errors error: aborting due to 6 previous errors

View file

@ -2,9 +2,9 @@ error[E0609]: no field `zz` on type `Foo`
--> $DIR/issue-36798_unknown_field.rs:7:7 --> $DIR/issue-36798_unknown_field.rs:7:7
| |
LL | f.zz; LL | f.zz;
| ^^ unknown field | ^^
| |
= note: available fields are: `bar` = note: available field is: `bar`
error: aborting due to previous error error: aborting due to previous error

View file

@ -22,7 +22,7 @@ error[E0609]: no field `egregiously_nonexistent_field` on type `Demo`
--> $DIR/issue-42599_available_fields_note.rs:35:42 --> $DIR/issue-42599_available_fields_note.rs:35:42
| |
LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field; LL | let egregious_field_misaccess = demo.egregiously_nonexistent_field;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unknown field | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: available fields are: `favorite_integer`, `innocently_misspellable` = note: available fields are: `favorite_integer`, `innocently_misspellable`

View file

@ -2,7 +2,7 @@ error[E0609]: no field `method` on type `Foo`
--> $DIR/E0609-private-method.rs:15:7 --> $DIR/E0609-private-method.rs:15:7
| |
LL | f.method; LL | f.method;
| ^^^^^^ unknown field | ^^^^^^
error: aborting due to previous error error: aborting due to previous error

View file

@ -2,15 +2,15 @@ error[E0609]: no field `foo` on type `Foo`
--> $DIR/E0609.rs:8:15 --> $DIR/E0609.rs:8:15
| |
LL | let _ = x.foo; LL | let _ = x.foo;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `x` = note: available field is: `x`
error[E0609]: no field `1` on type `Bar` error[E0609]: no field `1` on type `Bar`
--> $DIR/E0609.rs:11:7 --> $DIR/E0609.rs:11:7
| |
LL | y.1; LL | y.1;
| ^ unknown field | ^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -29,7 +29,7 @@ error[E0609]: no field `foo` on type `Foo`
--> $DIR/infinite-autoderef.rs:24:9 --> $DIR/infinite-autoderef.rs:24:9
| |
LL | Foo.foo; LL | Foo.foo;
| ^^^ unknown field | ^^^
error[E0055]: reached the recursion limit while auto-dereferencing `Foo` error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
--> $DIR/infinite-autoderef.rs:25:9 --> $DIR/infinite-autoderef.rs:25:9

View file

@ -2,9 +2,9 @@ error[E0609]: no field `nonexistent_field` on type `MyStruct`
--> $DIR/issue-19244-2.rs:5:27 --> $DIR/issue-19244-2.rs:5:27
| |
LL | let a: [isize; STRUCT.nonexistent_field]; 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 error: aborting due to previous error

View file

@ -8,7 +8,7 @@ error[E0609]: no field `001` on type `Verdict`
--> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31 --> $DIR/issue-47073-zero-padded-tuple-struct-indices.rs:10:31
| |
LL | let _punishment = justice.001; LL | let _punishment = justice.001;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`

View file

@ -54,6 +54,8 @@ error[E0609]: no field `Self` on type `S`
| |
LL | offset_of!(S, Self); LL | offset_of!(S, Self);
| ^^^^ | ^^^^
|
= note: available fields are: `v`, `w`
error[E0616]: field `v` of struct `T` is private error[E0616]: field `v` of struct `T` is private
--> $DIR/offset-of-self.rs:41:30 --> $DIR/offset-of-self.rs:41:30
@ -66,6 +68,8 @@ error[E0609]: no field `self` on type `S`
| |
LL | offset_of!(S, self); LL | offset_of!(S, self);
| ^^^^ | ^^^^
|
= note: available fields are: `v`, `w`
error[E0609]: no field `self` on type `u8` error[E0609]: no field `self` on type `u8`
--> $DIR/offset-of-self.rs:56:21 --> $DIR/offset-of-self.rs:56:21

View file

@ -266,7 +266,7 @@ error[E0609]: no field `1e1` on type `S`
--> $DIR/float-field.rs:6:7 --> $DIR/float-field.rs:6:7
| |
LL | s.1e1; LL | s.1e1;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -280,7 +280,7 @@ error[E0609]: no field `0x1e1` on type `S`
--> $DIR/float-field.rs:24:7 --> $DIR/float-field.rs:24:7
| |
LL | s.0x1e1; LL | s.0x1e1;
| ^^^^^ unknown field | ^^^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -288,7 +288,7 @@ error[E0609]: no field `0x1` on type `S`
--> $DIR/float-field.rs:25:7 --> $DIR/float-field.rs:25:7
| |
LL | s.0x1.; LL | s.0x1.;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -296,7 +296,7 @@ error[E0609]: no field `0x1` on type `S`
--> $DIR/float-field.rs:28:7 --> $DIR/float-field.rs:28:7
| |
LL | s.0x1.1; LL | s.0x1.1;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -304,7 +304,7 @@ error[E0609]: no field `0x1` on type `S`
--> $DIR/float-field.rs:30:7 --> $DIR/float-field.rs:30:7
| |
LL | s.0x1.1e1; LL | s.0x1.1e1;
| ^^^ unknown field | ^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -312,7 +312,7 @@ error[E0609]: no field `0x1e` on type `S`
--> $DIR/float-field.rs:34:7 --> $DIR/float-field.rs:34:7
| |
LL | s.0x1e+1; LL | s.0x1e+1;
| ^^^^ unknown field | ^^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -320,7 +320,7 @@ error[E0609]: no field `0x1e` on type `S`
--> $DIR/float-field.rs:35:7 --> $DIR/float-field.rs:35:7
| |
LL | s.0x1e-1; LL | s.0x1e-1;
| ^^^^ unknown field | ^^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`
@ -328,7 +328,7 @@ error[E0609]: no field `1e1` on type `S`
--> $DIR/float-field.rs:42:7 --> $DIR/float-field.rs:42:7
| |
LL | s.1e1f32; LL | s.1e1f32;
| ^^^^^^ unknown field | ^^^^^^
| |
= note: available fields are: `0`, `1` = note: available fields are: `0`, `1`

View file

@ -35,7 +35,7 @@ error[E0609]: no field `i` on type `Box<dyn Fn() -> Foo>`
--> $DIR/call-on-missing.rs:26:14 --> $DIR/call-on-missing.rs:26:14
| |
LL | callable.i; LL | callable.i;
| ^ unknown field | ^
| |
help: use parentheses to call this trait object help: use parentheses to call this trait object
| |

View file

@ -2,7 +2,7 @@ error[E0609]: no field `opts` on type `TyCtxt<'tcx>`
--> $DIR/field-access-considering-privacy.rs:29:13 --> $DIR/field-access-considering-privacy.rs:29:13
| |
LL | tcx.opts; LL | tcx.opts;
| ^^^^ unknown field | ^^^^
| |
help: one of the expressions' fields has a field of the same name help: one of the expressions' fields has a field of the same name
| |

View file

@ -2,7 +2,7 @@ error[E0609]: no field `f` on type `Foo`
--> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22 --> $DIR/non-existent-field-present-in-subfield-recursion-limit.rs:41:22
| |
LL | let test = fooer.f; LL | let test = fooer.f;
| ^ unknown field | ^
| |
= note: available fields are: `first`, `second`, `third` = note: available fields are: `first`, `second`, `third`

View file

@ -2,9 +2,8 @@ error[E0609]: no field `c` on type `Foo`
--> $DIR/non-existent-field-present-in-subfield.rs:37:24 --> $DIR/non-existent-field-present-in-subfield.rs:37:24
| |
LL | let _test = &fooer.c; 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 help: one of the expressions' fields has a field of the same name
| |
LL | let _test = &fooer.first.bar.c; 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 --> $DIR/non-existent-field-present-in-subfield.rs:40:24
| |
LL | let _test2 = fooer.test; 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 help: one of the expressions' fields has a field of the same name
| |
LL | let _test2 = fooer.first.bar.c.test; LL | let _test2 = fooer.first.bar.c.test;

View file

@ -2,9 +2,9 @@ error[E0609]: no field `cap` on type `S`
--> $DIR/private-field.rs:7:12 --> $DIR/private-field.rs:7:12
| |
LL | dbg!(s.cap) LL | dbg!(s.cap)
| ^^^ unknown field | ^^^
| |
= note: available fields are: `val` = note: available field is: `val`
error: aborting due to previous error error: aborting due to previous error

View file

@ -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`
}

View file

@ -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`
}

View file

@ -0,0 +1,15 @@
error[E0609]: no field `longname` on type `Arc<S>`
--> $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`.

View file

@ -23,9 +23,8 @@ error[E0609]: no field `field` on type `Thing`
--> $DIR/too-many-field-suggestions.rs:26:7 --> $DIR/too-many-field-suggestions.rs:26:7
| |
LL | t.field; 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 help: some of the expressions' fields have a field of the same name
| |
LL | t.a0.field; LL | t.a0.field;

View file

@ -8,7 +8,7 @@ error[E0609]: no field `0` on type `Empty`
--> $DIR/tuple-index-not-tuple.rs:8:11 --> $DIR/tuple-index-not-tuple.rs:8:11
| |
LL | Empty.0; LL | Empty.0;
| ^ unknown field | ^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -2,7 +2,7 @@ error[E0609]: no field `sleep` on type `&mut S`
--> $DIR/issue-67971.rs:5:9 --> $DIR/issue-67971.rs:5:9
| |
LL | ctx.sleep = 0; LL | ctx.sleep = 0;
| ^^^^^ unknown field | ^^^^^
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/issue-67971.rs:3:24 --> $DIR/issue-67971.rs:3:24