From 53ece7158500e561c69d6e07160518f19d8beafd Mon Sep 17 00:00:00 2001 From: Corey Richardson Date: Mon, 15 Dec 2014 09:45:28 -0500 Subject: [PATCH] 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 --- src/librustc/middle/infer/mod.rs | 21 ++++++++++- src/librustc/middle/ty.rs | 8 +++++ src/librustc_typeck/check/mod.rs | 19 ++++++++-- src/librustc_typeck/check/vtable.rs | 3 ++ src/test/compile-fail/issue-16966.rs | 3 +- ...traits-multidispatch-convert-ambig-dest.rs | 2 +- .../issue-6458-1.rs | 3 +- .../integer-literal-suffix-inference-2.rs | 2 +- .../integer-literal-suffix-inference-3.rs | 1 - .../{compile-fail => run-pass}/issue-11382.rs | 5 +-- .../{compile-fail => run-pass}/issue-15730.rs | 1 - .../{compile-fail => run-pass}/issue-16783.rs | 1 - ...ispatch-infer-convert-source-and-target.rs | 35 ------------------- ...aits-multidispatch-infer-convert-target.rs | 7 ++-- 14 files changed, 57 insertions(+), 54 deletions(-) rename src/test/{compile-fail => run-fail}/issue-6458-1.rs (92%) rename src/test/{compile-fail => run-pass}/integer-literal-suffix-inference-2.rs (88%) rename src/test/{compile-fail => run-pass}/integer-literal-suffix-inference-3.rs (89%) rename src/test/{compile-fail => run-pass}/issue-11382.rs (80%) rename src/test/{compile-fail => run-pass}/issue-15730.rs (85%) rename src/test/{compile-fail => run-pass}/issue-16783.rs (84%) delete mode 100644 src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 91fbaca26d113..d9b7e04bc7941 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 8e7470f5084b0..82a8bc3cd06c1 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 2e3552047b48b..1b45cc2f0d28c 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 15e942006f018..c85b542b6caee 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 dfa23c48afa6e..5dbf7546de224 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 3c461fd5b4b70..0a5aa1b7bd346 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 } 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 similarity index 92% rename from src/test/compile-fail/issue-6458-1.rs rename to src/test/run-fail/issue-6458-1.rs index 52a57fa2f4411..631517f6a3ca6 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) {} 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 similarity index 88% rename from src/test/compile-fail/integer-literal-suffix-inference-2.rs rename to src/test/run-pass/integer-literal-suffix-inference-2.rs index 7c862d04d206d..05973a545a20d 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 similarity index 89% rename from src/test/compile-fail/integer-literal-suffix-inference-3.rs rename to src/test/run-pass/integer-literal-suffix-inference-3.rs index dc3db98566030..05b275a0d8cab 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 similarity index 80% rename from src/test/compile-fail/issue-11382.rs rename to src/test/run-pass/issue-11382.rs index 44f6cd7719d1d..51996614d259f 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 similarity index 85% rename from src/test/compile-fail/issue-15730.rs rename to src/test/run-pass/issue-15730.rs index c29e74af03cd2..a1a5922e15003 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 similarity index 84% rename from src/test/compile-fail/issue-16783.rs rename to src/test/run-pass/issue-16783.rs index 1b52bd9c3de9d..cb12d138a5f29 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 c10029791df52..0000000000000 --- 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 or the MIT license -// , 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 { - fn convert(&self) -> Target; -} - -impl Convert for i16 { - fn convert(&self) -> u32 { - *self as u32 - } -} - -fn test(_: T, _: U, t_size: uint, u_size: uint) -where T : Convert -{ - assert_eq!(mem::size_of::(), t_size); - assert_eq!(mem::size_of::(), 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 54515f3b0d7d8..532ef7cbec6f3 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 } 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); }