Skip to content

Commit d0d7183

Browse files
committed
Mention missing constructor when complaining about inexhaustive top-level pattern
It previously, uselessly, only pointed out the constructor when the inexhaustive pattern was nested in some other pattern. Closes #2337
1 parent f112963 commit d0d7183

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

src/rustc/middle/check_alt.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ fn is_useful(tcx: ty::ctxt, m: matrix, v: [@pat]) -> useful {
122122

123123
alt pat_ctor_id(tcx, v[0]) {
124124
none {
125-
if is_complete(tcx, m, left_ty) {
125+
alt missing_ctor(tcx, m, left_ty) {
126+
none {
126127
alt ty::get(left_ty).struct {
127128
ty::ty_bool {
128129
alt is_useful_specialized(tcx, m, v, val(const_int(1i64)),
@@ -149,9 +150,14 @@ fn is_useful(tcx: ty::ctxt, m: matrix, v: [@pat]) -> useful {
149150
is_useful_specialized(tcx, m, v, single, arity, left_ty)
150151
}
151152
}
152-
} else {
153-
is_useful(tcx, vec::filter_map(m, {|r| default(tcx, r)}),
154-
vec::tail(v))
153+
}
154+
some(ctor) {
155+
alt is_useful(tcx, vec::filter_map(m, {|r| default(tcx, r)}),
156+
vec::tail(v)) {
157+
useful_ { useful(left_ty, ctor) }
158+
u { u }
159+
}
160+
}
155161
}
156162
}
157163
some(v0_ctor) {
@@ -202,13 +208,13 @@ fn is_wild(tcx: ty::ctxt, p: @pat) -> bool {
202208
}
203209
}
204210

205-
fn is_complete(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> bool {
211+
fn missing_ctor(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> option<ctor> {
206212
alt ty::get(left_ty).struct {
207213
ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_tup(_) | ty::ty_rec(_) {
208214
for m.each {|r|
209-
if !is_wild(tcx, r[0]) { ret true; }
215+
if !is_wild(tcx, r[0]) { ret none; }
210216
}
211-
ret false;
217+
ret some(single);
212218
}
213219
ty::ty_enum(eid, _) {
214220
let mut found = [];
@@ -217,9 +223,17 @@ fn is_complete(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> bool {
217223
if !vec::contains(found, id) { found += [id]; }
218224
}
219225
}
220-
found.len() == (*ty::enum_variants(tcx, eid)).len()
226+
let variants = ty::enum_variants(tcx, eid);
227+
if found.len() != (*variants).len() {
228+
for vec::each(*variants) {|v|
229+
if !found.contains(variant(v.id)) {
230+
ret some(variant(v.id));
231+
}
232+
}
233+
fail;
234+
} else { none }
221235
}
222-
ty::ty_nil { true }
236+
ty::ty_nil { none }
223237
ty::ty_bool {
224238
let mut true_found = false, false_found = false;
225239
for m.each {|r|
@@ -229,9 +243,11 @@ fn is_complete(tcx: ty::ctxt, m: matrix, left_ty: ty::t) -> bool {
229243
some(val(const_int(0i64))) { false_found = true; }
230244
}
231245
}
232-
true_found && false_found
246+
if true_found && false_found { none }
247+
else if true_found { some(val(const_int(0i64))) }
248+
else { some(val(const_int(1i64))) }
233249
}
234-
_ { false }
250+
_ { some(single) }
235251
}
236252
}
237253

src/test/compile-fail/non-exhaustive-match.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ fn main() {
1616
(a, b) {}
1717
(b, a) {}
1818
}
19+
alt a { //! ERROR b not covered
20+
a {}
21+
}
1922
// This is exhaustive, though the algorithm got it wrong at one point
2023
alt (a, b) {
2124
(a, _) {}

0 commit comments

Comments
 (0)