Skip to content

Commit 943f62c

Browse files
committed
Make bottom type fallback lazy
PR rust-lang#17603 introduced bottom type fallback but did it a bit too eagerly. This patch makes the fallback lazy so that `typeck` can run its cause and detect as many type errors as possible with regard to diverging types. Closes rust-lang#21878
1 parent f3573aa commit 943f62c

File tree

6 files changed

+100
-17
lines changed

6 files changed

+100
-17
lines changed

src/librustc/middle/infer/resolve.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,13 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
8282
let t = self.infcx.shallow_resolve(t);
8383
match t.sty {
8484
ty::ty_infer(ty::TyVar(vid)) => {
85-
self.err = Some(unresolved_ty(vid));
86-
self.tcx().types.err
85+
if self.infcx.type_var_diverges(t) {
86+
// Apply type fallbacks: ! gets replaced with ()
87+
ty::mk_nil(self.tcx())
88+
} else {
89+
self.err = Some(unresolved_ty(vid));
90+
self.tcx().types.err
91+
}
8792
}
8893
ty::ty_infer(ty::IntVar(vid)) => {
8994
self.err = Some(unresolved_int_ty(vid));

src/librustc_typeck/check/mod.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,23 +1338,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13381338
}
13391339

13401340
/// Apply "fallbacks" to some types
1341-
/// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1341+
/// Unconstrained ints gets replaced with i32, and unconstrained floats with f64.
13421342
pub fn default_type_parameters(&self) {
13431343
use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
13441344
for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
13451345
let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1346-
if self.infcx().type_var_diverges(resolved) {
1347-
demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1348-
} else {
1349-
match self.infcx().type_is_unconstrained_numeric(resolved) {
1350-
UnconstrainedInt => {
1351-
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1352-
},
1353-
UnconstrainedFloat => {
1354-
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1355-
}
1356-
Neither => { }
1346+
match self.infcx().type_is_unconstrained_numeric(resolved) {
1347+
UnconstrainedInt => {
1348+
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1349+
},
1350+
UnconstrainedFloat => {
1351+
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
13571352
}
1353+
Neither => { }
13581354
}
13591355
}
13601356
}

src/test/compile-fail/bot-ambig.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Make sure that bottom type fallback doesn't introduce type system
12+
// holes. See issue #21878 for more details.
13+
14+
trait Foo {}
15+
impl Foo for () {}
16+
impl Foo for i32 {}
17+
18+
struct Error;
19+
impl Error {
20+
fn foo(&self) -> ! { loop {} }
21+
}
22+
23+
fn bar<T: Foo>() -> Result<T, Error> { loop {} }
24+
25+
fn main() {
26+
let _ = bar().unwrap_or_else(|e| e.foo()); //~ ERROR unable to infer enough type information
27+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Make sure that bottom type fallback doesn't introduce type system
12+
// holes. See issue #21878 for more details.
13+
14+
trait Foo {}
15+
impl Foo for () {}
16+
impl Foo for i32 {}
17+
18+
struct Error;
19+
impl Error {
20+
fn foo(&self) -> ! { loop {} }
21+
}
22+
23+
fn bar<T: Foo>() -> Result<T, Error> { loop {} }
24+
25+
fn main() {
26+
let _: u8 = bar().unwrap_or_else(|e| e.foo());
27+
//~^ ERROR the trait `Foo` is not implemented for the type `u8`
28+
}

src/test/run-fail/issue-6458-1.rs renamed to src/test/compile-fail/issue-6458-1.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,5 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
// error-pattern:explicit panic
12-
1311
fn foo<T>(t: T) {}
14-
fn main() { foo(panic!()) }
12+
fn main() { foo(panic!()) } //~ ERROR unable to infer enough type information

src/test/run-fail/bot-annotated.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Make sure that bottom type fallback doesn't introduce type system
12+
// holes. See issue #21878 for more details.
13+
14+
// error-pattern:explicit panic
15+
16+
trait Foo {}
17+
impl Foo for () {}
18+
impl Foo for i32 {}
19+
20+
struct Error;
21+
impl Error {
22+
fn foo(&self) -> ! { panic!() }
23+
}
24+
25+
fn bar<T: Foo>() -> Result<T, Error> { panic!() }
26+
27+
fn main() {
28+
let _: i32 = bar().unwrap_or_else(|e| e.foo());
29+
}

0 commit comments

Comments
 (0)