diff options
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 b95c673f3ba..264b96af6da 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::<Vec<_>>(); 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::<Vec<String>>() - .join(".") + .map(|id| format!("{}.", id.name.to_ident_string())) + .collect::<String>() }) .collect::<Vec<_>>(); @@ -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 1b0912310e8..ebd117f506c 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<Output = ()>>` --> $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 ddc44562d2c..82c5b107b05 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<Output = ()>>` --> $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 7bd0eaf77a9..146ffd7dd65 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 98876e305ca..354aef4047b 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 a4c3512eb41..d830564bc37 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 b21b6fdfcf1..ee15147ba3e 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 193c5aaf72d..0edaeca8a88 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 6949a0a4a68..8423e7a97a0 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 a91e47657ab..f80c2383ef8 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 a0f20e563f3..07ba3aa911f 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 729e5db0552..6e24b425e95 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 649e28be51d..f12d53448d3 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<S>` --> $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<Arc<S>>` + --> $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<S>` + --> $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<Arc<S>, ()>` + --> $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<S, ()>` + --> $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 cc94a61ae7f..0f81f2a1bb8 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 7d7c5cd7892..7fc8289aaa0 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 58b1f5cb078..805f84da388 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 58b1f5cb078..805f84da388 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 |
