Rollup merge of #64748 - Centril:fix-64744, r=estebank
Fix #64744. Account for the Zero sub-pattern case. Fixes https://github.com/rust-lang/rust/issues/64744. r? @estebank
This commit is contained in:
commit
aeb24142be
3 changed files with 62 additions and 15 deletions
|
@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Pattern has wrong number of fields.
|
// 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();
|
on_error();
|
||||||
return tcx.types.err;
|
return tcx.types.err;
|
||||||
}
|
}
|
||||||
|
@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&self,
|
&self,
|
||||||
pat_span: Span,
|
pat_span: Span,
|
||||||
res: Res,
|
res: Res,
|
||||||
|
qpath: &hir::QPath,
|
||||||
subpats: &'tcx [P<Pat>],
|
subpats: &'tcx [P<Pat>],
|
||||||
fields: &[ty::FieldDef],
|
fields: &[ty::FieldDef],
|
||||||
expected: Ty<'tcx>
|
expected: Ty<'tcx>
|
||||||
) {
|
) {
|
||||||
let subpats_ending = pluralise!(subpats.len());
|
let subpats_ending = pluralise!(subpats.len());
|
||||||
let fields_ending = pluralise!(fields.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 res_span = self.tcx.def_span(res.def_id());
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self.tcx.sess,
|
self.tcx.sess,
|
||||||
|
@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
))
|
))
|
||||||
.span_label(res_span, format!("{} defined here", res.descr()));
|
.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 {
|
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(
|
err.multipart_suggestion(
|
||||||
"missing parenthesis",
|
"missing parenthesis",
|
||||||
vec![(subpats[0].span.shrink_to_lo(), "(".to_string()),
|
vec![
|
||||||
(subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())],
|
(left, "(".to_string()),
|
||||||
|
(right.shrink_to_hi(), ")".to_string()),
|
||||||
|
],
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@ enum Fruit {
|
||||||
Apple(String, String),
|
Apple(String, String),
|
||||||
Pear(u32),
|
Pear(u32),
|
||||||
Orange((String, String)),
|
Orange((String, String)),
|
||||||
|
Banana(()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let x = Fruit::Apple(String::new(), String::new());
|
let x = Fruit::Apple(String::new(), String::new());
|
||||||
match x {
|
match x {
|
||||||
|
@ -12,5 +12,6 @@ fn main() {
|
||||||
Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
|
Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
|
||||||
Fruit::Pear(1, 2) => {}, //~ ERROR E0023
|
Fruit::Pear(1, 2) => {}, //~ ERROR E0023
|
||||||
Fruit::Orange(a, b) => {}, //~ ERROR E0023
|
Fruit::Orange(a, b) => {}, //~ ERROR E0023
|
||||||
|
Fruit::Banana() => {}, //~ ERROR E0023
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,19 @@ help: missing parenthesis
|
||||||
LL | Fruit::Orange((a, b)) => {},
|
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`.
|
For more information about this error, try `rustc --explain E0023`.
|
||||||
|
|
Loading…
Reference in a new issue