Skip to content

Commit aeb2414

Browse files
authored
Rollup merge of #64748 - Centril:fix-64744, r=estebank
Fix #64744. Account for the Zero sub-pattern case. Fixes #64744. r? @estebank
2 parents c9dbaec + 7b71abd commit aeb2414

File tree

3 files changed

+62
-15
lines changed

3 files changed

+62
-15
lines changed

src/librustc_typeck/check/pat.rs

+46-13
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
676676
}
677677
} else {
678678
// Pattern has wrong number of fields.
679-
self.e0023(pat.span, res, &subpats, &variant.fields, expected);
679+
self.e0023(pat.span, res, qpath, subpats, &variant.fields, expected);
680680
on_error();
681681
return tcx.types.err;
682682
}
@@ -687,22 +687,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
687687
&self,
688688
pat_span: Span,
689689
res: Res,
690+
qpath: &hir::QPath,
690691
subpats: &'tcx [P<Pat>],
691692
fields: &[ty::FieldDef],
692693
expected: Ty<'tcx>
693694
) {
694695
let subpats_ending = pluralise!(subpats.len());
695696
let fields_ending = pluralise!(fields.len());
696-
let missing_parenthesis = match expected.sty {
697-
ty::Adt(_, substs) if fields.len() == 1 => {
698-
let field_ty = fields[0].ty(self.tcx, substs);
699-
match field_ty.sty {
700-
ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(),
701-
_ => false,
702-
}
703-
}
704-
_ => false,
705-
};
706697
let res_span = self.tcx.def_span(res.def_id());
707698
let mut err = struct_span_err!(
708699
self.tcx.sess,
@@ -723,11 +714,53 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
723714
))
724715
.span_label(res_span, format!("{} defined here", res.descr()));
725716

717+
// Identify the case `Some(x, y)` where the expected type is e.g. `Option<(T, U)>`.
718+
// More generally, the expected type wants a tuple variant with one field of an
719+
// N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern
720+
// with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`.
721+
let missing_parenthesis = match expected.sty {
722+
ty::Adt(_, substs) if fields.len() == 1 => {
723+
let field_ty = fields[0].ty(self.tcx, substs);
724+
match field_ty.sty {
725+
ty::Tuple(_) => field_ty.tuple_fields().count() == subpats.len(),
726+
_ => false,
727+
}
728+
}
729+
_ => false,
730+
};
726731
if missing_parenthesis {
732+
let (left, right) = match subpats {
733+
// This is the zero case; we aim to get the "hi" part of the `QPath`'s
734+
// span as the "lo" and then the "hi" part of the pattern's span as the "hi".
735+
// This looks like:
736+
//
737+
// help: missing parenthesis
738+
// |
739+
// L | let A(()) = A(());
740+
// | ^ ^
741+
[] => {
742+
let qpath_span = match qpath {
743+
hir::QPath::Resolved(_, path) => path.span,
744+
hir::QPath::TypeRelative(_, ps) => ps.ident.span,
745+
};
746+
(qpath_span.shrink_to_hi(), pat_span)
747+
},
748+
// Easy case. Just take the "lo" of the first sub-pattern and the "hi" of the
749+
// last sub-pattern. In the case of `A(x)` the first and last may coincide.
750+
// This looks like:
751+
//
752+
// help: missing parenthesis
753+
// |
754+
// L | let A((x, y)) = A((1, 2));
755+
// | ^ ^
756+
[first, ..] => (first.span.shrink_to_lo(), subpats.last().unwrap().span),
757+
};
727758
err.multipart_suggestion(
728759
"missing parenthesis",
729-
vec![(subpats[0].span.shrink_to_lo(), "(".to_string()),
730-
(subpats[subpats.len()-1].span.shrink_to_hi(), ")".to_string())],
760+
vec![
761+
(left, "(".to_string()),
762+
(right.shrink_to_hi(), ")".to_string()),
763+
],
731764
Applicability::MachineApplicable,
732765
);
733766
}

src/test/ui/error-codes/E0023.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ enum Fruit {
22
Apple(String, String),
33
Pear(u32),
44
Orange((String, String)),
5+
Banana(()),
56
}
67

7-
88
fn main() {
99
let x = Fruit::Apple(String::new(), String::new());
1010
match x {
1111
Fruit::Apple(a) => {}, //~ ERROR E0023
1212
Fruit::Apple(a, b, c) => {}, //~ ERROR E0023
1313
Fruit::Pear(1, 2) => {}, //~ ERROR E0023
1414
Fruit::Orange(a, b) => {}, //~ ERROR E0023
15+
Fruit::Banana() => {}, //~ ERROR E0023
1516
}
1617
}

src/test/ui/error-codes/E0023.stderr

+14-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ help: missing parenthesis
3838
LL | Fruit::Orange((a, b)) => {},
3939
| ^ ^
4040

41-
error: aborting due to 4 previous errors
41+
error[E0023]: this pattern has 0 fields, but the corresponding tuple variant has 1 field
42+
--> $DIR/E0023.rs:15:9
43+
|
44+
LL | Banana(()),
45+
| ---------- tuple variant defined here
46+
...
47+
LL | Fruit::Banana() => {},
48+
| ^^^^^^^^^^^^^^^ expected 1 field, found 0
49+
help: missing parenthesis
50+
|
51+
LL | Fruit::Banana(()) => {},
52+
| ^ ^
53+
54+
error: aborting due to 5 previous errors
4255

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

0 commit comments

Comments
 (0)