Change:
commit that introduced ICE: The ICE happens on . The most fundamental change here I imagine is introducing inside the match... <details<summaryBacktrace</summary<p</p</details
Can reproduce on the current nightly (rustc 1.39.0-nightly ( 2019-09-23)), but not on rustc 1.39.0-nightly ( 2019-08-26), so it's a regression.
Ok, this tries to eliminate stuff, but it doesn't fix the ICE: fixes the ICE.
Minimal reproducer: Problem was introduced in Specifically the line: is the problem... Seems we neglected to account for the nullary tuple case (). The fix is to account for the lack of any elements in deciding what spans to use.
cc
NM
I see you self-assigned, just add to the expr.
In case you haven't started, I can help with this.
Investigating a possibly better solution than for the zero case, I'll let you know how it pans out.
Fixed in

Discussion:
} } else { // Pattern has wrong number of fields. <del> self.e0023(pat.span, res, &subpats, &variant.fields, expected); </del> <ins> self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected); </ins> on_error(); return tcx.types.err; }

&self, pat_span: Span, res: Res, <ins> qpath: &hir::QPath, </ins> subpats: &'tcx [P<Pat>], fields: &[ty::FieldDef], expected: Ty<'tcx> ) { let subpats_ending = pluralise!(subpats.len()); let fields_ending = pluralise!(fields.len()); <del> let missing_parenthesis = match expected.sty { ty::Adt(_, substs) if fields.len() == 1 => { let field_ty = fields[0].ty(self.tcx, substs); match field_ty.sty { ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), _ => false, } } _ => false, }; </del> let res_span = self.tcx.def_span(res.def_id()); let mut err = struct_span_err!( self.tcx.sess,

)) .span_label(res_span, format!("{} defined here", res.descr())); <ins> // Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`. // More generally, the expected type wants a tuple variant with one field of an // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. let missing_parenthesis = match expected.sty { ty::Adt(_, substs) if fields.len() == 1 => { let field_ty = fields[0].ty(self.tcx, substs); match field_ty.sty { ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(), _ => false, } } _ => false, }; </ins> if missing_parenthesis { <ins> let (left, right) = match subpats { // This is the zero case; we aim to get the "hi" part of the `QPath`'s // span as the "lo" and then the "hi" part of the pattern's span as the "hi". // This looks like: // // help: missing parenthesis //   | // L |     let A(()) = A(()); //   |          ^  ^ [] => { let qpath_span = match qpath { hir::QPath::Resolved(_, path) => path.span, hir::QPath::TypeRelative(_, ps) => ps.ident.span, }; (qpath_span.shrink_to_hi(), pat_span) }, // Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the // last sub-pattern. In the case of `A(x)` the first and last may coincide. // This looks like: // // help: missing parenthesis //   | // L |     let A((x, y)) = A((1, 2)); //   |           ^    ^ [first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span), }; </ins> err.multipart_suggestion( "missing parenthesis", <del> vec![(subpats[0].span.shrink_to_lo(), "(".to_string()), (subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())], </del> <ins> vec![ (left, "(".to_string()), (right.shrink_to_hi(), ")".to_string()), ], </ins> Applicability::MachineApplicable, ); }

Apple(String, String), Pear(u32), Orange((String, String)), <ins> Banana(()), </ins> } fn main() { let x = Fruit::Apple(String::new(), String::new()); match x {

Fruit::Apple(a, b, c) => {}, //~ ERROR E0023 Fruit::Pear(1, 2) => {}, //~ ERROR E0023 Fruit::Orange(a, b) => {}, //~ ERROR E0023 <ins> Fruit::Banana() => {}, //~ ERROR E0023 </ins> } }

LL |         Fruit::Orange((a, b)) => {}, |                       ^    ^ <del> error: aborting due to 4 previous errors </del> <ins> error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field --> $DIR/E0023.rs:15:9 | LL |     Banana(()), |     ---------- tuple variant defined here ... LL |         Fruit::Banana() => {}, |         ^^^^^^^^^^^^^^^ expected 1 field, found 0 help: missing parenthesis | LL |         Fruit::Banana(()) => {}, |                      ^  ^ error: aborting due to 5 previous errors </ins> For more information about this error, try `rustc --explain E0023`.