Skip to content

Commit 53ece71

Browse files
committed
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
1 parent c594959 commit 53ece71

14 files changed

+57
-54
lines changed

src/librustc/middle/infer/mod.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub use self::freshen::TypeFreshener;
2323

2424
use middle::subst;
2525
use middle::subst::Substs;
26-
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid};
26+
use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
2727
use middle::ty::replace_late_bound_regions;
2828
use middle::ty::{mod, Ty};
2929
use middle::ty_fold::{TypeFolder, TypeFoldable};
@@ -525,6 +525,25 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
525525
freshen::TypeFreshener::new(self)
526526
}
527527

528+
pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
529+
use middle::ty::UnconstrainedNumeric::{Neither, UnconstrainedInt, UnconstrainedFloat};
530+
match ty.sty {
531+
ty::ty_infer(ty::IntVar(vid)) => {
532+
match self.int_unification_table.borrow_mut().get(self.tcx, vid).value {
533+
None => UnconstrainedInt,
534+
_ => Neither,
535+
}
536+
},
537+
ty::ty_infer(ty::FloatVar(vid)) => {
538+
match self.float_unification_table.borrow_mut().get(self.tcx, vid).value {
539+
None => return UnconstrainedFloat,
540+
_ => Neither,
541+
}
542+
},
543+
_ => Neither,
544+
}
545+
}
546+
528547
pub fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
529548
-> CombineFields<'b, 'tcx> {
530549
CombineFields {infcx: self,

src/librustc/middle/ty.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1641,6 +1641,14 @@ pub enum InferTy {
16411641
FreshIntTy(u32),
16421642
}
16431643

1644+
#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Show, Copy)]
1645+
pub enum UnconstrainedNumeric {
1646+
UnconstrainedFloat,
1647+
UnconstrainedInt,
1648+
Neither,
1649+
}
1650+
1651+
16441652
#[deriving(Clone, RustcEncodable, RustcDecodable, Eq, Hash, Show, Copy)]
16451653
pub enum InferRegion {
16461654
ReVar(RegionVid),

src/librustc_typeck/check/mod.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,6 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
453453

454454
vtable::select_all_fcx_obligations_or_error(&fcx);
455455
regionck::regionck_fn(&fcx, id, decl, body);
456-
fcx.default_diverging_type_variables_to_nil();
457456
writeback::resolve_type_vars_in_fn(&fcx, decl, body);
458457
}
459458
_ => ccx.tcx.sess.impossible_case(body.span,
@@ -1666,10 +1665,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
16661665
}
16671666
}
16681667

1669-
pub fn default_diverging_type_variables_to_nil(&self) {
1668+
/// Apply "fallbacks" to some types
1669+
/// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64.
1670+
pub fn default_type_parameters(&self) {
1671+
use middle::ty::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither};
16701672
for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
1671-
if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(ty)) {
1673+
let resolved = self.infcx().resolve_type_vars_if_possible(ty);
1674+
if self.infcx().type_var_diverges(resolved) {
16721675
demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
1676+
} else {
1677+
match self.infcx().type_is_unconstrained_numeric(resolved) {
1678+
UnconstrainedInt => {
1679+
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32)
1680+
},
1681+
UnconstrainedFloat => {
1682+
demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64)
1683+
}
1684+
Neither => { }
1685+
}
16731686
}
16741687
}
16751688
}

src/librustc_typeck/check/vtable.rs

+3
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ pub fn register_object_cast_obligations<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
407407
pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
408408
debug!("select_all_fcx_obligations_or_error");
409409

410+
select_fcx_obligations_where_possible(fcx);
411+
fcx.default_type_parameters();
412+
410413
let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
411414
let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
412415
&fcx.inh.param_env,

src/test/compile-fail/issue-16966.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// error-pattern:type annotations required
1112
fn main() {
1213
panic!(
13-
1.2 //~ ERROR cannot determine a type for this expression
14+
std::default::Default::default()
1415
);
1516
}

src/test/compile-fail/traits-multidispatch-convert-ambig-dest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ where T : Convert<U>
3333
}
3434

3535
fn a() {
36-
test(22_i32, 44); //~ ERROR type annotations required
36+
test(22_i32, std::default::Default::default()); //~ ERROR type annotations required
3737
}
3838

3939
fn main() {}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// error-pattern:explicit panic
12+
1113
fn foo<T>(t: T) {}
1214
fn main() { foo(panic!()) }
13-
//~^ ERROR type annotations required

src/test/compile-fail/integer-literal-suffix-inference-2.rs renamed to src/test/run-pass/integer-literal-suffix-inference-2.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
fn foo(_: *const ()) {}
1212

1313
fn main() {
14-
let a = 3; //~ ERROR cannot determine a type for this local variable
14+
let a = 3;
1515
foo(&a as *const _ as *const ());
1616
}
1717

src/test/compile-fail/integer-literal-suffix-inference-3.rs renamed to src/test/run-pass/integer-literal-suffix-inference-3.rs

-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@
1010

1111
fn main() {
1212
println!("{}", std::mem::size_of_val(&1));
13-
//~^ ERROR cannot determine a type for this expression
1413
}
1514

src/test/compile-fail/issue-11382.rs renamed to src/test/run-pass/issue-11382.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,5 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
panic!(
13-
1.2
14-
//~^ ERROR cannot determine the type of this number; add a suffix to specify the type explicitly
15-
);
12+
println!("{}", 1.2);
1613
}

src/test/compile-fail/issue-15730.rs renamed to src/test/run-pass/issue-15730.rs

-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@
1212

1313
fn main() {
1414
let mut array = [1, 2, 3];
15-
//~^ ERROR cannot determine a type for this local variable: cannot determine the type of this integ
1615
let pie_slice = array[1..2];
1716
}

src/test/compile-fail/issue-16783.rs renamed to src/test/run-pass/issue-16783.rs

-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,5 @@
1010

1111
pub fn main() {
1212
let x = [1, 2, 3];
13-
//~^ ERROR cannot determine a type for this local variable: cannot determine the type of this
1413
let y = x.as_slice();
1514
}

src/test/run-pass/traits-multidispatch-infer-convert-source-and-target.rs

-35
This file was deleted.

src/test/run-pass/traits-multidispatch-infer-convert-target.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,10 @@ where T : Convert<U>
3636
}
3737

3838
fn main() {
39+
use std::default::Default;
3940
// T = i16, U = u32
40-
test(22_i16, 44, 2, 4);
41-
test(22, 44_u32, 2, 4);
41+
test(22_i16, Default::default(), 2, 4);
4242

4343
// T = u32, U = i16
44-
test(22_u32, 44, 4, 2);
45-
test(22, 44_i16, 4, 2);
44+
test(22_u32, Default::default(), 4, 2);
4645
}

0 commit comments

Comments
 (0)