Skip to content

Commit fac9991

Browse files
committed
rustc_typeck: correctly track "always-diverges" and "has-type-errors".
1 parent 02a638a commit fac9991

26 files changed

+341
-209
lines changed

src/libpanic_abort/lib.rs

Lines changed: 1 addition & 1 deletion
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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,6 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
460460
1 => panic!("make_input should have provided valid inputs"),
461461
_ => early_error(sopts.error_format, "multiple input filenames provided"),
462462
}
463-
464-
None
465463
}
466464

467465
fn late_callback(&mut self,

src/librustc_typeck/check/_match.rs

Lines changed: 14 additions & 5 deletions
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::FnvHashMap;
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,12 +388,17 @@ 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+
let mut all_pats_diverge = Diverges::WarnedAlways;
396397
for arm in arms {
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
}
400403
}
401404

@@ -410,6 +413,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
410413
// type in that case)
411414
let expected = expected.adjust_for_branches(self);
412415
let mut result_ty = self.next_diverging_ty_var();
416+
let mut all_bodies_diverge = Diverges::WarnedAlways;
413417
let coerce_first = match expected {
414418
// We don't coerce to `()` so that if the match expression is a
415419
// statement it's branches can have any consistent type. That allows
@@ -424,9 +428,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
424428

425429
for (i, arm) in arms.iter().enumerate() {
426430
if let Some(ref e) = arm.guard {
431+
self.diverges.set(Diverges::Maybe);
427432
self.check_expr_has_type(e, tcx.types.bool);
428433
}
434+
435+
self.diverges.set(Diverges::Maybe);
429436
let arm_ty = self.check_expr_with_expectation(&arm.body, expected);
437+
all_bodies_diverge &= self.diverges.get();
430438

431439
if result_ty.references_error() || arm_ty.references_error() {
432440
result_ty = tcx.types.err;
@@ -476,11 +484,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
476484
};
477485
}
478486

487+
// We won't diverge unless the discriminant or all arms diverge.
488+
self.diverges.set(discrim_diverges | all_pats_diverge | all_bodies_diverge);
489+
479490
result_ty
480491
}
481-
}
482492

483-
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
484493
fn check_pat_struct(&self,
485494
pat: &'gcx hir::Pat,
486495
path: &hir::Path,

0 commit comments

Comments
 (0)