diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 10f5b000aca1c..1a4dfdcfcbfb4 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1236,6 +1236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant, fields, base_expr.is_none(), + expr.span, ); if let Some(base_expr) = base_expr { // If check_expr_struct_fields hit an error, do not attempt to populate @@ -1283,6 +1284,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant: &'tcx ty::VariantDef, ast_fields: &'tcx [hir::ExprField<'tcx>], check_completeness: bool, + expr_span: Span, ) -> bool { let tcx = self.tcx; @@ -1334,7 +1336,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ident, }); } else { - self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span); + self.report_unknown_field( + adt_ty, variant, field, ast_fields, kind_name, expr_span, + ); } tcx.ty_error() @@ -1467,7 +1471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: &hir::ExprField<'_>, skip_fields: &[hir::ExprField<'_>], kind_name: &str, - ty_span: Span, + expr_span: Span, ) { if variant.is_recovered() { self.set_tainted_by_errors(); @@ -1511,7 +1515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion( - ty_span, + expr_span, &format!( "`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, @@ -1529,7 +1533,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(variant.ident.span, format!("`{adt}` defined here", adt = ty)); err.span_label(field.ident.span, "field does not exist"); err.span_suggestion( - ty_span, + expr_span, &format!( "`{adt}` is a tuple {kind_name}, use the appropriate syntax", adt = ty, diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 9be4eb1c7fddb..7df506b198122 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -5,8 +5,9 @@ LL | struct NonCopyable(()); | ----------- `NonCopyable` defined here ... LL | let z = NonCopyable{ p: () }; - | ----------- ^ field does not exist - | | + | -------------^------ + | | | + | | field does not exist | help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-80607.stderr b/src/test/ui/issues/issue-80607.stderr index 22a660b4167d3..6172a7cc8aa08 100644 --- a/src/test/ui/issues/issue-80607.stderr +++ b/src/test/ui/issues/issue-80607.stderr @@ -5,8 +5,9 @@ LL | V1(i32), | -- `Enum::V1` defined here ... LL | Enum::V1 { x } - | -------- ^ field does not exist - | | + | -----------^-- + | | | + | | field does not exist | help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)` error: aborting due to previous error diff --git a/src/test/ui/numeric/numeric-fields.stderr b/src/test/ui/numeric/numeric-fields.stderr index 13b6cfae4ec47..daf1cbb65bf16 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -5,8 +5,9 @@ LL | struct S(u8, u16); | - `S` defined here ... LL | let s = S{0b1: 10, 0: 11}; - | - ^^^ field does not exist - | | + | --^^^------------ + | | | + | | field does not exist | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs new file mode 100644 index 0000000000000..308adcf01fe5d --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs @@ -0,0 +1,18 @@ +pub struct S(f32, f32); + +pub enum E { + V(f32, f32), +} + +fn main() { + let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + //~^ ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + //~| ERROR struct `S` has no field named `x` + //~| ERROR struct `S` has no field named `y` + let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + //~^ ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` + //~| ERROR variant `E::V` has no field named `x` + //~| ERROR variant `E::V` has no field named `y` +} diff --git a/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr new file mode 100644 index 0000000000000..5a234e2a75faf --- /dev/null +++ b/src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr @@ -0,0 +1,100 @@ +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:19 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ----^--------------- + | | | + | | field does not exist + | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:27 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ------------^------- + | | | + | | field does not exist + | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + +error[E0560]: struct `S` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:41 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ----^--------------- + | | | + | | field does not exist + | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + +error[E0560]: struct `S` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:8:49 + | +LL | pub struct S(f32, f32); + | - `S` defined here +... +LL | let _x = (S { x: 1.0, y: 2.0 }, S { x: 3.0, y: 4.0 }); + | ------------^------- + | | | + | | field does not exist + | help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:22 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | -------^--------------- + | | | + | | field does not exist + | help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)` + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:30 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ---------------^------- + | | | + | | field does not exist + | help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)` + +error[E0559]: variant `E::V` has no field named `x` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:47 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | -------^--------------- + | | | + | | field does not exist + | help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)` + +error[E0559]: variant `E::V` has no field named `y` + --> $DIR/nested-non-tuple-tuple-struct.rs:13:55 + | +LL | V(f32, f32), + | - `E::V` defined here +... +LL | let _y = (E::V { x: 1.0, y: 2.0 }, E::V { x: 3.0, y: 4.0 }); + | ---------------^------- + | | | + | | field does not exist + | help: `E::V` is a tuple variant, use the appropriate syntax: `E::V(/* fields */)` + +error: aborting due to 8 previous errors + +Some errors have detailed explanations: E0559, E0560. +For more information about an error, try `rustc --explain E0559`.