Skip to content

Commit d289f55

Browse files
committed
Move empty match check to check_exhaustive
1 parent 3532835 commit d289f55

File tree

1 file changed

+56
-53
lines changed

1 file changed

+56
-53
lines changed

src/librustc_mir/hair/pattern/check_match.rs

Lines changed: 56 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -166,60 +166,10 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
166166
// Fourth, check for unreachable arms.
167167
let matrix = check_arms(cx, &inlined_arms, source);
168168

169-
// Then, if the match has no arms, check whether the scrutinee
170-
// is uninhabited.
171-
let scrut_ty = self.tables.node_type(scrut.hir_id);
172-
if inlined_arms.is_empty() {
173-
let scrutinee_is_visibly_uninhabited = if self.tcx.features().exhaustive_patterns {
174-
let module = self.tcx.hir().get_module_parent(scrut.hir_id);
175-
self.tcx.is_ty_uninhabited_from(module, scrut_ty)
176-
} else {
177-
match scrut_ty.kind {
178-
ty::Never => true,
179-
ty::Adt(def, _) if def.is_enum() => {
180-
def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
181-
}
182-
_ => false,
183-
}
184-
};
185-
if scrutinee_is_visibly_uninhabited {
186-
// If the type *is* uninhabited, it's vacuously exhaustive.
187-
// This early return is only needed here because in the absence of the
188-
// `exhaustive_patterns` feature, empty matches are not detected by `is_useful`
189-
// to exhaustively match uninhabited types.
190-
return;
191-
} else {
192-
// We know the type is inhabited, so this must be wrong
193-
let (def_span, non_empty_enum) = match scrut_ty.kind {
194-
ty::Adt(def, _) if def.is_enum() => {
195-
(self.tcx.hir().span_if_local(def.did), !def.variants.is_empty())
196-
}
197-
_ => (None, false),
198-
};
199-
200-
if non_empty_enum {
201-
// Continue to the normal code path to display missing variants.
202-
} else {
203-
let mut err = create_e0004(
204-
self.tcx.sess,
205-
scrut.span,
206-
format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
207-
);
208-
err.help(
209-
"ensure that all possible cases are being handled, \
210-
possibly by adding wildcards or more match arms",
211-
);
212-
if let Some(sp) = def_span {
213-
err.span_label(sp, format!("`{}` defined here", scrut_ty));
214-
}
215-
err.emit();
216-
return;
217-
}
218-
}
219-
}
220-
221169
// Fifth, check if the match is exhaustive.
222-
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id);
170+
let scrut_ty = self.tables.node_type(scrut.hir_id);
171+
let is_empty_match = inlined_arms.is_empty();
172+
check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id, is_empty_match);
223173
})
224174
}
225175

@@ -483,7 +433,60 @@ fn check_exhaustive<'p, 'tcx>(
483433
sp: Span,
484434
matrix: &Matrix<'p, 'tcx>,
485435
hir_id: HirId,
436+
is_empty_match: bool,
486437
) {
438+
// If the match has no arms, check whether the scrutinee is uninhabited.
439+
// Note: An empty match isn't the same as an empty matrix for diagnostics purposes, since an
440+
// empty matrix can occur when there are arms, if those arms all have guards.
441+
if is_empty_match {
442+
let scrutinee_is_visibly_uninhabited = if cx.tcx.features().exhaustive_patterns {
443+
let module = cx.tcx.hir().get_module_parent(hir_id);
444+
cx.tcx.is_ty_uninhabited_from(module, scrut_ty)
445+
} else {
446+
match scrut_ty.kind {
447+
ty::Never => true,
448+
ty::Adt(def, _) if def.is_enum() => {
449+
def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
450+
}
451+
_ => false,
452+
}
453+
};
454+
if scrutinee_is_visibly_uninhabited {
455+
// If the type *is* uninhabited, it's vacuously exhaustive.
456+
// This early return is only needed here because in the absence of the
457+
// `exhaustive_patterns` feature, empty matches are not detected by `is_useful`
458+
// to exhaustively match uninhabited types.
459+
return;
460+
} else {
461+
// We know the type is inhabited, so this must be wrong
462+
let (def_span, non_empty_enum) = match scrut_ty.kind {
463+
ty::Adt(def, _) if def.is_enum() => {
464+
(cx.tcx.hir().span_if_local(def.did), !def.variants.is_empty())
465+
}
466+
_ => (None, false),
467+
};
468+
469+
if non_empty_enum {
470+
// Continue to the normal code path to display missing variants.
471+
} else {
472+
let mut err = create_e0004(
473+
cx.tcx.sess,
474+
sp,
475+
format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
476+
);
477+
err.help(
478+
"ensure that all possible cases are being handled, \
479+
possibly by adding wildcards or more match arms",
480+
);
481+
if let Some(sp) = def_span {
482+
err.span_label(sp, format!("`{}` defined here", scrut_ty));
483+
}
484+
err.emit();
485+
return;
486+
}
487+
}
488+
}
489+
487490
let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
488491
Ok(_) => return,
489492
Err(err) => err,

0 commit comments

Comments
 (0)