From 4030aaff2074487dd432531378579a6cce33e626 Mon Sep 17 00:00:00 2001 From: Graydon Hoare Date: Wed, 30 Jan 2013 16:21:10 -0800 Subject: [PATCH] rustc: make integral type inference transactional, close #3211, close #4401, close #3398. --- src/libcore/int-template.rs | 38 ------------------- src/libcore/to_str.rs | 4 +- src/libcore/uint-template.rs | 25 ------------ src/libcore/uint-template/uint.rs | 33 +++++++++++++++- src/librustc/middle/privacy.rs | 2 +- src/librustc/middle/typeck/check/method.rs | 5 +-- src/librustc/middle/typeck/infer/mod.rs | 9 ++--- src/libstd/cmp.rs | 6 +-- .../run-pass/fn-pattern-expected-type-2.rs | 2 +- src/test/run-pass/generic-newtype-struct.rs | 2 +- src/test/run-pass/issue-3211.rs | 8 ++++ src/test/run-pass/issue-4401.rs | 8 ++++ .../run-pass/numeric-method-autoexport.rs | 13 +------ 13 files changed, 64 insertions(+), 91 deletions(-) create mode 100644 src/test/run-pass/issue-3211.rs create mode 100644 src/test/run-pass/issue-4401.rs diff --git a/src/libcore/int-template.rs b/src/libcore/int-template.rs index 34e82890b47..532dd0007d5 100644 --- a/src/libcore/int-template.rs +++ b/src/libcore/int-template.rs @@ -18,7 +18,6 @@ use char; use cmp::{Eq, Ord}; use cmp; use from_str::FromStr; -use iter; use num; use num::Num::from_int; use prelude::*; @@ -201,26 +200,6 @@ impl T: num::One { static pure fn one() -> T { 1 } } -impl T: iter::Times { - #[inline(always)] - #[doc = "A convenience form for basic iteration. Given a variable `x` \ - of any numeric type, the expression `for x.times { /* anything */ }` \ - will execute the given function exactly x times. If we assume that \ - `x` is an int, this is functionally equivalent to \ - `for int::range(0, x) |_i| { /* anything */ }`."] - pure fn times(&self, it: fn() -> bool) { - if is_negative(*self) { - fail fmt!("The .times method expects a nonnegative number, \ - but found %?", self); - } - let mut i = *self; - while i > 0 { - if !it() { break } - i -= 1; - } - } -} - /** * Parse a buffer of bytes * @@ -357,23 +336,6 @@ fn test_interfaces() { test(10 as T); } -#[test] -fn test_times() { - use iter::Times; - let ten = 10 as T; - let mut accum = 0; - for ten.times { accum += 1; } - assert (accum == 10); -} - -#[test] -#[should_fail] -#[ignore(cfg(windows))] -fn test_times_negative() { - use iter::Times; - for (-10).times { log(error, ~"nope!"); } -} - #[test] pub fn test_ranges() { let mut l = ~[]; diff --git a/src/libcore/to_str.rs b/src/libcore/to_str.rs index 3f2f2e99ee8..b1fb1fdd483 100644 --- a/src/libcore/to_str.rs +++ b/src/libcore/to_str.rs @@ -146,8 +146,8 @@ impl ~A: ToStr { mod tests { #[test] fn test_simple_types() { - assert 1.to_str() == ~"1"; - assert (-1).to_str() == ~"-1"; + assert 1i.to_str() == ~"1"; + assert (-1i).to_str() == ~"-1"; assert 200u.to_str() == ~"200"; assert 2u8.to_str() == ~"2"; assert true.to_str() == ~"true"; diff --git a/src/libcore/uint-template.rs b/src/libcore/uint-template.rs index 637fd408e73..e4cc6651958 100644 --- a/src/libcore/uint-template.rs +++ b/src/libcore/uint-template.rs @@ -18,7 +18,6 @@ use T_SIGNED = self::inst::T_SIGNED; use char; use cmp::{Eq, Ord}; use from_str::FromStr; -use iter; use num; use option::{None, Option, Some}; use str; @@ -161,22 +160,6 @@ impl T: num::One { static pure fn one() -> T { 1 } } -impl T: iter::Times { - #[inline(always)] - #[doc = "A convenience form for basic iteration. Given a variable `x` \ - of any numeric type, the expression `for x.times { /* anything */ }` \ - will execute the given function exactly x times. If we assume that \ - `x` is an int, this is functionally equivalent to \ - `for int::range(0, x) |_i| { /* anything */ }`."] - pure fn times(&self, it: fn() -> bool) { - let mut i = *self; - while i > 0 { - if !it() { break } - i -= 1; - } - } -} - /** * Parse a buffer of bytes * @@ -349,14 +332,6 @@ pub fn to_str_radix17() { uint::to_str(100u, 17u); } -#[test] -pub fn test_times() { - use iter::Times; - let ten = 10 as T; - let mut accum = 0; - for ten.times { accum += 1; } - assert (accum == 10); -} use io; #[test] pub fn test_ranges() { diff --git a/src/libcore/uint-template/uint.rs b/src/libcore/uint-template/uint.rs index f54290f8394..93f59cd2d9f 100644 --- a/src/libcore/uint-template/uint.rs +++ b/src/libcore/uint-template/uint.rs @@ -15,9 +15,10 @@ pub use self::inst::{ next_power_of_two }; -mod inst { +pub mod inst { use sys; use uint; + use iter; pub type T = uint; #[allow(non_camel_case_types)] @@ -107,6 +108,27 @@ mod inst { return true; } + pub impl uint: iter::Times { + #[inline(always)] + /** + * A convenience form for basic iteration. Given a uint `x`, + * `for x.times { ... }` executes the given block x times. + * + * Equivalent to `for uint::range(0, x) |_| { ... }`. + * + * Not defined on all integer types to permit unambiguous + * use with integer literals of inferred integer-type as + * the self-value (eg. `for 100.times { ... }`). + */ + pure fn times(&self, it: fn() -> bool) { + let mut i = *self; + while i > 0 { + if !it() { break } + i -= 1; + } + } + } + /// Returns the smallest power of 2 greater than or equal to `n` #[inline(always)] pub pure fn next_power_of_two(n: uint) -> uint { @@ -174,4 +196,13 @@ mod inst { assert(uint::div_ceil(3u, 4u) == 1u); assert(uint::div_round(3u, 4u) == 1u); } + + #[test] + pub fn test_times() { + use iter::Times; + let ten = 10 as uint; + let mut accum = 0; + for ten.times { accum += 1; } + assert (accum == 10); + } } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index a7d89234030..1c92526d3d3 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -41,7 +41,7 @@ pub fn check_crate(tcx: ty::ctxt, let legacy_exports = has_legacy_export_attr(crate.node.attrs); // Adds structs that are privileged to this scope. - let add_privileged_items: @fn(&[@ast::item]) -> int = |items| { + let add_privileged_items: @fn(&[@ast::item]) -> uint = |items| { let mut count = 0; for items.each |item| { match item.node { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 5c012f474ab..44dd65f238b 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -257,7 +257,6 @@ pub impl LookupContext { match ty::deref(self.tcx(), ty, false) { None => None, Some(t) => { - //FIXME(#3211) -- probably want to force ivars Some(structurally_resolved_type(self.fcx, self.self_expr.span, t.ty)) @@ -907,8 +906,8 @@ pub impl LookupContext { let tcx = self.tcx(); match ty::get(self_ty).sty { ty_box(*) | ty_uniq(*) | ty_rptr(*) | - ty_infer(IntVar(_)) | // FIXME(#3211)---should be resolved - ty_infer(FloatVar(_)) | // FIXME(#3211)---should be resolved + ty_infer(IntVar(_)) | + ty_infer(FloatVar(_)) | ty_self | ty_param(*) | ty_nil | ty_bot | ty_bool | ty_int(*) | ty_uint(*) | ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_rec(*) | diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 7cc09733c20..2272e99995d 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -562,11 +562,10 @@ impl @InferCtxt { debug!("rollback!"); rollback_to(&self.ty_var_bindings, snapshot.ty_var_bindings_len); - // FIXME(#3211) -- int_var and float_var not transactional - //rollback_to(&self.int_var_bindings, - // snapshot.int_var_bindings_len); - //rollback_to(&self.float_var_bindings, - // snapshot.float_var_bindings_len); + rollback_to(&self.int_var_bindings, + snapshot.int_var_bindings_len); + rollback_to(&self.float_var_bindings, + snapshot.float_var_bindings_len); self.region_vars.rollback_to(snapshot.region_vars_snapshot); } diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs index 472f03d0551..7f5f65fe52b 100644 --- a/src/libstd/cmp.rs +++ b/src/libstd/cmp.rs @@ -54,13 +54,13 @@ impl f64: FuzzyEq { #[test] fn test_fuzzy_equals() { - assert (&1.0).fuzzy_eq(&1.0); + assert (&1.0f).fuzzy_eq(&1.0); assert (&1.0f32).fuzzy_eq(&1.0f32); assert (&1.0f64).fuzzy_eq(&1.0f64); } #[test] fn test_fuzzy_eq_eps() { - assert (&1.2).fuzzy_eq_eps(&0.9, &0.5); - assert !(&1.5).fuzzy_eq_eps(&0.9, &0.5); + assert (&1.2f).fuzzy_eq_eps(&0.9, &0.5); + assert !(&1.5f).fuzzy_eq_eps(&0.9, &0.5); } diff --git a/src/test/run-pass/fn-pattern-expected-type-2.rs b/src/test/run-pass/fn-pattern-expected-type-2.rs index 56c5b7f23c7..2442af5a402 100644 --- a/src/test/run-pass/fn-pattern-expected-type-2.rs +++ b/src/test/run-pass/fn-pattern-expected-type-2.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - let v = [ (1, 2), (3, 4), (5, 6) ]; + let v : &[(int,int)] = &[ (1, 2), (3, 4), (5, 6) ]; for v.each |&(x, y)| { io::println(y.to_str()); io::println(x.to_str()); diff --git a/src/test/run-pass/generic-newtype-struct.rs b/src/test/run-pass/generic-newtype-struct.rs index e4c7768357c..8b9d6479ed3 100644 --- a/src/test/run-pass/generic-newtype-struct.rs +++ b/src/test/run-pass/generic-newtype-struct.rs @@ -1,7 +1,7 @@ struct S(T); fn main() { - let s = S(2); + let s = S(2i); io::println(s.to_str()); } diff --git a/src/test/run-pass/issue-3211.rs b/src/test/run-pass/issue-3211.rs new file mode 100644 index 00000000000..ecdd0a2c2a7 --- /dev/null +++ b/src/test/run-pass/issue-3211.rs @@ -0,0 +1,8 @@ +fn main() { + let mut x = 0; + for 4096.times { + x += 1; + } + assert x == 4096; + io::println(fmt!("x = %u", x)); +} \ No newline at end of file diff --git a/src/test/run-pass/issue-4401.rs b/src/test/run-pass/issue-4401.rs new file mode 100644 index 00000000000..0fc2e4f1695 --- /dev/null +++ b/src/test/run-pass/issue-4401.rs @@ -0,0 +1,8 @@ +fn main() { + let mut count = 0; + for 999_999.times() { + count += 1; + } + assert count == 999_999; + io::println(fmt!("%u", count)); +} \ No newline at end of file diff --git a/src/test/run-pass/numeric-method-autoexport.rs b/src/test/run-pass/numeric-method-autoexport.rs index 4aa2e205ed6..d94d2bf5811 100644 --- a/src/test/run-pass/numeric-method-autoexport.rs +++ b/src/test/run-pass/numeric-method-autoexport.rs @@ -15,17 +15,11 @@ fn main() { // ints // num - assert 15.add(&6) == 21; + assert 15i.add(&6) == 21; assert 15i8.add(&6i8) == 21i8; assert 15i16.add(&6i16) == 21i16; assert 15i32.add(&6i32) == 21i32; assert 15i64.add(&6i64) == 21i64; - // times - 15.times(|| false); - 15i8.times(|| false); - 15i16.times(|| false); - 15i32.times(|| false); - 15i64.times(|| false); // uints // num @@ -34,12 +28,9 @@ fn main() { assert 15u16.add(&6u16) == 21u16; assert 15u32.add(&6u32) == 21u32; assert 15u64.add(&6u64) == 21u64; + // times 15u.times(|| false); - 15u8.times(|| false); - 15u16.times(|| false); - 15u32.times(|| false); - 15u64.times(|| false); // floats // num