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] 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 00499041f2e..6c99044d0aa 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2191,7 +2191,8 @@ fn report_unknown_field( 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 @@ fn suggest_await_on_field_access( 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 @@ fn ban_nonexisting_field( 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 @@ fn maybe_suggest_array_indexing( 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 @@ fn suggest_first_deref_field( 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 ef6a7055c78..cf6e5b4e436 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 13a0464fdb2..44de282988b 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 7066d29760e..473c9a339fc 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 bcd1a00a4bb..d60db01a465 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 0c6ed9afd35..a4af319e339 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 1a88f269347..e109980e0bb 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 3b8a2b5c7ba..ed3650e5298 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 d628bd16208..f67a4ed78e2 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 12466868f00..fb3573ee2a4 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 70921049399..efe4987bd02 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 70921049399..efe4987bd02 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