Skip to content

Commit 6b3cc0b

Browse files
committed
rustc_typeck: correctly track "always-diverges" and "has-type-errors".
1 parent ff0830d commit 6b3cc0b

26 files changed

+345
-212
lines changed

src/libpanic_abort/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ pub unsafe extern fn __rust_maybe_catch_panic(f: fn(*mut u8),
5353
// now hopefully.
5454
#[no_mangle]
5555
pub unsafe extern fn __rust_start_panic(_data: usize, _vtable: usize) -> u32 {
56-
return abort();
56+
abort();
5757

5858
#[cfg(unix)]
5959
unsafe fn abort() -> ! {

src/librustc_driver/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -455,8 +455,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
455455
1 => panic!("make_input should have provided valid inputs"),
456456
_ => early_error(sopts.error_format, "multiple input filenames provided"),
457457
}
458-
459-
None
460458
}
461459

462460
fn late_callback(&mut self,

src/librustc_typeck/check/_match.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc::hir::def::{Def, CtorKind};
1313
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
1414
use rustc::infer::{self, InferOk, TypeOrigin};
1515
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
16-
use check::{FnCtxt, Expectation};
16+
use check::{FnCtxt, Expectation, Diverges};
1717
use util::nodemap::FxHashMap;
1818

1919
use std::collections::hash_map::Entry::{Occupied, Vacant};
@@ -360,9 +360,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
360360
}
361361
true
362362
}
363-
}
364363

365-
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
366364
pub fn check_match(&self,
367365
expr: &'gcx hir::Expr,
368366
discrim: &'gcx hir::Expr,
@@ -390,14 +388,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
390388
discrim_ty = self.next_ty_var();
391389
self.check_expr_has_type(discrim, discrim_ty);
392390
};
391+
let discrim_diverges = self.diverges.get();
392+
self.diverges.set(Diverges::Maybe);
393393

394394
// Typecheck the patterns first, so that we get types for all the
395395
// bindings.
396-
for arm in arms {
396+
let all_arm_pats_diverge: Vec<_> = arms.iter().map(|arm| {
397+
let mut all_pats_diverge = Diverges::WarnedAlways;
397398
for p in &arm.pats {
399+
self.diverges.set(Diverges::Maybe);
398400
self.check_pat(&p, discrim_ty);
401+
all_pats_diverge &= self.diverges.get();
399402
}
400-
}
403+
all_pats_diverge
404+
}).collect();
401405

402406
// Now typecheck the blocks.
403407
//
@@ -410,6 +414,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
410414
// type in that case)
411415
let expected = expected.adjust_for_branches(self);
412416
let mut result_ty = self.next_diverging_ty_var();
417+
let mut all_arms_diverge = Diverges::WarnedAlways;
413418
let coerce_first = match expected {
414419
// We don't coerce to `()` so that if the match expression is a
415420
// statement it's branches can have any consistent type. That allows
@@ -422,11 +427,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
422427
_ => result_ty
423428
};
424429

425-
for (i, arm) in arms.iter().enumerate() {
430+
for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
426431
if let Some(ref e) = arm.guard {
432+
self.diverges.set(pats_diverge);
427433
self.check_expr_has_type(e, tcx.types.bool);
428434
}
435+
436+
self.diverges.set(pats_diverge);
429437
let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
438+
all_arms_diverge &= self.diverges.get();
430439

431440
if result_ty.references_error() || arm_ty.references_error() {
432441
result_ty = tcx.types.err;
@@ -476,11 +485,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
476485
};
477486
}
478487

488+
// We won't diverge unless the discriminant or all arms diverge.
489+
self.diverges.set(discrim_diverges | all_arms_diverge);
490+
479491
result_ty
480492
}
481-
}
482493

483-
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
484494
fn check_pat_struct(&self,
485495
pat: &'gcx hir::Pat,
486496
path: &hir::Path,

0 commit comments

Comments
 (0)