Fix span used for structured tuple struct suggestion

(And same for tuple variants.)

Previously, the span was just for the constructor name, which meant it
would result in syntactically-invalid code when applied. Now, the span
is for the entire expression.
This commit is contained in:
Noah Lev 2021-09-01 20:11:05 -07:00
parent 50171c310c
commit d2b13ba466
6 changed files with 135 additions and 10 deletions

View file

@ -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,

View file

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

View file

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

View file

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

View file

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

View file

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