diff options
| author | Corey Richardson <corey@octayn.net> | 2014-12-15 09:45:28 -0500 |
|---|---|---|
| committer | Corey Richardson <corey@octayn.net> | 2015-01-01 17:12:15 -0500 |
| commit | 53ece7158500e561c69d6e07160518f19d8beafd (patch) | |
| tree | 36ae3f5c6446362e42f7c111b972170d37c24ab4 | |
| parent | c594959cdff07b5545747809bb045bfa2868ebcc (diff) | |
| download | rust-53ece7158500e561c69d6e07160518f19d8beafd.tar.gz rust-53ece7158500e561c69d6e07160518f19d8beafd.zip | |
Implement numeric fallback
Doesn't yet converge on a fixed point, but generally works. A better algorithm will come with the implementation of default type parameter fallback. If inference fails to determine an exact integral or floating point type, it will set the type to i32 or f64, respectively. Closes #16968
14 files changed, 57 insertions, 54 deletions
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 91fbaca26d1..d9b7e04bc79 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -23,7 +23,7 @@ pub use self::freshen::TypeFreshener; use middle::subst; use middle::subst::Substs; -use middle::ty::{TyVid, IntVid, FloatVid, RegionVid}; +use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric}; use middle::ty::replace_late_bound_regions; use middle::ty::{mod, Ty}; use middle::ty_fold::{TypeFolder, TypeFoldable}; @@ -525,6 +525,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { freshen::TypeFreshener::new(self) } + pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric { + use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat}; + match ty.sty { + ty::ty_infer(ty::IntVar(vid)) => { + match self.int_unification_table.borrow_mut().get(self.tcx, vid).value { + None => UnconstrainedInt, + _ => Neither, + } + }, + ty::ty_infer(ty::FloatVar(vid)) => { + match self.float_unification_table.borrow_mut().get(self.tcx, vid).value { + None => return UnconstrainedFloat, + _ => Neither, + } + }, + _ => Neither, + } + } + pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>) -> CombineFields<'b, 'tcx> { CombineFields {infcx: self, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 8e7470f5084..82a8bc3cd06 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -1641,6 +1641,14 @@ pub enum InferTy { FreshIntTy(u32), } +#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)] +pub enum UnconstrainedNumeric { + UnconstrainedFloat, + UnconstrainedInt, + Neither, +} + + #[deriving(Clone, RustcEncodable, RustcDecodable, Eq, Hash, Show, Copy)] pub enum InferRegion { ReVar(RegionVid), diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2e3552047b4..1b45cc2f0d2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -453,7 +453,6 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, vtable::select_all_fcx_obligations_or_error(&fcx); regionck::regionck_fn(&fcx, id, decl, body); - fcx.default_diverging_type_variables_to_nil(); writeback::resolve_type_vars_in_fn(&fcx, decl, body); } _ => ccx.tcx.sess.impossible_case(body.span, @@ -1666,10 +1665,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub fn default_diverging_type_variables_to_nil(&self) { + /// Apply "fallbacks" to some types + /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. + pub fn default_type_parameters(&self) { + use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() { - if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(ty)) { + 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 => { } + } } } } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 15e942006f0..c85b542b6ca 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -407,6 +407,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) { debug!("select_all_fcx_obligations_or_error"); + select_fcx_obligations_where_possible(fcx); + fcx.default_type_parameters(); + let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut(); let r = fulfillment_cx.select_all_or_error(fcx.infcx(), &fcx.inh.param_env, diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs index dfa23c48afa..5dbf7546de2 100644 --- a/src/test/compile-fail/issue-16966.rs +++ b/src/test/compile-fail/issue-16966.rs @@ -8,8 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// error-pattern:type annotations required fn main() { panic!( - 1.2 //~ ERROR cannot determine a type for this expression + std::default::Default::default() ); } diff --git a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs index 3c461fd5b4b..0a5aa1b7bd3 100644 --- a/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs +++ b/src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs @@ -33,7 +33,7 @@ where T : Convert<U> } fn a() { - test(22_i32, 44); //~ ERROR type annotations required + test(22_i32, std::default::Default::default()); //~ ERROR type annotations required } fn main() {} diff --git a/src/test/compile-fail/issue-6458-1.rs b/src/test/run-fail/issue-6458-1.rs index 52a57fa2f44..631517f6a3c 100644 --- a/src/test/compile-fail/issue-6458-1.rs +++ b/src/test/run-fail/issue-6458-1.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// error-pattern:explicit panic + fn foo<T>(t: T) {} fn main() { foo(panic!()) } - //~^ ERROR type annotations required diff --git a/src/test/compile-fail/integer-literal-suffix-inference-2.rs b/src/test/run-pass/integer-literal-suffix-inference-2.rs index 7c862d04d20..05973a545a2 100644 --- a/src/test/compile-fail/integer-literal-suffix-inference-2.rs +++ b/src/test/run-pass/integer-literal-suffix-inference-2.rs @@ -11,7 +11,7 @@ fn foo(_: *const ()) {} fn main() { - let a = 3; //~ ERROR cannot determine a type for this local variable + let a = 3; foo(&a as *const _ as *const ()); } diff --git a/src/test/compile-fail/integer-literal-suffix-inference-3.rs b/src/test/run-pass/integer-literal-suffix-inference-3.rs index dc3db985660..05b275a0d8c 100644 --- a/src/test/compile-fail/integer-literal-suffix-inference-3.rs +++ b/src/test/run-pass/integer-literal-suffix-inference-3.rs @@ -10,6 +10,5 @@ fn main() { println!("{}", std::mem::size_of_val(&1)); - //~^ ERROR cannot determine a type for this expression } diff --git a/src/test/compile-fail/issue-11382.rs b/src/test/run-pass/issue-11382.rs index 44f6cd7719d..51996614d25 100644 --- a/src/test/compile-fail/issue-11382.rs +++ b/src/test/run-pass/issue-11382.rs @@ -9,8 +9,5 @@ // except according to those terms. fn main() { -panic!( - 1.2 -//~^ ERROR cannot determine the type of this number; add a suffix to specify the type explicitly -); + println!("{}", 1.2); } diff --git a/src/test/compile-fail/issue-15730.rs b/src/test/run-pass/issue-15730.rs index c29e74af03c..a1a5922e150 100644 --- a/src/test/compile-fail/issue-15730.rs +++ b/src/test/run-pass/issue-15730.rs @@ -12,6 +12,5 @@ fn main() { let mut array = [1, 2, 3]; -//~^ ERROR cannot determine a type for this local variable: cannot determine the type of this integ let pie_slice = array[1..2]; } diff --git a/src/test/compile-fail/issue-16783.rs b/src/test/run-pass/issue-16783.rs index 1b52bd9c3de..cb12d138a5f 100644 --- a/src/test/compile-fail/issue-16783.rs +++ b/src/test/run-pass/issue-16783.rs @@ -10,6 +10,5 @@ pub fn main() { let x = [1, 2, 3]; - //~^ ERROR cannot determine a type for this local variable: cannot determine the type of this let y = x.as_slice(); } diff --git a/src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs b/src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs deleted file mode 100644 index c10029791df..00000000000 --- a/src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 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 <LICENSE-APACHE or -// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test that if there is one impl we can infer everything. - -use std::mem; - -trait Convert<Target> { - fn convert(&self) -> Target; -} - -impl Convert<u32> for i16 { - fn convert(&self) -> u32 { - *self as u32 - } -} - -fn test<T,U>(_: T, _: U, t_size: uint, u_size: uint) -where T : Convert<U> -{ - assert_eq!(mem::size_of::<T>(), t_size); - assert_eq!(mem::size_of::<U>(), u_size); -} - -fn main() { - // T = i16, U = u32 - test(22, 44, 2, 4); -} diff --git a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs index 54515f3b0d7..532ef7cbec6 100644 --- a/src/test/run-pass/traits-multidispatch-infer-convert-target.rs +++ b/src/test/run-pass/traits-multidispatch-infer-convert-target.rs @@ -36,11 +36,10 @@ where T : Convert<U> } fn main() { + use std::default::Default; // T = i16, U = u32 - test(22_i16, 44, 2, 4); - test(22, 44_u32, 2, 4); + test(22_i16, Default::default(), 2, 4); // T = u32, U = i16 - test(22_u32, 44, 4, 2); - test(22, 44_i16, 4, 2); + test(22_u32, Default::default(), 4, 2); } |
