From 943f62c618b0f5066498235f905234a505921574 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Fri, 6 Feb 2015 23:52:35 +0800 Subject: [PATCH] Make bottom type fallback lazy PR #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 #21878 --- src/librustc/middle/infer/resolve.rs | 9 ++++-- src/librustc_typeck/check/mod.rs | 20 +++++-------- src/test/compile-fail/bot-ambig.rs | 27 +++++++++++++++++ src/test/compile-fail/bot-wrong-annotation.rs | 28 ++++++++++++++++++ .../issue-6458-1.rs | 4 +-- src/test/run-fail/bot-annotated.rs | 29 +++++++++++++++++++ 6 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 src/test/compile-fail/bot-ambig.rs create mode 100644 src/test/compile-fail/bot-wrong-annotation.rs rename src/test/{run-fail => compile-fail}/issue-6458-1.rs (86%) create mode 100644 src/test/run-fail/bot-annotated.rs diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs index 7bb3106b0ba6c..6dc9664c68f9a 100644 --- a/src/librustc/middle/infer/resolve.rs +++ b/src/librustc/middle/infer/resolve.rs @@ -82,8 +82,13 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> { let t = self.infcx.shallow_resolve(t); match t.sty { ty::ty_infer(ty::TyVar(vid)) => { - self.err = Some(unresolved_ty(vid)); - self.tcx().types.err + if self.infcx.type_var_diverges(t) { + // Apply type fallbacks: ! gets replaced with () + ty::mk_nil(self.tcx()) + } else { + self.err = Some(unresolved_ty(vid)); + self.tcx().types.err + } } ty::ty_infer(ty::IntVar(vid)) => { self.err = Some(unresolved_int_ty(vid)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fb05450373f7d..50dbff9dbec26 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1338,23 +1338,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } /// Apply "fallbacks" to some types - /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. + /// Unconstrained ints gets replaced with i32, and unconstrained floats with f64. pub fn default_type_parameters(&self) { use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() { let resolved = self.infcx().resolve_type_vars_if_possible(ty); - if self.infcx().type_var_diverges(resolved) { - demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx())); - } else { - match self.infcx().type_is_unconstrained_numeric(resolved) { - UnconstrainedInt => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) - }, - UnconstrainedFloat => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64) - } - Neither => { } + match self.infcx().type_is_unconstrained_numeric(resolved) { + UnconstrainedInt => { + demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) + }, + UnconstrainedFloat => { + demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64) } + Neither => { } } } } diff --git a/src/test/compile-fail/bot-ambig.rs b/src/test/compile-fail/bot-ambig.rs new file mode 100644 index 0000000000000..61f8b1f68c744 --- /dev/null +++ b/src/test/compile-fail/bot-ambig.rs @@ -0,0 +1,27 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure that bottom type fallback doesn't introduce type system +// holes. See issue #21878 for more details. + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +struct Error; +impl Error { + fn foo(&self) -> ! { loop {} } +} + +fn bar() -> Result { loop {} } + +fn main() { + let _ = bar().unwrap_or_else(|e| e.foo()); //~ ERROR unable to infer enough type information +} diff --git a/src/test/compile-fail/bot-wrong-annotation.rs b/src/test/compile-fail/bot-wrong-annotation.rs new file mode 100644 index 0000000000000..1c5d421dc8b73 --- /dev/null +++ b/src/test/compile-fail/bot-wrong-annotation.rs @@ -0,0 +1,28 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure that bottom type fallback doesn't introduce type system +// holes. See issue #21878 for more details. + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +struct Error; +impl Error { + fn foo(&self) -> ! { loop {} } +} + +fn bar() -> Result { loop {} } + +fn main() { + let _: u8 = bar().unwrap_or_else(|e| e.foo()); + //~^ ERROR the trait `Foo` is not implemented for the type `u8` +} diff --git a/src/test/run-fail/issue-6458-1.rs b/src/test/compile-fail/issue-6458-1.rs similarity index 86% rename from src/test/run-fail/issue-6458-1.rs rename to src/test/compile-fail/issue-6458-1.rs index 631517f6a3ca6..fd03e38cac2c2 100644 --- a/src/test/run-fail/issue-6458-1.rs +++ b/src/test/compile-fail/issue-6458-1.rs @@ -8,7 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:explicit panic - fn foo(t: T) {} -fn main() { foo(panic!()) } +fn main() { foo(panic!()) } //~ ERROR unable to infer enough type information diff --git a/src/test/run-fail/bot-annotated.rs b/src/test/run-fail/bot-annotated.rs new file mode 100644 index 0000000000000..e3d138de6404b --- /dev/null +++ b/src/test/run-fail/bot-annotated.rs @@ -0,0 +1,29 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Make sure that bottom type fallback doesn't introduce type system +// holes. See issue #21878 for more details. + +// error-pattern:explicit panic + +trait Foo {} +impl Foo for () {} +impl Foo for i32 {} + +struct Error; +impl Error { + fn foo(&self) -> ! { panic!() } +} + +fn bar() -> Result { panic!() } + +fn main() { + let _: i32 = bar().unwrap_or_else(|e| e.foo()); +}