Auto merge of #88631 - camelid:sugg-span, r=davidtwco
Improve structured tuple struct suggestion 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. I also changed it to use `span_suggestion_verbose`, for two reasons: 1. Now that the suggestion span has been corrected, the output is a bit cluttered and hard to read. Putting the suggestion its own window creates more space. 2. It's easier to see what's being suggested, since now the version after the suggestion is applied is shown. r? `@davidtwco`
This commit is contained in:
commit
d19d864e79
6 changed files with 162 additions and 15 deletions
|
@ -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();
|
||||
|
@ -1510,8 +1514,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
),
|
||||
);
|
||||
err.span_label(field.ident.span, "field does not exist");
|
||||
err.span_suggestion(
|
||||
ty_span,
|
||||
err.span_suggestion_verbose(
|
||||
expr_span,
|
||||
&format!(
|
||||
"`{adt}::{variant}` is a tuple {kind_name}, use the appropriate syntax",
|
||||
adt = ty,
|
||||
|
@ -1528,8 +1532,8 @@ 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,
|
||||
err.span_suggestion_verbose(
|
||||
expr_span,
|
||||
&format!(
|
||||
"`{adt}` is a tuple {kind_name}, use the appropriate syntax",
|
||||
adt = ty,
|
||||
|
|
|
@ -5,9 +5,12 @@ LL | struct NonCopyable(());
|
|||
| ----------- `NonCopyable` defined here
|
||||
...
|
||||
LL | let z = NonCopyable{ p: () };
|
||||
| ----------- ^ field does not exist
|
||||
| |
|
||||
| help: `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)`
|
||||
| ^ field does not exist
|
||||
|
|
||||
help: `NonCopyable` is a tuple struct, use the appropriate syntax
|
||||
|
|
||||
LL | let z = NonCopyable(/* fields */);
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,9 +5,12 @@ LL | V1(i32),
|
|||
| -- `Enum::V1` defined here
|
||||
...
|
||||
LL | Enum::V1 { x }
|
||||
| -------- ^ field does not exist
|
||||
| |
|
||||
| help: `Enum::V1` is a tuple variant, use the appropriate syntax: `Enum::V1(/* fields */)`
|
||||
| ^ field does not exist
|
||||
|
|
||||
help: `Enum::V1` is a tuple variant, use the appropriate syntax
|
||||
|
|
||||
LL | Enum::V1(/* fields */)
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -5,9 +5,12 @@ LL | struct S(u8, u16);
|
|||
| - `S` defined here
|
||||
...
|
||||
LL | let s = S{0b1: 10, 0: 11};
|
||||
| - ^^^ field does not exist
|
||||
| |
|
||||
| help: `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)`
|
||||
| ^^^ field does not exist
|
||||
|
|
||||
help: `S` is a tuple struct, use the appropriate syntax
|
||||
|
|
||||
LL | let s = S(/* fields */);
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0026]: struct `S` does not have a field named `0x1`
|
||||
--> $DIR/numeric-fields.rs:7:17
|
||||
|
|
18
src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs
Normal file
18
src/test/ui/suggestions/nested-non-tuple-tuple-struct.rs
Normal 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`
|
||||
}
|
116
src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr
Normal file
116
src/test/ui/suggestions/nested-non-tuple-tuple-struct.stderr
Normal file
|
@ -0,0 +1,116 @@
|
|||
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
|
||||
|
|
||||
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
|
||||
LL | let _x = (S(/* fields */), S { x: 3.0, y: 4.0 });
|
||||
| ~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
|
||||
LL | let _x = (S { x: 1.0, y: 2.0 }, 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
|
||||
|
|
||||
LL | let _x = (S { x: 1.0, y: 2.0 }, 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
|
||||
|
|
||||
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
|
||||
LL | let _y = (E::V(/* fields */), E::V { x: 3.0, y: 4.0 });
|
||||
| ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
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
|
||||
|
|
||||
LL | let _y = (E::V { x: 1.0, y: 2.0 }, 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
|
||||
|
|
||||
LL | let _y = (E::V { x: 1.0, y: 2.0 }, 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`.
|
Loading…
Add table
Reference in a new issue