diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d3b1ea8778d6..ea04454a356d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1082,14 +1082,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Require `..` if struct has non_exhaustive attribute. if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { - struct_span_err!( - tcx.sess, - pat.span, - E0638, - "`..` required with {} marked as non-exhaustive", - adt.variant_descr() - ) - .emit(); + self.error_foreign_non_exhaustive_spat(pat, adt.variant_descr(), fields.is_empty()); } // Report an error if incorrect number of the fields were specified. @@ -1108,6 +1101,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { no_field_errors } + fn error_foreign_non_exhaustive_spat(&self, pat: &Pat<'_>, descr: &str, no_fields: bool) { + let sess = self.tcx.sess; + let sm = sess.source_map(); + let sp_brace = sm.end_point(pat.span); + let sp_comma = sm.end_point(pat.span.with_hi(sp_brace.hi())); + let sugg = if no_fields || sp_brace != sp_comma { ".. }" } else { ", .. }" }; + + let mut err = struct_span_err!( + sess, + pat.span, + E0638, + "`..` required with {} marked as non-exhaustive", + descr + ); + err.span_suggestion_verbose( + sp_comma, + "add `..` at the end of the field list", + sugg.to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + } + fn error_field_already_bound(&self, span: Span, ident: ast::Ident, other_field: Span) { struct_span_err!( self.tcx.sess, diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 4e91e7bff34b..b1351e6fb9c4 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -62,18 +62,33 @@ error[E0638]: `..` required with struct marked as non-exhaustive | LL | let NormalStruct { first_field, second_field } = ns; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let NormalStruct { first_field, second_field , .. } = ns; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:26:9 | LL | let TupleStruct { 0: first_field, 1: second_field } = ts; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let TupleStruct { 0: first_field, 1: second_field , .. } = ts; + | ^^^^^^ error[E0638]: `..` required with struct marked as non-exhaustive --> $DIR/struct.rs:35:9 | LL | let UnitStruct { } = us; | ^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | let UnitStruct { .. } = us; + | ^^^^ error: aborting due to 9 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index ae4f6aff11a0..94432ce29d59 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -69,12 +69,22 @@ error[E0638]: `..` required with variant marked as non-exhaustive | LL | NonExhaustiveVariants::Struct { field } => "" | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | NonExhaustiveVariants::Struct { field , .. } => "" + | ^^^^^^ error[E0638]: `..` required with variant marked as non-exhaustive --> $DIR/variant.rs:30:12 | LL | if let NonExhaustiveVariants::Struct { field } = variant_struct { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `..` at the end of the field list + | +LL | if let NonExhaustiveVariants::Struct { field , .. } = variant_struct { + | ^^^^^^ error: aborting due to 8 previous errors