From f7ecf1c54806d0a2b614510b46d1b25c178450f0 Mon Sep 17 00:00:00 2001 From: Cedric Date: Mon, 17 Jun 2019 20:04:26 +0200 Subject: [PATCH 1/5] suggest tuple struct syntax --- src/librustc_typeck/check/expr.rs | 71 +++++++++++++---------- src/test/ui/issues/issue-4736.stderr | 5 +- src/test/ui/numeric/numeric-fields.stderr | 7 ++- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index fa9e0d8a8578a..06d07d992427e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1215,38 +1215,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }, ty); - // prevent all specified fields from being suggested - let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); - if let Some(field_name) = Self::suggest_field_name(variant, - &field.ident.as_str(), - skip_fields.collect()) { - err.span_suggestion( - field.ident.span, - "a field with a similar name exists", - field_name.to_string(), - Applicability::MaybeIncorrect, - ); - } else { - match ty.sty { - ty::Adt(adt, ..) => { - if adt.is_enum() { - err.span_label(field.ident.span, - format!("`{}::{}` does not have this field", - ty, variant.ident)); - } else { - err.span_label(field.ident.span, - format!("`{}` does not have this field", ty)); - } - let available_field_names = self.available_field_names(variant); - if !available_field_names.is_empty() { - err.note(&format!("available fields are: {}", - self.name_series_display(available_field_names))); + match variant.ctor_kind { + CtorKind::Fn => { + err.span_label(field.ident.span, "field does not exist"); + err.span_label( + field.ident.span, + format!("`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name) + ); + } + _ => { + // prevent all specified fields from being suggested + let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); + if let Some(field_name) = Self::suggest_field_name(variant, + &field.ident.as_str(), + skip_fields.collect()) { + err.span_suggestion( + field.ident.span, + "a field with a similar name exists", + field_name.to_string(), + Applicability::MaybeIncorrect, + ); + } else { + match ty.sty { + ty::Adt(adt, ..) => { + if adt.is_enum() { + err.span_label(field.ident.span, + format!("`{}::{}` does not have this field", + ty, variant.ident)); + } else { + err.span_label(field.ident.span, + format!("`{}` does not have this field", ty)); + } + let available_field_names = self.available_field_names(variant); + if !available_field_names.is_empty() { + err.note(&format!("available fields are: {}", + self.name_series_display(available_field_names))); + } + } + _ => bug!("non-ADT passed to report_unknown_field") } - } - _ => bug!("non-ADT passed to report_unknown_field") + }; } - }; - err.emit(); + } + err.emit(); } // Return an hint about the closest match in field names diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index b4ac12643bcac..557ee5593f373 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,7 +2,10 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; - | ^ help: a field with a similar name exists: `0` + | ^ + | | + | field does not exist + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* 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 13c18d740fc1c..fef7486b8536d 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -2,9 +2,10 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | LL | let s = S{0b1: 10, 0: 11}; - | ^^^ `S` does not have this field - | - = note: available fields are: `0`, `1` + | ^^^ + | | + | field does not exist + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From 2191c1db08d21aac4d3823a497e429de283e878b Mon Sep 17 00:00:00 2001 From: Cedric Date: Tue, 18 Jun 2019 22:05:27 +0200 Subject: [PATCH 2/5] improve indentation --- src/librustc_typeck/check/expr.rs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 06d07d992427e..8edda805592a3 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1218,17 +1218,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match variant.ctor_kind { CtorKind::Fn => { err.span_label(field.ident.span, "field does not exist"); - err.span_label( - field.ident.span, - format!("`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name) - ); + err.span_label(field.ident.span, format!( + "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", + adt=ty, + kind_name=kind_name + )); } _ => { // prevent all specified fields from being suggested let skip_fields = skip_fields.iter().map(|ref x| x.ident.as_str()); - if let Some(field_name) = Self::suggest_field_name(variant, - &field.ident.as_str(), - skip_fields.collect()) { + if let Some(field_name) = Self::suggest_field_name( + variant, + &field.ident.as_str(), + skip_fields.collect() + ) { err.span_suggestion( field.ident.span, "a field with a similar name exists", @@ -1239,12 +1242,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match ty.sty { ty::Adt(adt, ..) => { if adt.is_enum() { - err.span_label(field.ident.span, - format!("`{}::{}` does not have this field", - ty, variant.ident)); + err.span_label(field.ident.span, format!( + "`{}::{}` does not have this field", + ty, + variant.ident + )); } else { - err.span_label(field.ident.span, - format!("`{}` does not have this field", ty)); + err.span_label(field.ident.span, format!( + "`{}` does not have this field", + ty + )); } let available_field_names = self.available_field_names(variant); if !available_field_names.is_empty() { From c917ba325f3e7944eefb5e906ca0392c9b499541 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 10:07:07 +0200 Subject: [PATCH 3/5] adt hint pointing to adt span --- src/librustc_typeck/check/expr.rs | 5 +++-- src/test/ui/issues/issue-4736.stderr | 7 +++---- src/test/ui/numeric/numeric-fields.stderr | 7 +++---- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 8edda805592a3..3c31e01240317 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1125,7 +1125,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } else { - self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name); + self.report_unknown_field(adt_ty, variant, field, ast_fields, kind_name, span); } tcx.types.err @@ -1196,6 +1196,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { field: &hir::Field, skip_fields: &[hir::Field], kind_name: &str, + ty_span: Span ) { if variant.recovered { return; @@ -1218,7 +1219,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match variant.ctor_kind { CtorKind::Fn => { err.span_label(field.ident.span, "field does not exist"); - err.span_label(field.ident.span, format!( + err.span_label(ty_span, format!( "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 557ee5593f373..6786b592d9857 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -2,10 +2,9 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | LL | let z = NonCopyable{ p: () }; - | ^ - | | - | field does not exist - | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` + | ----------- ^ field does not exist + | | + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* 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 fef7486b8536d..e71af0f33ee42 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -2,10 +2,9 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | LL | let s = S{0b1: 10, 0: 11}; - | ^^^ - | | - | field does not exist - | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + | - ^^^ field does not exist + | | + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From 70e52f84186ee017d19d26e081ab8688beee9b37 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 11:09:17 +0200 Subject: [PATCH 4/5] provide variant definition on tuple struct unknow field error --- src/librustc_typeck/check/expr.rs | 4 +++- src/test/ui/issues/issue-4736.stderr | 5 ++++- src/test/ui/numeric/numeric-fields.stderr | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 3c31e01240317..d659169711f2f 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1218,9 +1218,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty); match variant.ctor_kind { CtorKind::Fn => { + err.span_label(variant.ident.span, format!("`{adt}` defined here", adt=ty)); err.span_label(field.ident.span, "field does not exist"); err.span_label(ty_span, format!( - "`{adt}` is a tuple {kind_name}, use the appropriate syntax: `{adt}(/* fields */)`", + "`{adt}` is a tuple {kind_name},\ + use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name )); diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 6786b592d9857..557607503efab 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -1,10 +1,13 @@ error[E0560]: struct `NonCopyable` has no field named `p` --> $DIR/issue-4736.rs:4:26 | +LL | struct NonCopyable(()); + | ----------- `NonCopyable` defined here +... LL | let z = NonCopyable{ p: () }; | ----------- ^ field does not exist | | - | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* fields */)` + | `NonCopyable` is a tuple struct,use the appropriate syntax: `NonCopyable(/* 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 e71af0f33ee42..ad1f1177f7be7 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -1,10 +1,13 @@ error[E0560]: struct `S` has no field named `0b1` --> $DIR/numeric-fields.rs:4:15 | +LL | struct S(u8, u16); + | - `S` defined here +... LL | let s = S{0b1: 10, 0: 11}; | - ^^^ field does not exist | | - | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` + | `S` is a tuple struct,use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17 From b72b1ac062a66819cd06a3f147486678e99b4f40 Mon Sep 17 00:00:00 2001 From: Cedric Date: Wed, 19 Jun 2019 19:47:52 +0200 Subject: [PATCH 5/5] fix indentation --- src/librustc_typeck/check/expr.rs | 4 ++-- src/test/ui/issues/issue-4736.stderr | 2 +- src/test/ui/numeric/numeric-fields.stderr | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index d659169711f2f..b6e17091c06f9 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1221,7 +1221,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_label(ty_span, format!( - "`{adt}` is a tuple {kind_name},\ + "`{adt}` is a tuple {kind_name}, \ use the appropriate syntax: `{adt}(/* fields */)`", adt=ty, kind_name=kind_name @@ -1267,7 +1267,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; } } - err.emit(); + err.emit(); } // Return an hint about the closest match in field names diff --git a/src/test/ui/issues/issue-4736.stderr b/src/test/ui/issues/issue-4736.stderr index 557607503efab..257ec914a61ca 100644 --- a/src/test/ui/issues/issue-4736.stderr +++ b/src/test/ui/issues/issue-4736.stderr @@ -7,7 +7,7 @@ LL | struct NonCopyable(()); LL | let z = NonCopyable{ p: () }; | ----------- ^ field does not exist | | - | `NonCopyable` is a tuple struct,use the appropriate syntax: `NonCopyable(/* fields */)` + | `NonCopyable` is a tuple struct, use the appropriate syntax: `NonCopyable(/* 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 ad1f1177f7be7..5202393f559c9 100644 --- a/src/test/ui/numeric/numeric-fields.stderr +++ b/src/test/ui/numeric/numeric-fields.stderr @@ -7,7 +7,7 @@ LL | struct S(u8, u16); LL | let s = S{0b1: 10, 0: 11}; | - ^^^ field does not exist | | - | `S` is a tuple struct,use the appropriate syntax: `S(/* fields */)` + | `S` is a tuple struct, use the appropriate syntax: `S(/* fields */)` error[E0026]: struct `S` does not have a field named `0x1` --> $DIR/numeric-fields.rs:7:17