Skip to content

Commit

Permalink
Rollup merge of rust-lang#64748 - Centril:fix-64744, r=estebank
Browse files Browse the repository at this point in the history
Fix rust-lang#64744. Account for the Zero sub-pattern case.

Fixes rust-lang#64744.

r? @estebank
  • Loading branch information
Centril committed Sep 24, 2019
2 parents c9dbaec + 7b71abd commit aeb2414
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 15 deletions.
59 changes: 46 additions & 13 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
} else {
// Pattern has wrong number of fields.
self.e0023(pat.span, res, &subpats, &variant.fields, expected);
self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected);
on_error();
return tcx.types.err;
}
Expand All @@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&self,
pat_span: Span,
res: Res,
qpath: &hir::QPath,
subpats: &'tcx [P<Pat>],
fields: &[ty::FieldDef],
expected: Ty<'tcx>
) {
let subpats_ending = pluralise!(subpats.len());
let fields_ending = pluralise!(fields.len());
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,
};
let res_span = self.tcx.def_span(res.def_id());
let mut err = struct_span_err!(
self.tcx.sess,
Expand All @@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
))
.span_label(res_span, format!("{} defined here", res.descr()));

// 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,
};
if missing_parenthesis {
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),
};
err.multipart_suggestion(
"missing parenthesis",
vec![(subpats[0].span.shrink_to_lo(), "(".to_string()),
(subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())],
vec![
(left, "(".to_string()),
(right.shrink_to_hi(), ")".to_string()),
],
Applicability::MachineApplicable,
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/test/ui/error-codes/E0023.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ enum Fruit {
Apple(String, String),
Pear(u32),
Orange((String, String)),
Banana(()),
}


fn main() {
let x = Fruit::Apple(String::new(), String::new());
match x {
Fruit::Apple(a) => {}, //~ ERROR E0023
Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
Fruit::Pear(1, 2) => {}, //~ ERROR E0023
Fruit::Orange(a, b) => {}, //~ ERROR E0023
Fruit::Banana() => {}, //~ ERROR E0023
}
}
15 changes: 14 additions & 1 deletion src/test/ui/error-codes/E0023.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ help: missing parenthesis
LL | Fruit::Orange((a, b)) => {},
| ^ ^

error: aborting due to 4 previous errors
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

For more information about this error, try `rustc --explain E0023`.

0 comments on commit aeb2414

Please sign in to comment.