diff --git a/src/libextra/dlist.rs b/src/libextra/dlist.rs index 076e86dd5b040..8e64107363785 100644 --- a/src/libextra/dlist.rs +++ b/src/libextra/dlist.rs @@ -661,7 +661,7 @@ mod tests { #[test] fn test_basic() { - let mut m = DList::new::<~int>(); + let mut m: DList<~int> = DList::new(); assert_eq!(m.pop_front(), None); assert_eq!(m.pop_back(), None); assert_eq!(m.pop_front(), None); @@ -768,7 +768,7 @@ mod tests { #[test] fn test_rotate() { - let mut n = DList::new::(); + let mut n: DList = DList::new(); n.rotate_backward(); check_links(&n); assert_eq!(n.len(), 0); n.rotate_forward(); check_links(&n); @@ -1033,7 +1033,7 @@ mod tests { #[cfg(test)] fn fuzz_test(sz: int) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); let mut v = ~[]; for i in range(0, sz) { check_links(&m); @@ -1078,7 +1078,7 @@ mod tests { #[bench] fn bench_push_front(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); do b.iter { m.push_front(0); } @@ -1086,7 +1086,7 @@ mod tests { #[bench] fn bench_push_back(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); do b.iter { m.push_back(0); } @@ -1094,7 +1094,7 @@ mod tests { #[bench] fn bench_push_back_pop_back(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); do b.iter { m.push_back(0); m.pop_back(); @@ -1103,7 +1103,7 @@ mod tests { #[bench] fn bench_push_front_pop_front(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); do b.iter { m.push_front(0); m.pop_front(); @@ -1112,7 +1112,7 @@ mod tests { #[bench] fn bench_rotate_forward(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); m.push_front(0); m.push_front(1); do b.iter { @@ -1122,7 +1122,7 @@ mod tests { #[bench] fn bench_rotate_backward(b: &mut test::BenchHarness) { - let mut m = DList::new::(); + let mut m: DList = DList::new(); m.push_front(0); m.push_front(1); do b.iter { diff --git a/src/libextra/flate.rs b/src/libextra/flate.rs index ed8cbcd0663f3..a066ea92ba1d1 100644 --- a/src/libextra/flate.rs +++ b/src/libextra/flate.rs @@ -25,13 +25,13 @@ pub mod rustrt { #[link_name = "rustrt"] extern { - pub fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void, + pub fn tdefl_compress_mem_to_heap(psrc_buf: *c_void, src_buf_len: size_t, pout_len: *mut size_t, flags: c_int) -> *c_void; - pub fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void, + pub fn tinfl_decompress_mem_to_heap(psrc_buf: *c_void, src_buf_len: size_t, pout_len: *mut size_t, flags: c_int) diff --git a/src/libextra/num/bigint.rs b/src/libextra/num/bigint.rs index 354696ef42060..7e74fff82f7a3 100644 --- a/src/libextra/num/bigint.rs +++ b/src/libextra/num/bigint.rs @@ -380,7 +380,7 @@ impl Integer for BigUint { fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) { let mut m = a; - let mut d = Zero::zero::(); + let mut d: BigUint = Zero::zero(); let mut n = 1; while m >= b { let (d0, d_unit, b_unit) = div_estimate(&m, &b, n); @@ -432,8 +432,9 @@ impl Integer for BigUint { if shift == 0 { return (BigUint::new(d), One::one(), (*b).clone()); } + let one: BigUint = One::one(); return (BigUint::from_slice(d).shl_unit(shift), - One::one::().shl_unit(shift), + one.shl_unit(shift), b.shl_unit(shift)); } } @@ -1510,11 +1511,18 @@ mod biguint_tests { #[test] fn test_is_even() { - assert!(FromStr::from_str::("1").unwrap().is_odd()); - assert!(FromStr::from_str::("2").unwrap().is_even()); - assert!(FromStr::from_str::("1000").unwrap().is_even()); - assert!(FromStr::from_str::("1000000000000000000000").unwrap().is_even()); - assert!(FromStr::from_str::("1000000000000000000001").unwrap().is_odd()); + let one: Option = FromStr::from_str("1"); + let two: Option = FromStr::from_str("2"); + let thousand: Option = FromStr::from_str("1000"); + let big: Option = + FromStr::from_str("1000000000000000000000"); + let bigger: Option = + FromStr::from_str("1000000000000000000001"); + assert!(one.unwrap().is_odd()); + assert!(two.unwrap().is_even()); + assert!(thousand.unwrap().is_even()); + assert!(big.unwrap().is_even()); + assert!(bigger.unwrap().is_odd()); assert!((BigUint::from_uint(1) << 64).is_even()); assert!(((BigUint::from_uint(1) << 64) + BigUint::from_uint(1)).is_odd()); } @@ -1599,15 +1607,19 @@ mod biguint_tests { } } - assert_eq!(FromStrRadix::from_str_radix::("Z", 10), None); - assert_eq!(FromStrRadix::from_str_radix::("_", 2), None); - assert_eq!(FromStrRadix::from_str_radix::("-1", 10), None); + let zed: Option = FromStrRadix::from_str_radix("Z", 10); + assert_eq!(zed, None); + let blank: Option = FromStrRadix::from_str_radix("_", 2); + assert_eq!(blank, None); + let minus_one: Option = FromStrRadix::from_str_radix("-1", + 10); + assert_eq!(minus_one, None); } #[test] fn test_factor() { fn factor(n: uint) -> BigUint { - let mut f= One::one::(); + let mut f: BigUint = One::one(); for i in range(2, n + 1) { // FIXME(#6102): Assignment operator for BigInt causes ICE // f *= BigUint::from_uint(i); @@ -2005,17 +2017,24 @@ mod bigint_tests { #[test] fn test_abs_sub() { - assert_eq!((-One::one::()).abs_sub(&One::one()), Zero::zero()); - assert_eq!(One::one::().abs_sub(&One::one()), Zero::zero()); - assert_eq!(One::one::().abs_sub(&Zero::zero()), One::one()); - assert_eq!(One::one::().abs_sub(&-One::one::()), - IntConvertible::from_int(2)); + let zero: BigInt = Zero::zero(); + let one: BigInt = One::one(); + assert_eq!((-one).abs_sub(&one), zero); + let one: BigInt = One::one(); + let zero: BigInt = Zero::zero(); + assert_eq!(one.abs_sub(&one), zero); + let one: BigInt = One::one(); + let zero: BigInt = Zero::zero(); + assert_eq!(one.abs_sub(&zero), one); + let one: BigInt = One::one(); + assert_eq!(one.abs_sub(&-one), IntConvertible::from_int(2)); } #[test] fn test_to_str_radix() { fn check(n: int, ans: &str) { - assert!(ans == IntConvertible::from_int::(n).to_str_radix(10)); + let n: BigInt = IntConvertible::from_int(n); + assert!(ans == n.to_str_radix(10)); } check(10, "10"); check(1, "1"); @@ -2028,7 +2047,10 @@ mod bigint_tests { #[test] fn test_from_str_radix() { fn check(s: &str, ans: Option) { - let ans = ans.map_move(|n| IntConvertible::from_int::(n)); + let ans = ans.map_move(|n| { + let x: BigInt = IntConvertible::from_int(n); + x + }); assert_eq!(FromStrRadix::from_str_radix(s, 10), ans); } check("10", Some(10)); @@ -2046,6 +2068,7 @@ mod bigint_tests { BigInt::new(Minus, ~[1, 1, 1])); assert!(-BigInt::new(Minus, ~[1, 1, 1]) == BigInt::new(Plus, ~[1, 1, 1])); - assert_eq!(-Zero::zero::(), Zero::zero::()); + let zero: BigInt = Zero::zero(); + assert_eq!(-zero, zero); } } diff --git a/src/libextra/num/rational.rs b/src/libextra/num/rational.rs index 60dd36a3b886e..41e9a488bf8ae 100644 --- a/src/libextra/num/rational.rs +++ b/src/libextra/num/rational.rs @@ -269,9 +269,13 @@ impl /// Parses `numer/denom`. fn from_str(s: &str) -> Option> { let split: ~[&str] = s.splitn_iter('/', 1).collect(); - if split.len() < 2 { return None; } - do FromStr::from_str::(split[0]).chain |a| { - do FromStr::from_str::(split[1]).chain |b| { + if split.len() < 2 { + return None + } + let a_option: Option = FromStr::from_str(split[0]); + do a_option.chain |a| { + let b_option: Option = FromStr::from_str(split[1]); + do b_option.chain |b| { Some(Ratio::new(a.clone(), b.clone())) } } @@ -282,10 +286,15 @@ impl /// Parses `numer/denom` where the numbers are in base `radix`. fn from_str_radix(s: &str, radix: uint) -> Option> { let split: ~[&str] = s.splitn_iter('/', 1).collect(); - if split.len() < 2 { None } - else { - do FromStrRadix::from_str_radix::(split[0], radix).chain |a| { - do FromStrRadix::from_str_radix::(split[1], radix).chain |b| { + if split.len() < 2 { + None + } else { + let a_option: Option = FromStrRadix::from_str_radix(split[0], + radix); + do a_option.chain |a| { + let b_option: Option = + FromStrRadix::from_str_radix(split[1], radix); + do b_option.chain |b| { Some(Ratio::new(a.clone(), b.clone())) } } @@ -496,7 +505,8 @@ mod test { #[test] fn test_from_str_fail() { fn test(s: &str) { - assert_eq!(FromStr::from_str::(s), None); + let rational: Option = FromStr::from_str(s); + assert_eq!(rational, None); } let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1"]; @@ -536,7 +546,8 @@ mod test { #[test] fn test_from_str_radix_fail() { fn test(s: &str) { - assert_eq!(FromStrRadix::from_str_radix::(s, 3), None); + let radix: Option = FromStrRadix::from_str_radix(s, 3); + assert_eq!(radix, None); } let xs = ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"]; diff --git a/src/libextra/priority_queue.rs b/src/libextra/priority_queue.rs index 4f0fed5fccf47..09b351433a26d 100644 --- a/src/libextra/priority_queue.rs +++ b/src/libextra/priority_queue.rs @@ -339,29 +339,38 @@ mod tests { #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_pop() { let mut heap = PriorityQueue::new::(); heap.pop(); } + fn test_empty_pop() { + let mut heap: PriorityQueue = PriorityQueue::new(); + heap.pop(); + } #[test] fn test_empty_maybe_pop() { - let mut heap = PriorityQueue::new::(); + let mut heap: PriorityQueue = PriorityQueue::new(); assert!(heap.maybe_pop().is_none()); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_top() { let empty = PriorityQueue::new::(); empty.top(); } + fn test_empty_top() { + let empty: PriorityQueue = PriorityQueue::new(); + empty.top(); + } #[test] fn test_empty_maybe_top() { - let empty = PriorityQueue::new::(); + let empty: PriorityQueue = PriorityQueue::new(); assert!(empty.maybe_top().is_none()); } #[test] #[should_fail] #[ignore(cfg(windows))] - fn test_empty_replace() { let mut heap = PriorityQueue::new(); heap.replace(5); } + fn test_empty_replace() { + let mut heap: PriorityQueue = PriorityQueue::new(); + heap.replace(5); + } #[test] fn test_from_iter() { diff --git a/src/libextra/ringbuf.rs b/src/libextra/ringbuf.rs index a38cb580c5057..4f2755374af02 100644 --- a/src/libextra/ringbuf.rs +++ b/src/libextra/ringbuf.rs @@ -483,7 +483,7 @@ mod tests { #[bench] fn bench_new(b: &mut test::BenchHarness) { do b.iter { - let _ = RingBuf::new::(); + let _: RingBuf = RingBuf::new(); } } diff --git a/src/libextra/treemap.rs b/src/libextra/treemap.rs index 118754ec02830..307de43a067f0 100644 --- a/src/libextra/treemap.rs +++ b/src/libextra/treemap.rs @@ -879,7 +879,8 @@ mod test_treemap { #[test] fn find_empty() { - let m = TreeMap::new::(); assert!(m.find(&5) == None); + let m: TreeMap = TreeMap::new(); + assert!(m.find(&5) == None); } #[test] @@ -1006,7 +1007,7 @@ mod test_treemap { #[test] fn test_rand_int() { - let mut map = TreeMap::new::(); + let mut map: TreeMap = TreeMap::new(); let mut ctrl = ~[]; check_equal(ctrl, &map); diff --git a/src/librustc/front/std_inject.rs b/src/librustc/front/std_inject.rs index 2a61ea28e0c6b..429a1c35b3421 100644 --- a/src/librustc/front/std_inject.rs +++ b/src/librustc/front/std_inject.rs @@ -17,6 +17,7 @@ use syntax::attr; use syntax::codemap::dummy_sp; use syntax::codemap; use syntax::fold; +use syntax::opt_vec; static STD_VERSION: &'static str = "0.8-pre"; @@ -90,12 +91,18 @@ fn inject_libstd_ref(sess: Session, crate: &ast::Crate) -> @ast::Crate { let prelude_path = ast::Path { span: dummy_sp(), global: false, - idents: ~[ - sess.ident_of("std"), - sess.ident_of("prelude") + segments: ~[ + ast::PathSegment { + identifier: sess.ident_of("std"), + lifetime: None, + types: opt_vec::Empty, + }, + ast::PathSegment { + identifier: sess.ident_of("prelude"), + lifetime: None, + types: opt_vec::Empty, + }, ], - rp: None, - types: ~[] }; let vp = @spanned(ast::view_path_glob(prelude_path, n2)); diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 597de440ae1fc..92e9e17cde7d9 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -16,14 +16,15 @@ use front::config; use std::vec; use syntax::ast_util::*; +use syntax::attr::AttrMetaMethods; use syntax::attr; use syntax::codemap::{dummy_sp, span, ExpnInfo, NameAndSpan}; use syntax::codemap; use syntax::ext::base::ExtCtxt; use syntax::fold; +use syntax::opt_vec; use syntax::print::pprust; use syntax::{ast, ast_util}; -use syntax::attr::AttrMetaMethods; type node_id_gen = @fn() -> ast::NodeId; @@ -340,19 +341,27 @@ fn nospan(t: T) -> codemap::spanned { } fn path_node(ids: ~[ast::ident]) -> ast::Path { - ast::Path { span: dummy_sp(), - global: false, - idents: ids, - rp: None, - types: ~[] } + ast::Path { + span: dummy_sp(), + global: false, + segments: ids.move_iter().map(|identifier| ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }).collect() + } } fn path_node_global(ids: ~[ast::ident]) -> ast::Path { - ast::Path { span: dummy_sp(), - global: true, - idents: ids, - rp: None, - types: ~[] } + ast::Path { + span: dummy_sp(), + global: true, + segments: ids.move_iter().map(|identifier| ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }).collect() + } } fn mk_tests(cx: &TestCtxt) -> @ast::item { diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index c8c4a396c87af..f74fecb522390 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -25,7 +25,8 @@ use syntax::codemap::{span, dummy_sp}; use syntax::diagnostic::span_handler; use syntax::parse::token; use syntax::parse::token::ident_interner; -use syntax::oldvisit; +use syntax::visit::SimpleVisitor; +use syntax::visit; // Traverses an AST, reading all the information about use'd crates and extern // libraries necessary for later resolving, typechecking, linking, etc. @@ -46,13 +47,11 @@ pub fn read_crates(diag: @mut span_handler, next_crate_num: 1, intr: intr }; - let v = - oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor { - visit_view_item: |a| visit_view_item(e, a), - visit_item: |a| visit_item(e, a), - .. *oldvisit::default_simple_visitor()}); - visit_crate(e, crate); - oldvisit::visit_crate(crate, ((), v)); + e.visit_crate(crate); + let mut visitor = visit::SimpleVisitorVisitor { + simple_visitor: e as @mut SimpleVisitor, + }; + visit::walk_crate(&mut visitor, crate, ()); dump_crates(*e.crate_cache); warn_if_multiple_versions(e, diag, *e.crate_cache); } @@ -115,103 +114,113 @@ struct Env { intr: @ident_interner } -fn visit_crate(e: &Env, c: &ast::Crate) { - let cstore = e.cstore; +impl Env { + fn visit_crate(&self, c: &ast::Crate) { + let cstore = self.cstore; - for a in c.attrs.iter().filter(|m| "link_args" == m.name()) { - match a.value_str() { - Some(ref linkarg) => { - cstore::add_used_link_args(cstore, *linkarg); - } - None => {/* fallthrough */ } + for a in c.attrs.iter().filter(|m| "link_args" == m.name()) { + match a.value_str() { + Some(ref linkarg) => { + cstore::add_used_link_args(cstore, *linkarg); + } + None => {/* fallthrough */ } + } } } } -fn visit_view_item(e: @mut Env, i: &ast::view_item) { - match i.node { - ast::view_item_extern_mod(ident, path_opt, ref meta_items, id) => { - let ident = token::ident_to_str(&ident); - let meta_items = match path_opt { - None => meta_items.clone(), - Some(p) => { - let p_path = Path(p); - match p_path.filestem() { - Some(s) => - vec::append( - ~[attr::mk_name_value_item_str(@"package_id", p), - attr::mk_name_value_item_str(@"name", s.to_managed())], - *meta_items), - None => e.diag.span_bug(i.span, "Bad package path in `extern mod` item") - } - } - }; - debug!("resolving extern mod stmt. ident: %?, meta: %?", - ident, meta_items); - let cnum = resolve_crate(e, - ident, - meta_items, - @"", - i.span); - cstore::add_extern_mod_stmt_cnum(e.cstore, id, cnum); + +impl SimpleVisitor for Env { + fn visit_view_item(&mut self, i: &ast::view_item) { + match i.node { + ast::view_item_extern_mod(ident, path_opt, ref meta_items, id) => { + let ident = token::ident_to_str(&ident); + let meta_items = match path_opt { + None => meta_items.clone(), + Some(p) => { + let p_path = Path(p); + match p_path.filestem() { + Some(s) => + vec::append( + ~[attr::mk_name_value_item_str(@"package_id", p), + attr::mk_name_value_item_str(@"name", s.to_managed())], + *meta_items), + None => { + self.diag.span_bug(i.span, + "bad package path in `extern mod` item") + } + } + } + }; + debug!("resolving extern mod stmt. ident: %?, meta: %?", + ident, meta_items); + let cnum = resolve_crate(self, + ident, + meta_items, + @"", + i.span); + cstore::add_extern_mod_stmt_cnum(self.cstore, id, cnum); + } + _ => () } - _ => () - } -} + } -fn visit_item(e: &Env, i: @ast::item) { - match i.node { - ast::item_foreign_mod(ref fm) => { - if fm.abis.is_rust() || fm.abis.is_intrinsic() { - return; - } + fn visit_item(&mut self, i: @ast::item) { + match i.node { + ast::item_foreign_mod(ref fm) => { + if fm.abis.is_rust() || fm.abis.is_intrinsic() { + return; + } - let cstore = e.cstore; - let mut already_added = false; - let link_args = i.attrs.iter() - .filter_map(|at| if "link_args" == at.name() {Some(at)} else {None}) - .collect::<~[&ast::Attribute]>(); - - match fm.sort { - ast::named => { - let link_name = i.attrs.iter() - .find(|at| "link_name" == at.name()) - .chain(|at| at.value_str()); - - let foreign_name = match link_name { - Some(nn) => { - if nn.is_empty() { - e.diag.span_fatal( - i.span, - "empty #[link_name] not allowed; use \ - #[nolink]."); + let cstore = self.cstore; + let mut already_added = false; + let link_args = i.attrs.iter() + .filter_map(|at| if "link_args" == at.name() {Some(at)} else {None}) + .collect::<~[&ast::Attribute]>(); + + match fm.sort { + ast::named => { + let link_name = i.attrs.iter() + .find(|at| "link_name" == at.name()) + .chain(|at| at.value_str()); + + let foreign_name = match link_name { + Some(nn) => { + if nn.is_empty() { + self.diag.span_fatal( + i.span, + "empty #[link_name] not allowed; use \ + #[nolink]."); + } + nn } - nn - } - None => token::ident_to_str(&i.ident) - }; - if !attr::contains_name(i.attrs, "nolink") { - already_added = - !cstore::add_used_library(cstore, foreign_name); - } - if !link_args.is_empty() && already_added { - e.diag.span_fatal(i.span, ~"library '" + foreign_name + - "' already added: can't specify link_args."); + None => token::ident_to_str(&i.ident) + }; + if !attr::contains_name(i.attrs, "nolink") { + already_added = + !cstore::add_used_library(cstore, foreign_name); + } + if !link_args.is_empty() && already_added { + self.diag.span_fatal(i.span, ~"library '" + + foreign_name + + "' already added: can't specify \ + link_args."); + } } + ast::anonymous => { /* do nothing */ } } - ast::anonymous => { /* do nothing */ } - } - for m in link_args.iter() { - match m.value_str() { - Some(linkarg) => { - cstore::add_used_link_args(cstore, linkarg); + for m in link_args.iter() { + match m.value_str() { + Some(linkarg) => { + cstore::add_used_link_args(cstore, linkarg); + } + None => { /* fallthrough */ } } - None => { /* fallthrough */ } } + } + _ => { } } - } - _ => { } } } @@ -240,7 +249,7 @@ fn existing_match(e: &Env, metas: &[@ast::MetaItem], hash: &str) return None; } -fn resolve_crate(e: @mut Env, +fn resolve_crate(e: &mut Env, ident: @str, metas: ~[@ast::MetaItem], hash: @str, @@ -308,7 +317,7 @@ fn resolve_crate(e: @mut Env, } // Go through the crate metadata and load any crates that it references -fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map { +fn resolve_crate_deps(e: &mut Env, cdata: @~[u8]) -> cstore::cnum_map { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 81a2e863bde00..34c100a95f2f3 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -335,15 +335,19 @@ fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::CrateNum) let purity = if fam == UnsafeStaticMethod { ast::unsafe_fn } else { ast::impure_fn }; // def_static_method carries an optional field of its enclosing - // *trait*, but not an inclosing Impl (if this is an inherent - // static method). So we need to detect whether this is in - // a trait or not, which we do through the mildly hacky - // way of checking whether there is a trait_method_sort. - let trait_did_opt = if reader::maybe_get_doc( + // trait or enclosing impl (if this is an inherent static method). + // So we need to detect whether this is in a trait or not, which + // we do through the mildly hacky way of checking whether there is + // a trait_method_sort. + let provenance = if reader::maybe_get_doc( item, tag_item_trait_method_sort).is_some() { - Some(item_reqd_and_translated_parent_item(cnum, item)) - } else { None }; - dl_def(ast::def_static_method(did, trait_did_opt, purity)) + ast::FromTrait(item_reqd_and_translated_parent_item(cnum, + item)) + } else { + ast::FromImpl(item_reqd_and_translated_parent_item(cnum, + item)) + }; + dl_def(ast::def_static_method(did, provenance, purity)) } Type | ForeignType => dl_def(ast::def_ty(did)), Mod => dl_def(ast::def_mod(did)), @@ -792,12 +796,9 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::NodeId, fn get_explicit_self(item: ebml::Doc) -> ast::explicit_self_ { fn get_mutability(ch: u8) -> ast::mutability { match ch as char { - 'i' => { ast::m_imm } - 'm' => { ast::m_mutbl } - 'c' => { ast::m_const } - _ => { - fail!("unknown mutability character: `%c`", ch as char) - } + 'i' => ast::m_imm, + 'm' => ast::m_mutbl, + _ => fail!("unknown mutability character: `%c`", ch as char), } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 4a3704dc3aa4e..915eaad87f593 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -645,15 +645,8 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explic fn encode_mutability(ebml_w: &writer::Encoder, m: ast::mutability) { match m { - m_imm => { - ebml_w.writer.write(&[ 'i' as u8 ]); - } - m_mutbl => { - ebml_w.writer.write(&[ 'm' as u8 ]); - } - m_const => { - ebml_w.writer.write(&[ 'c' as u8 ]); - } + m_imm => ebml_w.writer.write(&[ 'i' as u8 ]), + m_mutbl => ebml_w.writer.write(&[ 'm' as u8 ]), } } } @@ -1005,7 +998,8 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(ecx, ebml_w, item.ident); encode_attributes(ebml_w, item.attrs); match ty.node { - ast::ty_path(ref path, ref bounds, _) if path.idents.len() == 1 => { + ast::ty_path(ref path, ref bounds, _) if path.segments + .len() == 1 => { assert!(bounds.is_none()); encode_impl_type_basename(ecx, ebml_w, ast_util::path_to_ident(path)); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 89b30e46ac06d..f5bad88b1ca66 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -138,12 +138,20 @@ fn parse_path(st: &mut PState) -> @ast::Path { ':' => { next(st); next(st); } c => { if c == '(' { - return @ast::Path { span: dummy_sp(), - global: false, - idents: idents, - rp: None, - types: ~[] }; - } else { idents.push(parse_ident_(st, is_last)); } + return @ast::Path { + span: dummy_sp(), + global: false, + segments: idents.move_iter().map(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; + } else { + idents.push(parse_ident_(st, is_last)); + } } } }; @@ -417,7 +425,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { fn parse_mutability(st: &mut PState) -> ast::mutability { match peek(st) { 'm' => { next(st); ast::m_mutbl } - '?' => { next(st); ast::m_const } _ => { ast::m_imm } } } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 915729d254f94..82b79f864848d 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -100,7 +100,6 @@ fn enc_mutability(w: @io::Writer, mt: ast::mutability) { match mt { m_imm => (), m_mutbl => w.write_char('m'), - m_const => w.write_char('?') } } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index d6342c582f052..7cf4d05f095bc 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -374,9 +374,16 @@ impl tr for ast::def { fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::def { match *self { ast::def_fn(did, p) => ast::def_fn(did.tr(xcx), p), - ast::def_static_method(did, did2_opt, p) => { + ast::def_static_method(did, wrapped_did2, p) => { ast::def_static_method(did.tr(xcx), - did2_opt.map(|did2| did2.tr(xcx)), + match wrapped_did2 { + ast::FromTrait(did2) => { + ast::FromTrait(did2.tr(xcx)) + } + ast::FromImpl(did2) => { + ast::FromImpl(did2.tr(xcx)) + } + }, p) } ast::def_method(did0, did1) => { diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 620a1e9efe33f..ca49354f1d89d 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -23,11 +23,12 @@ use mc = middle::mem_categorization; use middle::borrowck::*; use middle::moves; use middle::ty; -use syntax::ast::{m_mutbl, m_imm, m_const}; +use syntax::ast::m_mutbl; use syntax::ast; use syntax::ast_util; use syntax::codemap::span; -use syntax::oldvisit; +use syntax::visit::Visitor; +use syntax::visit; use util::ppaux::Repr; #[deriving(Clone)] @@ -39,6 +40,93 @@ struct CheckLoanCtxt<'self> { reported: @mut HashSet, } +impl<'self> Visitor<()> for CheckLoanCtxt<'self> { + fn visit_expr(&mut self, expr: @ast::expr, _: ()) { + visit::walk_expr(self, expr, ()); + + debug!("check_loans_in_expr(expr=%s)", expr.repr(self.tcx())); + + self.check_for_conflicting_loans(expr.id); + self.check_move_out_from_expr(expr); + + match expr.node { + ast::expr_self | + ast::expr_path(*) => { + if !self.move_data.is_assignee(expr.id) { + let cmt = self.bccx.cat_expr_unadjusted(expr); + debug!("path cmt=%s", cmt.repr(self.tcx())); + let r = opt_loan_path(cmt); + for &lp in r.iter() { + self.check_if_path_is_moved(expr.id, expr.span, MovedInUse, lp); + } + } + } + ast::expr_assign(dest, _) | + ast::expr_assign_op(_, _, dest, _) => { + self.check_assignment(dest); + } + ast::expr_call(f, ref args, _) => { + self.check_call(expr, Some(f), f.id, f.span, *args); + } + ast::expr_method_call(callee_id, _, _, _, ref args, _) => { + self.check_call(expr, None, callee_id, expr.span, *args); + } + ast::expr_index(callee_id, _, rval) | + ast::expr_binary(callee_id, _, _, rval) + if self.bccx.method_map.contains_key(&expr.id) => { + self.check_call(expr, + None, + callee_id, + expr.span, + [rval]); + } + ast::expr_unary(callee_id, _, _) | ast::expr_index(callee_id, _, _) + if self.bccx.method_map.contains_key(&expr.id) => { + self.check_call(expr, + None, + callee_id, + expr.span, + []); + } + _ => { } + } + } + + fn visit_pat(&mut self, pat: @ast::pat, _: ()) { + self.check_for_conflicting_loans(pat.id); + self.check_move_out_from_id(pat.id, pat.span); + visit::walk_pat(self, pat, ()); + } + + fn visit_fn(&mut self, + fk: &visit::fn_kind, + decl: &ast::fn_decl, + body: &ast::Block, + sp: span, + id: ast::NodeId, + _: ()) { + match *fk { + visit::fk_item_fn(*) | + visit::fk_method(*) => { + // Don't process nested items. + return; + } + + visit::fk_anon(*) | + visit::fk_fn_block(*) => { + self.check_captured_variables(id, sp); + } + } + + visit::walk_fn(self, fk, decl, body, sp, id, ()); + } + + fn visit_block(&mut self, blk: &ast::Block, _: ()) { + visit::walk_block(self, blk, ()); + self.check_for_conflicting_loans(blk.id); + } +} + pub fn check_loans(bccx: @BorrowckCtxt, dfcx_loans: &LoanDataFlow, move_data: move_data::FlowedMoveData, @@ -46,23 +134,14 @@ pub fn check_loans(bccx: @BorrowckCtxt, body: &ast::Block) { debug!("check_loans(body id=%?)", body.id); - let clcx = CheckLoanCtxt { + let mut clcx = CheckLoanCtxt { bccx: bccx, dfcx_loans: dfcx_loans, move_data: @move_data, all_loans: all_loans, reported: @mut HashSet::new(), }; - - let vt = oldvisit::mk_vt(@oldvisit::Visitor { - visit_expr: check_loans_in_expr, - visit_local: check_loans_in_local, - visit_block: check_loans_in_block, - visit_pat: check_loans_in_pat, - visit_fn: check_loans_in_fn, - .. *oldvisit::default_visitor() - }); - (vt.visit_block)(body, (clcx, vt)); + clcx.visit_block(body, ()); } enum MoveError { @@ -71,6 +150,44 @@ enum MoveError { } impl<'self> CheckLoanCtxt<'self> { + fn check_by_move_capture(&self, + closure_id: ast::NodeId, + cap_var: &moves::CaptureVar, + move_path: @LoanPath) { + let move_err = self.analyze_move_out_from(closure_id, move_path); + match move_err { + MoveOk => {} + MoveWhileBorrowed(loan_path, loan_span) => { + self.bccx.span_err( + cap_var.span, + fmt!("cannot move `%s` into closure \ + because it is borrowed", + self.bccx.loan_path_to_str(move_path))); + self.bccx.span_note( + loan_span, + fmt!("borrow of `%s` occurs here", + self.bccx.loan_path_to_str(loan_path))); + } + } + } + + fn check_captured_variables(&self, closure_id: ast::NodeId, span: span) { + let cap_vars = self.bccx.capture_map.get(&closure_id); + for cap_var in cap_vars.iter() { + let var_id = ast_util::def_id_of_def(cap_var.def).node; + let var_path = @LpVar(var_id); + self.check_if_path_is_moved(closure_id, span, + MovedInCapture, var_path); + match cap_var.mode { + moves::CapRef | moves::CapCopy => {} + moves::CapMove => { + self.check_by_move_capture(closure_id, cap_var, var_path); + } + } + } + return; + } + pub fn tcx(&self) -> ty::ctxt { self.bccx.tcx } pub fn each_issued_loan(&self, @@ -205,9 +322,9 @@ impl<'self> CheckLoanCtxt<'self> { // Restrictions that would cause the new loan to be illegal: let illegal_if = match loan2.mutbl { - m_mutbl => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, - m_imm => RESTR_ALIAS | RESTR_FREEZE, - m_const => RESTR_ALIAS, + MutableMutability => RESTR_ALIAS | RESTR_FREEZE | RESTR_CLAIM, + ImmutableMutability => RESTR_ALIAS | RESTR_FREEZE, + ConstMutability => RESTR_ALIAS, }; debug!("illegal_if=%?", illegal_if); @@ -216,7 +333,7 @@ impl<'self> CheckLoanCtxt<'self> { if restr.loan_path != loan2.loan_path { loop; } match (new_loan.mutbl, old_loan.mutbl) { - (m_mutbl, m_mutbl) => { + (MutableMutability, MutableMutability) => { self.bccx.span_err( new_loan.span, fmt!("cannot borrow `%s` as mutable \ @@ -522,7 +639,6 @@ impl<'self> CheckLoanCtxt<'self> { // Otherwise stop iterating LpExtend(_, mc::McDeclared, _) | LpExtend(_, mc::McImmutable, _) | - LpExtend(_, mc::McReadOnly, _) | LpVar(_) => { return true; } @@ -530,8 +646,11 @@ impl<'self> CheckLoanCtxt<'self> { // Check for a non-const loan of `loan_path` let cont = do this.each_in_scope_loan(expr.id) |loan| { - if loan.loan_path == loan_path && loan.mutbl != m_const { - this.report_illegal_mutation(expr, full_loan_path, loan); + if loan.loan_path == loan_path && + loan.mutbl != ConstMutability { + this.report_illegal_mutation(expr, + full_loan_path, + loan); false } else { true @@ -626,142 +745,3 @@ impl<'self> CheckLoanCtxt<'self> { } } -fn check_loans_in_fn<'a>(fk: &oldvisit::fn_kind, - decl: &ast::fn_decl, - body: &ast::Block, - sp: span, - id: ast::NodeId, - (this, visitor): (CheckLoanCtxt<'a>, - oldvisit::vt>)) { - match *fk { - oldvisit::fk_item_fn(*) | - oldvisit::fk_method(*) => { - // Don't process nested items. - return; - } - - oldvisit::fk_anon(*) | - oldvisit::fk_fn_block(*) => { - check_captured_variables(this, id, sp); - } - } - - oldvisit::visit_fn(fk, decl, body, sp, id, (this, visitor)); - - fn check_captured_variables(this: CheckLoanCtxt, - closure_id: ast::NodeId, - span: span) { - let cap_vars = this.bccx.capture_map.get(&closure_id); - for cap_var in cap_vars.iter() { - let var_id = ast_util::def_id_of_def(cap_var.def).node; - let var_path = @LpVar(var_id); - this.check_if_path_is_moved(closure_id, span, - MovedInCapture, var_path); - match cap_var.mode { - moves::CapRef | moves::CapCopy => {} - moves::CapMove => { - check_by_move_capture(this, closure_id, cap_var, var_path); - } - } - } - return; - - fn check_by_move_capture(this: CheckLoanCtxt, - closure_id: ast::NodeId, - cap_var: &moves::CaptureVar, - move_path: @LoanPath) { - let move_err = this.analyze_move_out_from(closure_id, move_path); - match move_err { - MoveOk => {} - MoveWhileBorrowed(loan_path, loan_span) => { - this.bccx.span_err( - cap_var.span, - fmt!("cannot move `%s` into closure \ - because it is borrowed", - this.bccx.loan_path_to_str(move_path))); - this.bccx.span_note( - loan_span, - fmt!("borrow of `%s` occurs here", - this.bccx.loan_path_to_str(loan_path))); - } - } - } - } -} - -fn check_loans_in_local<'a>(local: @ast::Local, - (this, vt): (CheckLoanCtxt<'a>, - oldvisit::vt>)) { - oldvisit::visit_local(local, (this, vt)); -} - -fn check_loans_in_expr<'a>(expr: @ast::expr, - (this, vt): (CheckLoanCtxt<'a>, - oldvisit::vt>)) { - oldvisit::visit_expr(expr, (this, vt)); - - debug!("check_loans_in_expr(expr=%s)", - expr.repr(this.tcx())); - - this.check_for_conflicting_loans(expr.id); - this.check_move_out_from_expr(expr); - - match expr.node { - ast::expr_self | - ast::expr_path(*) => { - if !this.move_data.is_assignee(expr.id) { - let cmt = this.bccx.cat_expr_unadjusted(expr); - debug!("path cmt=%s", cmt.repr(this.tcx())); - let r = opt_loan_path(cmt); - for &lp in r.iter() { - this.check_if_path_is_moved(expr.id, expr.span, MovedInUse, lp); - } - } - } - ast::expr_assign(dest, _) | - ast::expr_assign_op(_, _, dest, _) => { - this.check_assignment(dest); - } - ast::expr_call(f, ref args, _) => { - this.check_call(expr, Some(f), f.id, f.span, *args); - } - ast::expr_method_call(callee_id, _, _, _, ref args, _) => { - this.check_call(expr, None, callee_id, expr.span, *args); - } - ast::expr_index(callee_id, _, rval) | - ast::expr_binary(callee_id, _, _, rval) - if this.bccx.method_map.contains_key(&expr.id) => { - this.check_call(expr, - None, - callee_id, - expr.span, - [rval]); - } - ast::expr_unary(callee_id, _, _) | ast::expr_index(callee_id, _, _) - if this.bccx.method_map.contains_key(&expr.id) => { - this.check_call(expr, - None, - callee_id, - expr.span, - []); - } - _ => { } - } -} - -fn check_loans_in_pat<'a>(pat: @ast::pat, - (this, vt): (CheckLoanCtxt<'a>, - oldvisit::vt>)) -{ - this.check_for_conflicting_loans(pat.id); - this.check_move_out_from_id(pat.id, pat.span); - oldvisit::visit_pat(pat, (this, vt)); -} - -fn check_loans_in_block<'a>(blk: &ast::Block, - (this, vt): (CheckLoanCtxt<'a>, - oldvisit::vt>)) -{ - oldvisit::visit_block(blk, (this, vt)); - this.check_for_conflicting_loans(blk.id); -} diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index b315a7a2e7290..5bb7e63485e63 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -15,7 +15,7 @@ use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; -use syntax::ast::{m_const, m_imm, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::ast; use syntax::codemap::span; use util::ppaux::{note_and_explain_region}; @@ -26,7 +26,7 @@ pub fn guarantee_lifetime(bccx: @BorrowckCtxt, span: span, cmt: mc::cmt, loan_region: ty::Region, - loan_mutbl: ast::mutability) { + loan_mutbl: LoanMutability) { debug!("guarantee_lifetime(cmt=%s, loan_region=%s)", cmt.repr(bccx.tcx), loan_region.repr(bccx.tcx)); let ctxt = GuaranteeLifetimeContext {bccx: bccx, @@ -54,7 +54,7 @@ struct GuaranteeLifetimeContext { span: span, loan_region: ty::Region, - loan_mutbl: ast::mutability, + loan_mutbl: LoanMutability, cmt_original: mc::cmt } @@ -236,11 +236,11 @@ impl GuaranteeLifetimeContext { // we need to dynamically mark it to prevent incompatible // borrows from happening later. let opt_dyna = match ptr_mutbl { - m_imm | m_const => None, + m_imm => None, m_mutbl => { match self.loan_mutbl { - m_mutbl => Some(DynaMut), - m_imm | m_const => Some(DynaImm) + MutableMutability => Some(DynaMut), + ImmutableMutability | ConstMutability => Some(DynaImm) } } }; diff --git a/src/librustc/middle/borrowck/gather_loans/mod.rs b/src/librustc/middle/borrowck/gather_loans/mod.rs index 6d2a4fcc9f31a..dbe5214e0eb50 100644 --- a/src/librustc/middle/borrowck/gather_loans/mod.rs +++ b/src/librustc/middle/borrowck/gather_loans/mod.rs @@ -26,7 +26,6 @@ use middle::ty; use util::common::indenter; use util::ppaux::{Repr}; -use syntax::ast::{m_const, m_imm, m_mutbl}; use syntax::ast; use syntax::ast_util::id_range; use syntax::codemap::span; @@ -237,7 +236,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor, // make sure that the thing we are pointing out stays valid // for the lifetime `scope_r` of the resulting ptr: let scope_r = ty_region(tcx, ex.span, ty::expr_ty(tcx, ex)); - this.guarantee_valid(ex.id, ex.span, base_cmt, mutbl, scope_r); + this.guarantee_valid(ex.id, + ex.span, + base_cmt, + LoanMutability::from_ast_mutability(mutbl), + scope_r); visit::walk_expr(v, ex, this); } @@ -278,7 +281,11 @@ fn gather_loans_in_expr(v: &mut GatherLoanVisitor, // adjustments). let scope_r = ty::re_scope(ex.id); let arg_cmt = this.bccx.cat_expr(arg); - this.guarantee_valid(arg.id, arg.span, arg_cmt, m_imm, scope_r); + this.guarantee_valid(arg.id, + arg.span, + arg_cmt, + ImmutableMutability, + scope_r); visit::walk_expr(v, ex, this); } @@ -357,18 +364,22 @@ impl GatherLoanCtxt { match *autoref { ty::AutoPtr(r, m) => { + let loan_mutability = + LoanMutability::from_ast_mutability(m); self.guarantee_valid(expr.id, expr.span, cmt, - m, + loan_mutability, r) } ty::AutoBorrowVec(r, m) | ty::AutoBorrowVecRef(r, m) => { let cmt_index = mcx.cat_index(expr, cmt, autoderefs+1); + let loan_mutability = + LoanMutability::from_ast_mutability(m); self.guarantee_valid(expr.id, expr.span, cmt_index, - m, + loan_mutability, r) } ty::AutoBorrowFn(r) => { @@ -376,15 +387,17 @@ impl GatherLoanCtxt { self.guarantee_valid(expr.id, expr.span, cmt_deref, - m_imm, + ImmutableMutability, r) } ty::AutoBorrowObj(r, m) => { let cmt_deref = mcx.cat_deref_fn_or_obj(expr, cmt, 0); + let loan_mutability = + LoanMutability::from_ast_mutability(m); self.guarantee_valid(expr.id, expr.span, cmt_deref, - m, + loan_mutability, r) } ty::AutoUnsafe(_) => {} @@ -402,7 +415,7 @@ impl GatherLoanCtxt { borrow_id: ast::NodeId, borrow_span: span, cmt: mc::cmt, - req_mutbl: ast::mutability, + req_mutbl: LoanMutability, loan_region: ty::Region) { debug!("guarantee_valid(borrow_id=%?, cmt=%s, \ req_mutbl=%?, loan_region=%?)", @@ -473,7 +486,7 @@ impl GatherLoanCtxt { let kill_scope = self.compute_kill_scope(loan_scope, loan_path); debug!("kill_scope = %?", kill_scope); - if req_mutbl == m_mutbl { + if req_mutbl == MutableMutability { self.mark_loan_path_as_mutated(loan_path); } @@ -516,7 +529,7 @@ impl GatherLoanCtxt { // index: all_loans.len(), // loan_path: loan_path, // cmt: cmt, - // mutbl: m_const, + // mutbl: ConstMutability, // gen_scope: borrow_id, // kill_scope: kill_scope, // span: borrow_span, @@ -527,29 +540,20 @@ impl GatherLoanCtxt { fn check_mutability(bccx: @BorrowckCtxt, borrow_span: span, cmt: mc::cmt, - req_mutbl: ast::mutability) { + req_mutbl: LoanMutability) { //! Implements the M-* rules in doc.rs. match req_mutbl { - m_const => { + ConstMutability => { // Data of any mutability can be lent as const. } - m_imm => { - match cmt.mutbl { - mc::McImmutable | mc::McDeclared | mc::McInherited => { - // both imm and mut data can be lent as imm; - // for mutable data, this is a freeze - } - mc::McReadOnly => { - bccx.report(BckError {span: borrow_span, - cmt: cmt, - code: err_mutbl(req_mutbl)}); - } - } + ImmutableMutability => { + // both imm and mut data can be lent as imm; + // for mutable data, this is a freeze } - m_mutbl => { + MutableMutability => { // Only mutable data can be lent as mutable. if !cmt.mutbl.is_mutable() { bccx.report(BckError {span: borrow_span, @@ -561,12 +565,14 @@ impl GatherLoanCtxt { } } - pub fn restriction_set(&self, req_mutbl: ast::mutability) + pub fn restriction_set(&self, req_mutbl: LoanMutability) -> RestrictionSet { match req_mutbl { - m_const => RESTR_EMPTY, - m_imm => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, - m_mutbl => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE + ConstMutability => RESTR_EMPTY, + ImmutableMutability => RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM, + MutableMutability => { + RESTR_EMPTY | RESTR_MUTATE | RESTR_CLAIM | RESTR_FREEZE + } } } @@ -582,8 +588,8 @@ impl GatherLoanCtxt { self.mark_loan_path_as_mutated(base); } LpExtend(_, mc::McDeclared, _) | - LpExtend(_, mc::McImmutable, _) | - LpExtend(_, mc::McReadOnly, _) => { + LpExtend(_, mc::McImmutable, _) => { + // Nothing to do. } } } @@ -701,8 +707,13 @@ impl GatherLoanCtxt { } } }; - self.guarantee_valid(pat.id, pat.span, - cmt_discr, mutbl, scope_r); + let loan_mutability = + LoanMutability::from_ast_mutability(mutbl); + self.guarantee_valid(pat.id, + pat.span, + cmt_discr, + loan_mutability, + scope_r); } ast::bind_infer => { // No borrows here, but there may be moves @@ -725,6 +736,8 @@ impl GatherLoanCtxt { self.vec_slice_info(slice_pat, slice_ty); let mcx = self.bccx.mc_ctxt(); let cmt_index = mcx.cat_index(slice_pat, cmt, 0); + let slice_loan_mutability = + LoanMutability::from_ast_mutability(slice_mutbl); // Note: We declare here that the borrow occurs upon // entering the `[...]` pattern. This implies that @@ -743,8 +756,11 @@ impl GatherLoanCtxt { // trans do the right thing, and it would only work // for `~` vectors. It seems simpler to just require // that people call `vec.pop()` or `vec.unshift()`. - self.guarantee_valid(pat.id, pat.span, - cmt_index, slice_mutbl, slice_r); + self.guarantee_valid(pat.id, + pat.span, + cmt_index, + slice_loan_mutability, + slice_r); } _ => {} diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 46bb23e400ee5..cdd6ed71114a3 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -15,7 +15,7 @@ use std::vec; use middle::borrowck::*; use mc = middle::mem_categorization; use middle::ty; -use syntax::ast::{m_const, m_imm, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::codemap::span; pub enum RestrictionResult { @@ -122,13 +122,6 @@ impl RestrictionsContext { Safe } - mc::cat_deref(_, _, mc::region_ptr(m_const, _)) | - mc::cat_deref(_, _, mc::gc_ptr(m_const)) => { - // R-Deref-Freeze-Borrowed - self.check_no_mutability_control(cmt, restrictions); - Safe - } - mc::cat_deref(cmt_base, _, mc::gc_ptr(m_mutbl)) => { // R-Deref-Managed-Borrowed // diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 95eae32922b7f..7414cefe8bd13 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -241,12 +241,39 @@ pub enum PartialTotal { /////////////////////////////////////////////////////////////////////////// // Loans and loan paths +#[deriving(Clone, Eq)] +pub enum LoanMutability { + ImmutableMutability, + ConstMutability, + MutableMutability, +} + +impl LoanMutability { + pub fn from_ast_mutability(ast_mutability: ast::mutability) + -> LoanMutability { + match ast_mutability { + ast::m_imm => ImmutableMutability, + ast::m_mutbl => MutableMutability, + } + } +} + +impl ToStr for LoanMutability { + fn to_str(&self) -> ~str { + match *self { + ImmutableMutability => ~"immutable", + ConstMutability => ~"read-only", + MutableMutability => ~"mutable", + } + } +} + /// Record of a loan that was issued. pub struct Loan { index: uint, loan_path: @LoanPath, cmt: mc::cmt, - mutbl: ast::mutability, + mutbl: LoanMutability, restrictions: ~[Restriction], gen_scope: ast::NodeId, kill_scope: ast::NodeId, @@ -418,7 +445,7 @@ impl ToStr for DynaFreezeKind { // Errors that can occur #[deriving(Eq)] pub enum bckerr_code { - err_mutbl(ast::mutability), + err_mutbl(LoanMutability), err_out_of_root_scope(ty::Region, ty::Region), // superscope, subscope err_out_of_scope(ty::Region, ty::Region), // superscope, subscope err_freeze_aliasable_const @@ -795,17 +822,14 @@ impl BorrowckCtxt { mc.cmt_to_str(cmt) } - pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { - let mc = &mc::mem_categorization_ctxt {tcx: self.tcx, - method_map: self.method_map}; - mc.mut_to_str(mutbl) + pub fn mut_to_str(&self, mutbl: LoanMutability) -> ~str { + mutbl.to_str() } pub fn mut_to_keyword(&self, mutbl: ast::mutability) -> &'static str { match mutbl { ast::m_imm => "", - ast::m_const => "const", - ast::m_mutbl => "mut" + ast::m_mutbl => "mut", } } } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index 160cc23bd19ff..6694b0b21244f 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -16,185 +16,206 @@ use middle::typeck; use util::ppaux; use syntax::ast::*; +use syntax::ast_map; +use syntax::ast_util; use syntax::codemap; -use syntax::{oldvisit, ast_util, ast_map}; +use syntax::visit::Visitor; +use syntax::visit; -pub fn check_crate(sess: Session, - crate: &Crate, - ast_map: ast_map::map, - def_map: resolve::DefMap, - method_map: typeck::method_map, - tcx: ty::ctxt) { - oldvisit::visit_crate(crate, (false, oldvisit::mk_vt(@oldvisit::Visitor { - visit_item: |a,b| check_item(sess, ast_map, def_map, a, b), - visit_pat: check_pat, - visit_expr: |a,b| - check_expr(sess, def_map, method_map, tcx, a, b), - .. *oldvisit::default_visitor() - }))); - sess.abort_if_errors(); +struct ConstCheckingVisitor { + sess: Session, + ast_map: ast_map::map, + def_map: resolve::DefMap, + method_map: typeck::method_map, + tcx: ty::ctxt, } -pub fn check_item(sess: Session, - ast_map: ast_map::map, - def_map: resolve::DefMap, - it: @item, - (_is_const, v): (bool, - oldvisit::vt)) { - match it.node { - item_static(_, _, ex) => { - (v.visit_expr)(ex, (true, v)); - check_item_recursion(sess, ast_map, def_map, it); - } - item_enum(ref enum_definition, _) => { - for var in (*enum_definition).variants.iter() { - for ex in var.node.disr_expr.iter() { - (v.visit_expr)(*ex, (true, v)); +impl Visitor for ConstCheckingVisitor { + fn visit_item(&mut self, it: @item, _: bool) { + match it.node { + item_static(_, _, ex) => { + self.visit_expr(ex, true); + check_item_recursion(self.sess, self.ast_map, self.def_map, it); + } + item_enum(ref enum_definition, _) => { + for var in (*enum_definition).variants.iter() { + for ex in var.node.disr_expr.iter() { + self.visit_expr(*ex, true); + } } + } + _ => visit::walk_item(self, it, false) } - } - _ => oldvisit::visit_item(it, (false, v)) } -} -pub fn check_pat(p: @pat, (_is_const, v): (bool, oldvisit::vt)) { - fn is_str(e: @expr) -> bool { - match e.node { - expr_vstore( - @expr { node: expr_lit(@codemap::spanned { - node: lit_str(_), - _}), - _ }, - expr_vstore_uniq - ) => true, - _ => false + fn visit_pat(&mut self, p: @pat, _: bool) { + fn is_str(e: @expr) -> bool { + match e.node { + expr_vstore( + @expr { node: expr_lit(@codemap::spanned { + node: lit_str(_), + _}), + _ }, + expr_vstore_uniq + ) => true, + _ => false + } } - } - match p.node { - // Let through plain ~-string literals here - pat_lit(a) => if !is_str(a) { (v.visit_expr)(a, (true, v)); }, - pat_range(a, b) => { - if !is_str(a) { (v.visit_expr)(a, (true, v)); } - if !is_str(b) { (v.visit_expr)(b, (true, v)); } - } - _ => oldvisit::visit_pat(p, (false, v)) - } -} - -pub fn check_expr(sess: Session, - def_map: resolve::DefMap, - method_map: typeck::method_map, - tcx: ty::ctxt, - e: @expr, - (is_const, v): (bool, - oldvisit::vt)) { - if is_const { - match e.node { - expr_unary(_, deref, _) => { } - expr_unary(_, box(_), _) | expr_unary(_, uniq, _) => { - sess.span_err(e.span, - "disallowed operator in constant expression"); - return; - } - expr_lit(@codemap::spanned {node: lit_str(_), _}) => { } - expr_binary(*) | expr_unary(*) => { - if method_map.contains_key(&e.id) { - sess.span_err(e.span, "user-defined operators are not \ - allowed in constant expressions"); + match p.node { + // Let through plain ~-string literals here + pat_lit(a) => { + if !is_str(a) { + self.visit_expr(a, true); } } - expr_lit(_) => (), - expr_cast(_, _) => { - let ety = ty::expr_ty(tcx, e); - if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { - sess.span_err(e.span, ~"can not cast to `" + - ppaux::ty_to_str(tcx, ety) + - "` in a constant expression"); - } + pat_range(a, b) => { + if !is_str(a) { self.visit_expr(a, true); } + if !is_str(b) { self.visit_expr(b, true); } } - expr_path(ref pth) => { - // NB: In the future you might wish to relax this slightly - // to handle on-demand instantiation of functions via - // foo:: in a const. Currently that is only done on - // a path in trans::callee that only works in block contexts. - if pth.types.len() != 0 { - sess.span_err( - e.span, "paths in constants may only refer to \ - items without type parameters"); - } - match def_map.find(&e.id) { - Some(&def_static(*)) | - Some(&def_fn(_, _)) | - Some(&def_variant(_, _)) | - Some(&def_struct(_)) => { } - - Some(&def) => { - debug!("(checking const) found bad def: %?", def); - sess.span_err( - e.span, - "paths in constants may only refer to \ - constants or functions"); + _ => visit::walk_pat(self, p, false) + } + } + + fn visit_expr(&mut self, e: @expr, is_const: bool) { + if is_const { + match e.node { + expr_unary(_, deref, _) => { } + expr_unary(_, box(_), _) | expr_unary(_, uniq, _) => { + self.sess.span_err(e.span, + "disallowed operator in constant \ + expression"); + return; } - None => { - sess.span_bug(e.span, "unbound path in const?!"); + expr_lit(@codemap::spanned {node: lit_str(_), _}) => { } + expr_binary(*) | expr_unary(*) => { + if self.method_map.contains_key(&e.id) { + self.sess.span_err(e.span, + "user-defined operators are not \ + allowed in constant expressions"); + } } - } - } - expr_call(callee, _, NoSugar) => { - match def_map.find(&callee.id) { - Some(&def_struct(*)) => {} // OK. - Some(&def_variant(*)) => {} // OK. - _ => { - sess.span_err( + expr_lit(_) => (), + expr_cast(_, _) => { + let ety = ty::expr_ty(self.tcx, e); + if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) { + self.sess.span_err(e.span, + ~"can not cast to `" + + ppaux::ty_to_str(self.tcx, ety) + + "` in a constant expression"); + } + } + expr_path(ref pth) => { + // NB: In the future you might wish to relax this slightly + // to handle on-demand instantiation of functions via + // foo:: in a const. Currently that is only done on + // a path in trans::callee that only works in block contexts. + if !pth.segments.iter().all(|s| s.types.is_empty()) { + self.sess.span_err( + e.span, "paths in constants may only refer to \ + items without type parameters"); + } + match self.def_map.find(&e.id) { + Some(&def_static(*)) | + Some(&def_fn(_, _)) | + Some(&def_variant(_, _)) | + Some(&def_struct(_)) => { } + + Some(&def) => { + debug!("(checking const) found bad def: %?", def); + self.sess.span_err( e.span, - "function calls in constants are limited to \ - struct and enum constructors"); + "paths in constants may only refer to \ + constants or functions"); + } + None => { + self.sess.span_bug(e.span, "unbound path in const?!"); + } } + } + expr_call(callee, _, NoSugar) => { + match self.def_map.find(&callee.id) { + Some(&def_struct(*)) => {} // OK. + Some(&def_variant(*)) => {} // OK. + _ => { + self.sess.span_err( + e.span, + "function calls in constants are limited to \ + struct and enum constructors"); + } + } + } + expr_paren(e) => self.visit_expr(e, is_const), + expr_vstore(_, expr_vstore_slice) | + expr_vec(_, m_imm) | + expr_addr_of(m_imm, _) | + expr_field(*) | + expr_index(*) | + expr_tup(*) | + expr_repeat(*) | + expr_struct(*) => { } + expr_addr_of(*) => { + self.sess.span_err( + e.span, + "borrowed pointers in constants may only refer to \ + immutable values"); + } + _ => { + self.sess.span_err(e.span, + "constant contains unimplemented \ + expression type"); + return; + } } - } - expr_paren(e) => { check_expr(sess, def_map, method_map, - tcx, e, (is_const, v)); } - expr_vstore(_, expr_vstore_slice) | - expr_vec(_, m_imm) | - expr_addr_of(m_imm, _) | - expr_field(*) | - expr_index(*) | - expr_tup(*) | - expr_repeat(*) | - expr_struct(*) => { } - expr_addr_of(*) => { - sess.span_err( - e.span, - "borrowed pointers in constants may only refer to \ - immutable values"); - } - _ => { - sess.span_err(e.span, - "constant contains unimplemented expression type"); - return; - } } - } - match e.node { - expr_lit(@codemap::spanned {node: lit_int(v, t), _}) => { - if t != ty_char { - if (v as u64) > ast_util::int_ty_max( - if t == ty_i { sess.targ_cfg.int_type } else { t }) { - sess.span_err(e.span, "literal out of range for its type"); + match e.node { + expr_lit(@codemap::spanned {node: lit_int(v, t), _}) => { + if t != ty_char { + if (v as u64) > ast_util::int_ty_max( + if t == ty_i { + self.sess.targ_cfg.int_type + } else { + t + }) { + self.sess.span_err(e.span, + "literal out of range for its type"); + } } + } + expr_lit(@codemap::spanned {node: lit_uint(v, t), _}) => { + if v > ast_util::uint_ty_max(if t == ty_u { + self.sess.targ_cfg.uint_type + } else { + t + }) { + self.sess.span_err(e.span, + "literal out of range for its type"); + } + } + _ => () } - } - expr_lit(@codemap::spanned {node: lit_uint(v, t), _}) => { - if v > ast_util::uint_ty_max( - if t == ty_u { sess.targ_cfg.uint_type } else { t }) { - sess.span_err(e.span, "literal out of range for its type"); - } - } - _ => () + visit::walk_expr(self, e, is_const); } - oldvisit::visit_expr(e, (is_const, v)); + } +pub fn check_crate(sess: Session, + crate: &Crate, + ast_map: ast_map::map, + def_map: resolve::DefMap, + method_map: typeck::method_map, + tcx: ty::ctxt) { + let mut visitor = ConstCheckingVisitor { + sess: sess, + ast_map: ast_map, + def_map: def_map, + method_map: method_map, + tcx: tcx, + }; + visit::walk_crate(&mut visitor, crate, false); + sess.abort_if_errors(); +} + + #[deriving(Clone)] struct env { root_it: @item, @@ -206,41 +227,29 @@ struct env { // Make sure a const item doesn't recursively refer to itself // FIXME: Should use the dependency graph when it's available (#1356) -pub fn check_item_recursion(sess: Session, - ast_map: ast_map::map, - def_map: resolve::DefMap, - it: @item) { - let env = env { - root_it: it, - sess: sess, - ast_map: ast_map, - def_map: def_map, - idstack: @mut ~[] - }; - - let visitor = oldvisit::mk_vt(@oldvisit::Visitor { - visit_item: visit_item, - visit_expr: visit_expr, - .. *oldvisit::default_visitor() - }); - (visitor.visit_item)(it, (env, visitor)); +struct ItemRecursionCheckingVisitor { + sess: Session, + ast_map: ast_map::map, + def_map: resolve::DefMap, +} - fn visit_item(it: @item, (env, v): (env, oldvisit::vt)) { +impl Visitor for ItemRecursionCheckingVisitor { + fn visit_item(&mut self, it: @item, env: env) { if env.idstack.iter().any(|x| x == &(it.id)) { env.sess.span_fatal(env.root_it.span, "recursive constant"); } env.idstack.push(it.id); - oldvisit::visit_item(it, (env, v)); + visit::walk_item(self, it, env); env.idstack.pop(); } - fn visit_expr(e: @expr, (env, v): (env, oldvisit::vt)) { + fn visit_expr(&mut self, e: @expr, env: env) { match e.node { expr_path(*) => match env.def_map.find(&e.id) { Some(&def_static(def_id, _)) if ast_util::is_local(def_id) => match env.ast_map.get_copy(&def_id.node) { ast_map::node_item(it, _) => { - (v.visit_item)(it, (env, v)); + self.visit_item(it, env); } _ => fail!("const not bound to an item") }, @@ -248,6 +257,26 @@ pub fn check_item_recursion(sess: Session, }, _ => () } - oldvisit::visit_expr(e, (env, v)); + visit::walk_expr(self, e, env); } } + +fn check_item_recursion(sess: Session, + ast_map: ast_map::map, + def_map: resolve::DefMap, + it: @item) { + let env = env { + root_it: it, + sess: sess, + ast_map: ast_map, + def_map: def_map, + idstack: @mut ~[] + }; + let mut visitor = ItemRecursionCheckingVisitor { + sess: sess, + ast_map: ast_map, + def_map: def_map, + }; + visitor.visit_item(it, env); +} + diff --git a/src/librustc/middle/check_loop.rs b/src/librustc/middle/check_loop.rs index cbd1d3cd9ad81..bddf3b0038f86 100644 --- a/src/librustc/middle/check_loop.rs +++ b/src/librustc/middle/check_loop.rs @@ -12,7 +12,8 @@ use middle::ty; use syntax::ast::*; -use syntax::oldvisit; +use syntax::visit::Visitor; +use syntax::visit; #[deriving(Clone)] pub struct Context { @@ -20,50 +21,61 @@ pub struct Context { can_ret: bool } -pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { - oldvisit::visit_crate(crate, - (Context { in_loop: false, can_ret: true }, - oldvisit::mk_vt(@oldvisit::Visitor { - visit_item: |i, (_cx, v)| { - oldvisit::visit_item(i, (Context { - in_loop: false, - can_ret: true - }, v)); - }, - visit_expr: |e: @expr, (cx, v): (Context, oldvisit::vt)| { - match e.node { - expr_while(e, ref b) => { - (v.visit_expr)(e, (cx, v)); - (v.visit_block)(b, (Context { in_loop: true,.. cx }, v)); - } - expr_loop(ref b, _) => { - (v.visit_block)(b, (Context { in_loop: true,.. cx }, v)); - } - expr_fn_block(_, ref b) => { - (v.visit_block)(b, (Context { - in_loop: false, - can_ret: false - }, v)); - } - expr_break(_) => { - if !cx.in_loop { - tcx.sess.span_err(e.span, "`break` outside of loop"); - } - } - expr_again(_) => { - if !cx.in_loop { - tcx.sess.span_err(e.span, "`loop` outside of loop"); - } - } - expr_ret(oe) => { - if !cx.can_ret { - tcx.sess.span_err(e.span, "`return` in block function"); - } - oldvisit::visit_expr_opt(oe, (cx, v)); - } - _ => oldvisit::visit_expr(e, (cx, v)) +struct LoopCheckingVisitor { + tcx: ty::ctxt, +} + +impl Visitor for LoopCheckingVisitor { + fn visit_item(&mut self, i: @item, _: Context) { + visit::walk_item(self, i, Context { + in_loop: false, + can_ret: true, + }); + } + + fn visit_expr(&mut self, e: @expr, cx: Context) { + match e.node { + expr_while(e, ref b) => { + self.visit_expr(e, cx); + self.visit_block(b, Context { in_loop: true,.. cx }); + } + expr_loop(ref b, _) => { + self.visit_block(b, Context { in_loop: true,.. cx }); + } + expr_fn_block(_, ref b) => { + self.visit_block(b, Context { + in_loop: false, + can_ret: false, + }); + } + expr_break(_) => { + if !cx.in_loop { + self.tcx.sess.span_err(e.span, "`break` outside of loop"); + } + } + expr_again(_) => { + if !cx.in_loop { + self.tcx.sess.span_err(e.span, "`loop` outside of loop"); } - }, - .. *oldvisit::default_visitor() - }))); + } + expr_ret(oe) => { + if !cx.can_ret { + self.tcx.sess.span_err(e.span, "`return` in block function"); + } + visit::walk_expr_opt(self, oe, cx); + } + _ => visit::walk_expr(self, e, cx) + } + } +} + +pub fn check_crate(tcx: ty::ctxt, crate: &Crate) { + let cx = Context { + in_loop: false, + can_ret: true, + }; + let mut visitor = LoopCheckingVisitor { + tcx: tcx, + }; + visit::walk_crate(&mut visitor, crate, cx); } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 9719460bbd33e..5988d4ac6ccad 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -25,7 +25,8 @@ use extra::sort; use syntax::ast::*; use syntax::ast_util::{unguarded_pat, walk_pat}; use syntax::codemap::{span, dummy_sp, spanned}; -use syntax::oldvisit; +use syntax::visit::Visitor; +use syntax::visit; pub struct MatchCheckCtxt { tcx: ty::ctxt, @@ -33,72 +34,96 @@ pub struct MatchCheckCtxt { moves_map: moves::MovesMap } -pub fn check_crate(tcx: ty::ctxt, - method_map: method_map, - moves_map: moves::MovesMap, - crate: &Crate) { - let cx = @MatchCheckCtxt {tcx: tcx, - method_map: method_map, - moves_map: moves_map}; - oldvisit::visit_crate(crate, ((), oldvisit::mk_vt(@oldvisit::Visitor { - visit_expr: |a,b| check_expr(cx, a, b), - visit_local: |a,b| check_local(cx, a, b), - visit_fn: |kind, decl, body, sp, id, (e, v)| - check_fn(cx, kind, decl, body, sp, id, (e, v)), - .. *oldvisit::default_visitor::<()>() - }))); - tcx.sess.abort_if_errors(); -} +impl Visitor<()> for MatchCheckCtxt { + fn visit_expr(&mut self, ex: @expr, _: ()) { + visit::walk_expr(self, ex, ()); + match ex.node { + expr_match(scrut, ref arms) => { + // First, check legality of move bindings. + for arm in arms.iter() { + check_legality_of_move_bindings(self, + arm.guard.is_some(), + arm.pats); + } -pub fn check_expr(cx: @MatchCheckCtxt, - ex: @expr, - (s, v): ((), oldvisit::vt<()>)) { - oldvisit::visit_expr(ex, (s, v)); - match ex.node { - expr_match(scrut, ref arms) => { - // First, check legality of move bindings. - for arm in arms.iter() { - check_legality_of_move_bindings(cx, - arm.guard.is_some(), - arm.pats); - } + check_arms(self, *arms); + /* Check for exhaustiveness */ + // Check for empty enum, because is_useful only works on inhabited + // types. + let pat_ty = node_id_to_type(self.tcx, scrut.id); + if (*arms).is_empty() { + if !type_is_empty(self.tcx, pat_ty) { + // We know the type is inhabited, so this must be wrong + self.tcx.sess.span_err(ex.span, + fmt!("non-exhaustive patterns: \ + type %s is non-empty", + ty_to_str(self.tcx, pat_ty))); + } + // If the type *is* empty, it's vacuously exhaustive + return; + } + match ty::get(pat_ty).sty { + ty_enum(did, _) => { + if (*enum_variants(self.tcx, did)).is_empty() && + (*arms).is_empty() { - check_arms(cx, *arms); - /* Check for exhaustiveness */ - // Check for empty enum, because is_useful only works on inhabited - // types. - let pat_ty = node_id_to_type(cx.tcx, scrut.id); - if (*arms).is_empty() { - if !type_is_empty(cx.tcx, pat_ty) { - // We know the type is inhabited, so this must be wrong - cx.tcx.sess.span_err(ex.span, fmt!("non-exhaustive patterns: \ - type %s is non-empty", - ty_to_str(cx.tcx, pat_ty))); + return; + } + } + _ => { /* We assume only enum types can be uninhabited */ } } - // If the type *is* empty, it's vacuously exhaustive - return; - } - match ty::get(pat_ty).sty { - ty_enum(did, _) => { - if (*enum_variants(cx.tcx, did)).is_empty() && - (*arms).is_empty() { + let arms = arms.iter().filter_map(unguarded_pat).collect::<~[~[@pat]]>().concat_vec(); + if arms.is_empty() { + self.tcx.sess.span_err(ex.span, "non-exhaustive patterns"); + } else { + check_exhaustive(self, ex.span, arms); + } + } + _ => () + } + } - return; + fn visit_local(&mut self, loc: @Local, _: ()) { + visit::walk_local(self, loc, ()); + if is_refutable(self, loc.pat) { + self.tcx.sess.span_err(loc.pat.span, + "refutable pattern in local binding"); + } + + // Check legality of move bindings. + check_legality_of_move_bindings(self, false, [ loc.pat ]); + } + + fn visit_fn(&mut self, + kind: &visit::fn_kind, + decl: &fn_decl, + body: &Block, + sp: span, + id: NodeId, + _: ()) { + visit::walk_fn(self, kind, decl, body, sp, id, ()); + for input in decl.inputs.iter() { + if is_refutable(self, input.pat) { + self.tcx.sess.span_err(input.pat.span, + "refutable pattern in function argument"); } - } - _ => { /* We assume only enum types can be uninhabited */ } - } - let arms = arms.iter().filter_map(unguarded_pat).collect::<~[~[@pat]]>().concat_vec(); - if arms.is_empty() { - cx.tcx.sess.span_err(ex.span, "non-exhaustive patterns"); - } else { - check_exhaustive(cx, ex.span, arms); - } - } - _ => () + } } } +pub fn check_crate(tcx: ty::ctxt, + method_map: method_map, + moves_map: moves::MovesMap, + crate: &Crate) { + let mut cx = MatchCheckCtxt { + tcx: tcx, + method_map: method_map, + moves_map: moves_map + }; + visit::walk_crate(&mut cx, crate, ()); + tcx.sess.abort_if_errors(); +} + // Check for unreachable patterns pub fn check_arms(cx: &MatchCheckCtxt, arms: &[arm]) { let mut seen = ~[]; @@ -787,36 +812,6 @@ pub fn default(cx: &MatchCheckCtxt, r: &[@pat]) -> Option<~[@pat]> { else { None } } -pub fn check_local(cx: &MatchCheckCtxt, - loc: @Local, - (s, v): ((), oldvisit::vt<()>)) { - oldvisit::visit_local(loc, (s, v)); - if is_refutable(cx, loc.pat) { - cx.tcx.sess.span_err(loc.pat.span, - "refutable pattern in local binding"); - } - - // Check legality of move bindings. - check_legality_of_move_bindings(cx, false, [ loc.pat ]); -} - -pub fn check_fn(cx: &MatchCheckCtxt, - kind: &oldvisit::fn_kind, - decl: &fn_decl, - body: &Block, - sp: span, - id: NodeId, - (s, v): ((), - oldvisit::vt<()>)) { - oldvisit::visit_fn(kind, decl, body, sp, id, (s, v)); - for input in decl.inputs.iter() { - if is_refutable(cx, input.pat) { - cx.tcx.sess.span_err(input.pat.span, - "refutable pattern in function argument"); - } - } -} - pub fn is_refutable(cx: &MatchCheckCtxt, pat: &pat) -> bool { match cx.tcx.def_map.find(&pat.id) { Some(&def_variant(enum_id, _)) => { diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 68e3dfd63be9f..c5f3dc6ea0341 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -14,8 +14,10 @@ use middle::astencode; use middle::ty; use middle; -use syntax::{ast, ast_map, ast_util, oldvisit}; +use syntax::{ast, ast_map, ast_util}; use syntax::ast::*; +use syntax::visit::{SimpleVisitor, SimpleVisitorVisitor}; +use syntax::visit; use std::float; use std::hashmap::{HashMap, HashSet}; @@ -267,13 +269,25 @@ pub fn lookup_constness(tcx: ty::ctxt, e: &expr) -> constness { } } +struct ConstantClassifyingVisitor { + tcx: ty::ctxt, +} + +impl SimpleVisitor for ConstantClassifyingVisitor { + fn visit_expr_post(&mut self, e: @expr) { + let _ = classify(e, self.tcx); + } +} + pub fn process_crate(crate: &ast::Crate, tcx: ty::ctxt) { - let v = oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor { - visit_expr_post: |e| { classify(e, tcx); }, - .. *oldvisit::default_simple_visitor() - }); - oldvisit::visit_crate(crate, ((), v)); + let visitor = @mut ConstantClassifyingVisitor { + tcx: tcx, + }; + let mut simple_visitor = SimpleVisitorVisitor { + simple_visitor: visitor as @mut SimpleVisitor, + }; + visit::walk_crate(&mut simple_visitor, crate, ()); tcx.sess.abort_if_errors(); } diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 651ce292d284d..c159a35bc5451 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -20,8 +20,8 @@ use syntax::ast::{deref, expr_call, expr_inline_asm, expr_method_call}; use syntax::ast::{expr_unary, unsafe_fn, expr_path}; use syntax::ast; use syntax::codemap::span; -use syntax::oldvisit::{fk_item_fn, fk_method}; -use syntax::oldvisit; +use syntax::visit::{fk_item_fn, fk_method, Visitor}; +use syntax::visit; #[deriving(Eq)] enum UnsafeContext { @@ -31,134 +31,139 @@ enum UnsafeContext { } struct Context { + /// The type context. + type_context: ty::ctxt, /// The method map. method_map: method_map, /// Whether we're in an unsafe context. unsafe_context: UnsafeContext, } -fn type_is_unsafe_function(ty: ty::t) -> bool { - match ty::get(ty).sty { - ty_bare_fn(ref f) => f.purity == unsafe_fn, - ty_closure(ref f) => f.purity == unsafe_fn, - _ => false, - } -} - -pub fn check_crate(tcx: ty::ctxt, - method_map: method_map, - crate: &ast::Crate) { - let context = @mut Context { - method_map: method_map, - unsafe_context: SafeContext, - }; - - let require_unsafe: @fn(span: span, - description: &str) = |span, description| { - match context.unsafe_context { - SafeContext => { - // Report an error. - tcx.sess.span_err(span, - fmt!("%s requires unsafe function or block", - description)) - } - UnsafeBlock(block_id) => { - // OK, but record this. - debug!("effect: recording unsafe block as used: %?", block_id); - let _ = tcx.used_unsafe.insert(block_id); - } - UnsafeFn => {} +impl Visitor<()> for Context { + fn visit_fn(&mut self, + fn_kind: &visit::fn_kind, + fn_decl: &ast::fn_decl, + block: &ast::Block, + span: span, + node_id: ast::NodeId, + _: ()) { + let (is_item_fn, is_unsafe_fn) = match *fn_kind { + fk_item_fn(_, _, purity, _) => (true, purity == unsafe_fn), + fk_method(_, _, method) => (true, method.purity == unsafe_fn), + _ => (false, false), + }; + + let old_unsafe_context = self.unsafe_context; + if is_unsafe_fn { + self.unsafe_context = UnsafeFn + } else if is_item_fn { + self.unsafe_context = SafeContext } - }; - let visitor = oldvisit::mk_vt(@oldvisit::Visitor { - visit_fn: |fn_kind, fn_decl, block, span, node_id, (_, visitor)| { - let (is_item_fn, is_unsafe_fn) = match *fn_kind { - fk_item_fn(_, _, purity, _) => (true, purity == unsafe_fn), - fk_method(_, _, method) => (true, method.purity == unsafe_fn), - _ => (false, false), - }; - - let old_unsafe_context = context.unsafe_context; - if is_unsafe_fn { - context.unsafe_context = UnsafeFn - } else if is_item_fn { - context.unsafe_context = SafeContext - } + visit::walk_fn(self, fn_kind, fn_decl, block, span, node_id, ()); - oldvisit::visit_fn(fn_kind, - fn_decl, - block, - span, - node_id, - ((), - visitor)); - - context.unsafe_context = old_unsafe_context - }, - - visit_block: |block, (_, visitor)| { - let old_unsafe_context = context.unsafe_context; - if block.rules == ast::UnsafeBlock && - context.unsafe_context == SafeContext { - context.unsafe_context = UnsafeBlock(block.id) - } + self.unsafe_context = old_unsafe_context + } - oldvisit::visit_block(block, ((), visitor)); + fn visit_block(&mut self, block: &ast::Block, _: ()) { + let old_unsafe_context = self.unsafe_context; + if block.rules == ast::UnsafeBlock && + self.unsafe_context == SafeContext { + self.unsafe_context = UnsafeBlock(block.id) + } - context.unsafe_context = old_unsafe_context - }, + visit::walk_block(self, block, ()); - visit_expr: |expr, (_, visitor)| { - match expr.node { - expr_method_call(callee_id, _, _, _, _, _) => { - let base_type = ty::node_id_to_type(tcx, callee_id); - debug!("effect: method call case, base type is %s", - ppaux::ty_to_str(tcx, base_type)); - if type_is_unsafe_function(base_type) { - require_unsafe(expr.span, - "invocation of unsafe method") - } + self.unsafe_context = old_unsafe_context + } + + fn visit_expr(&mut self, expr: @ast::expr, _: ()) { + match expr.node { + expr_method_call(callee_id, _, _, _, _, _) => { + let base_type = ty::node_id_to_type(self.type_context, + callee_id); + debug!("effect: method call case, base type is %s", + ppaux::ty_to_str(self.type_context, base_type)); + if type_is_unsafe_function(base_type) { + self.require_unsafe(expr.span, + "invocation of unsafe method") } - expr_call(base, _, _) => { - let base_type = ty::node_id_to_type(tcx, base.id); - debug!("effect: call case, base type is %s", - ppaux::ty_to_str(tcx, base_type)); - if type_is_unsafe_function(base_type) { - require_unsafe(expr.span, "call to unsafe function") - } + } + expr_call(base, _, _) => { + let base_type = ty::node_id_to_type(self.type_context, + base.id); + debug!("effect: call case, base type is %s", + ppaux::ty_to_str(self.type_context, base_type)); + if type_is_unsafe_function(base_type) { + self.require_unsafe(expr.span, "call to unsafe function") } - expr_unary(_, deref, base) => { - let base_type = ty::node_id_to_type(tcx, base.id); - debug!("effect: unary case, base type is %s", - ppaux::ty_to_str(tcx, base_type)); - match ty::get(base_type).sty { - ty_ptr(_) => { - require_unsafe(expr.span, - "dereference of unsafe pointer") - } - _ => {} + } + expr_unary(_, deref, base) => { + let base_type = ty::node_id_to_type(self.type_context, + base.id); + debug!("effect: unary case, base type is %s", + ppaux::ty_to_str(self.type_context, base_type)); + match ty::get(base_type).sty { + ty_ptr(_) => { + self.require_unsafe(expr.span, + "dereference of unsafe pointer") } + _ => {} } - expr_inline_asm(*) => { - require_unsafe(expr.span, "use of inline assembly") - } - expr_path(*) => { - match ty::resolve_expr(tcx, expr) { - ast::def_static(_, true) => { - require_unsafe(expr.span, "use of mutable static") - } - _ => {} + } + expr_inline_asm(*) => { + self.require_unsafe(expr.span, "use of inline assembly") + } + expr_path(*) => { + match ty::resolve_expr(self.type_context, expr) { + ast::def_static(_, true) => { + self.require_unsafe(expr.span, + "use of mutable static") } + _ => {} } - _ => {} } + _ => {} + } - oldvisit::visit_expr(expr, ((), visitor)) - }, + visit::walk_expr(self, expr, ()); + } +} + +impl Context { + fn require_unsafe(&mut self, span: span, description: &str) { + match self.unsafe_context { + SafeContext => { + // Report an error. + self.type_context.sess.span_err(span, + fmt!("%s requires unsafe function or block", + description)) + } + UnsafeBlock(block_id) => { + // OK, but record this. + debug!("effect: recording unsafe block as used: %?", block_id); + let _ = self.type_context.used_unsafe.insert(block_id); + } + UnsafeFn => {} + } + } +} - .. *oldvisit::default_visitor() - }); +fn type_is_unsafe_function(ty: ty::t) -> bool { + match ty::get(ty).sty { + ty_bare_fn(ref f) => f.purity == unsafe_fn, + ty_closure(ref f) => f.purity == unsafe_fn, + _ => false, + } +} - oldvisit::visit_crate(crate, ((), visitor)) +pub fn check_crate(tcx: ty::ctxt, + method_map: method_map, + crate: &ast::Crate) { + let mut context = Context { + type_context: tcx, + method_map: method_map, + unsafe_context: SafeContext, + }; + visit::walk_crate(&mut context, crate, ()); } diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 34aeaf8a6cebe..b2d5d3a695ec4 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -15,9 +15,9 @@ use syntax::ast::{Crate, NodeId, item, item_fn}; use syntax::ast_map; use syntax::attr; use syntax::codemap::span; -use syntax::oldvisit::{default_visitor, mk_vt, vt, Visitor, visit_crate}; -use syntax::oldvisit::{visit_item}; use syntax::parse::token::special_idents; +use syntax::visit::Visitor; +use syntax::visit; use std::util; struct EntryContext { @@ -39,8 +39,6 @@ struct EntryContext { non_main_fns: ~[(NodeId, span)], } -type EntryVisitor = vt<@mut EntryContext>; - pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map) { // FIXME #4404 android JNI hacks @@ -56,7 +54,7 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map) return } - let ctxt = @mut EntryContext { + let mut ctxt = EntryContext { session: session, ast_map: ast_map, main_fn: None, @@ -64,67 +62,64 @@ pub fn find_entry_point(session: Session, crate: &Crate, ast_map: ast_map::map) start_fn: None, non_main_fns: ~[], }; - - visit_crate(crate, (ctxt, mk_vt(@Visitor { - visit_item: |item, (ctxt, visitor)| find_item(item, ctxt, visitor), - .. *default_visitor() - }))); - - configure_main(ctxt); + visit::walk_crate(&mut ctxt, crate, ()); + configure_main(&mut ctxt); } -fn find_item(item: @item, ctxt: @mut EntryContext, visitor: EntryVisitor) { - match item.node { - item_fn(*) => { - if item.ident == special_idents::main { - match ctxt.ast_map.find(&item.id) { - Some(&ast_map::node_item(_, path)) => { - if path.len() == 0 { - // This is a top-level function so can be 'main' - if ctxt.main_fn.is_none() { - ctxt.main_fn = Some((item.id, item.span)); +impl Visitor<()> for EntryContext { + fn visit_item(&mut self, item: @item, _: ()) { + match item.node { + item_fn(*) => { + if item.ident == special_idents::main { + match self.ast_map.find(&item.id) { + Some(&ast_map::node_item(_, path)) => { + if path.len() == 0 { + // This is a top-level function so can be + // 'main' + if self.main_fn.is_none() { + self.main_fn = Some((item.id, item.span)); + } else { + self.session.span_err( + item.span, + "multiple 'main' functions"); + } } else { - ctxt.session.span_err( - item.span, - "multiple 'main' functions"); + // This isn't main + self.non_main_fns.push((item.id, item.span)); } - } else { - // This isn't main - ctxt.non_main_fns.push((item.id, item.span)); } + _ => util::unreachable() } - _ => util::unreachable() } - } - if attr::contains_name(item.attrs, "main") { - if ctxt.attr_main_fn.is_none() { - ctxt.attr_main_fn = Some((item.id, item.span)); - } else { - ctxt.session.span_err( - item.span, - "multiple 'main' functions"); + if attr::contains_name(item.attrs, "main") { + if self.attr_main_fn.is_none() { + self.attr_main_fn = Some((item.id, item.span)); + } else { + self.session.span_err( + item.span, + "multiple 'main' functions"); + } } - } - if attr::contains_name(item.attrs, "start") { - if ctxt.start_fn.is_none() { - ctxt.start_fn = Some((item.id, item.span)); - } else { - ctxt.session.span_err( - item.span, - "multiple 'start' functions"); + if attr::contains_name(item.attrs, "start") { + if self.start_fn.is_none() { + self.start_fn = Some((item.id, item.span)); + } else { + self.session.span_err( + item.span, + "multiple 'start' functions"); + } } } + _ => () } - _ => () - } - visit_item(item, (ctxt, visitor)); + visit::walk_item(self, item, ()); + } } -fn configure_main(ctxt: @mut EntryContext) { - let this = &mut *ctxt; +fn configure_main(this: &mut EntryContext) { if this.start_fn.is_some() { *this.session.entry_fn = this.start_fn; *this.session.entry_type = Some(session::EntryStart); diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 5f7ef8d31f703..8a61f8bd3bd5c 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -17,7 +17,9 @@ use middle::ty; use std::hashmap::HashMap; use syntax::codemap::span; -use syntax::{ast, ast_util, oldvisit}; +use syntax::{ast, ast_util}; +use syntax::visit::{SimpleVisitor, SimpleVisitorVisitor, Visitor}; +use syntax::visit; // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). @@ -29,6 +31,53 @@ pub struct freevar_entry { pub type freevar_info = @~[@freevar_entry]; pub type freevar_map = @mut HashMap; +struct FreeVarCollectingVisitor { + seen: @mut HashMap, + refs: @mut ~[@freevar_entry], + def_map: resolve::DefMap, +} + +impl Visitor for FreeVarCollectingVisitor { + fn visit_item(&mut self, _: @ast::item, _: int) { + // Ignore! + } + + fn visit_expr(&mut self, expr: @ast::expr, depth: int) { + match expr.node { + ast::expr_fn_block(*) => { + visit::walk_expr(self, expr, depth + 1) + } + ast::expr_path(*) | ast::expr_self => { + let mut i = 0; + match self.def_map.find(&expr.id) { + None => fail!("path not found"), + Some(&df) => { + let mut def = df; + while i < depth { + match def { + ast::def_upvar(_, inner, _, _) => { def = *inner; } + _ => break + } + i += 1; + } + if i == depth { // Made it to end of loop + let dnum = ast_util::def_id_of_def(def).node; + if !self.seen.contains_key(&dnum) { + self.refs.push(@freevar_entry { + def: def, + span: expr.span, + }); + self.seen.insert(dnum, ()); + } + } + } + } + } + _ => visit::walk_expr(self, expr, depth) + } + } +} + // Searches through part of the AST for all references to locals or // upvars in this frame and returns the list of definition IDs thus found. // Since we want to be able to collect upvars in some arbitrary piece @@ -38,50 +87,30 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) -> freevar_info { let seen = @mut HashMap::new(); let refs = @mut ~[]; + let mut visitor = FreeVarCollectingVisitor { + seen: seen, + refs: refs, + def_map: def_map, + }; + visitor.visit_block(blk, 1); + return @(*refs).clone(); +} - fn ignore_item(_i: @ast::item, (_depth, _v): (int, oldvisit::vt)) { } - - let walk_expr: @fn(expr: @ast::expr, (int, oldvisit::vt)) = - |expr, (depth, v)| { - match expr.node { - ast::expr_fn_block(*) => { - oldvisit::visit_expr(expr, (depth + 1, v)) - } - ast::expr_path(*) | ast::expr_self => { - let mut i = 0; - match def_map.find(&expr.id) { - None => fail!("path not found"), - Some(&df) => { - let mut def = df; - while i < depth { - match def { - ast::def_upvar(_, inner, _, _) => { def = *inner; } - _ => break - } - i += 1; - } - if i == depth { // Made it to end of loop - let dnum = ast_util::def_id_of_def(def).node; - if !seen.contains_key(&dnum) { - refs.push(@freevar_entry { - def: def, - span: expr.span, - }); - seen.insert(dnum, ()); - } - } - } - } - } - _ => oldvisit::visit_expr(expr, (depth, v)) - } - }; +struct FreeVarAnnotatingVisitor { + def_map: resolve::DefMap, + freevars: freevar_map, +} - let v = oldvisit::mk_vt(@oldvisit::Visitor {visit_item: ignore_item, - visit_expr: walk_expr, - .. *oldvisit::default_visitor()}); - (v.visit_block)(blk, (1, v)); - return @(*refs).clone(); +impl SimpleVisitor for FreeVarAnnotatingVisitor { + fn visit_fn(&mut self, + _: &visit::fn_kind, + _: &ast::fn_decl, + blk: &ast::Block, + _: span, + nid: ast::NodeId) { + let vars = collect_freevars(self.def_map, blk); + self.freevars.insert(nid, vars); + } } // Build a map from every function and for-each body to a set of the @@ -92,22 +121,14 @@ fn collect_freevars(def_map: resolve::DefMap, blk: &ast::Block) pub fn annotate_freevars(def_map: resolve::DefMap, crate: &ast::Crate) -> freevar_map { let freevars = @mut HashMap::new(); - - let walk_fn: @fn(&oldvisit::fn_kind, - &ast::fn_decl, - &ast::Block, - span, - ast::NodeId) = |_, _, blk, _, nid| { - let vars = collect_freevars(def_map, blk); - freevars.insert(nid, vars); + let visitor = @mut FreeVarAnnotatingVisitor { + def_map: def_map, + freevars: freevars, }; - - let visitor = - oldvisit::mk_simple_visitor(@oldvisit::SimpleVisitor { - visit_fn: walk_fn, - .. *oldvisit::default_simple_visitor()}); - oldvisit::visit_crate(crate, ((), visitor)); - + let mut simple_visitor = SimpleVisitorVisitor { + simple_visitor: visitor as @mut SimpleVisitor, + }; + visit::walk_crate(&mut simple_visitor, crate, ()); return freevars; } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 283724447f831..8bf3f4900b5d9 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -52,7 +52,7 @@ use middle::typeck; use util::ppaux::{ty_to_str, region_ptr_to_str, Repr}; use util::common::indenter; -use syntax::ast::{m_imm, m_const, m_mutbl}; +use syntax::ast::{m_imm, m_mutbl}; use syntax::ast; use syntax::codemap::span; use syntax::print::pprust; @@ -114,7 +114,6 @@ pub enum ElementKind { #[deriving(Eq, IterBytes)] pub enum MutabilityCategory { McImmutable, // Immutable. - McReadOnly, // Read-only (`const`) McDeclared, // Directly declared as mutable. McInherited // Inherited from the fact that owner is mutable. } @@ -298,7 +297,6 @@ impl MutabilityCategory { pub fn from_mutbl(m: ast::mutability) -> MutabilityCategory { match m { m_imm => McImmutable, - m_const => McReadOnly, m_mutbl => McDeclared } } @@ -306,7 +304,6 @@ impl MutabilityCategory { pub fn inherit(&self) -> MutabilityCategory { match *self { McImmutable => McImmutable, - McReadOnly => McReadOnly, McDeclared => McInherited, McInherited => McInherited } @@ -314,7 +311,7 @@ impl MutabilityCategory { pub fn is_mutable(&self) -> bool { match *self { - McImmutable | McReadOnly => false, + McImmutable => false, McDeclared | McInherited => true } } @@ -322,7 +319,7 @@ impl MutabilityCategory { pub fn is_immutable(&self) -> bool { match *self { McImmutable => true, - McReadOnly | McDeclared | McInherited => false + McDeclared | McInherited => false } } @@ -330,7 +327,6 @@ impl MutabilityCategory { match *self { McDeclared | McInherited => "mutable", McImmutable => "immutable", - McReadOnly => "const" } } } @@ -617,7 +613,6 @@ impl mem_categorization_ctxt { -> MutabilityCategory { match interior_m { m_imm => base_m.inherit(), - m_const => McReadOnly, m_mutbl => McDeclared } } @@ -1006,7 +1001,6 @@ impl mem_categorization_ctxt { pub fn mut_to_str(&self, mutbl: ast::mutability) -> ~str { match mutbl { m_mutbl => ~"mutable", - m_const => ~"const", m_imm => ~"immutable" } } @@ -1175,7 +1169,6 @@ impl cmt_ { Some(AliasableManaged(m)) } - cat_deref(_, _, region_ptr(m @ m_const, _)) | cat_deref(_, _, region_ptr(m @ m_imm, _)) => { Some(AliasableBorrowed(m)) } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 54e7c79e97cc2..b9dad6b45c502 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -8,9 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// A pass that checks to make sure private fields and methods aren't used -// outside their scopes. - +//! A pass that checks to make sure private fields and methods aren't used +//! outside their scopes. use metadata::csearch; use middle::ty::{ty_struct, ty_enum}; @@ -33,12 +32,12 @@ use syntax::ast_util::{Private, Public, is_local}; use syntax::ast_util::{variant_visibility_to_privacy, visibility_to_privacy}; use syntax::attr; use syntax::codemap::span; -use syntax::parse::token; use syntax::oldvisit; +use syntax::parse::token; pub fn check_crate<'mm>(tcx: ty::ctxt, - method_map: &'mm method_map, - crate: &ast::Crate) { + method_map: &'mm method_map, + crate: &ast::Crate) { let privileged_items = @mut ~[]; // Adds an item to its scope. @@ -255,7 +254,9 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, match def { def_static_method(method_id, _, _) => { debug!("found static method def, checking it"); - check_method_common(span, method_id, path.idents.last()) + check_method_common(span, + method_id, + &path.segments.last().identifier) } def_fn(def_id, _) => { if def_id.crate == LOCAL_CRATE { @@ -263,13 +264,19 @@ pub fn check_crate<'mm>(tcx: ty::ctxt, !privileged_items.iter().any(|x| x == &def_id.node) { tcx.sess.span_err(span, fmt!("function `%s` is private", - token::ident_to_str(path.idents.last()))); + token::ident_to_str( + &path.segments + .last() + .identifier))); } } else if csearch::get_item_visibility(tcx.sess.cstore, def_id) != public { tcx.sess.span_err(span, fmt!("function `%s` is private", - token::ident_to_str(path.idents.last()))); + token::ident_to_str( + &path.segments + .last() + .identifier))); } } _ => {} diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 4da22be4428e2..01b1b4c3e4e99 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -34,7 +34,10 @@ use syntax::codemap::span; use syntax::print::pprust; use syntax::parse::token; use syntax::parse::token::special_idents; -use syntax::{ast, oldvisit}; +use syntax::ast; +use syntax::oldvisit; +use syntax::visit::Visitor; +use syntax::visit; /** The region maps encode information about region relationships. @@ -323,147 +326,142 @@ fn parent_to_expr(cx: Context, child_id: ast::NodeId, sp: span) { } } -fn resolve_block(blk: &ast::Block, - (cx, visitor): (Context, oldvisit::vt)) { - // Record the parent of this block. - parent_to_expr(cx, blk.id, blk.span); - - // Descend. - let new_cx = Context {var_parent: Some(blk.id), - parent: Some(blk.id), - ..cx}; - oldvisit::visit_block(blk, (new_cx, visitor)); +struct RegionVisitor { + contents: (), } -fn resolve_arm(arm: &ast::arm, - (cx, visitor): (Context, oldvisit::vt)) { - oldvisit::visit_arm(arm, (cx, visitor)); -} +impl Visitor for RegionVisitor { + fn visit_block(&mut self, blk: &ast::Block, cx: Context) { + // Record the parent of this block. + parent_to_expr(cx, blk.id, blk.span); -fn resolve_pat(pat: @ast::pat, - (cx, visitor): (Context, oldvisit::vt)) { - assert_eq!(cx.var_parent, cx.parent); - parent_to_expr(cx, pat.id, pat.span); - oldvisit::visit_pat(pat, (cx, visitor)); -} - -fn resolve_stmt(stmt: @ast::stmt, - (cx, visitor): (Context, oldvisit::vt)) { - match stmt.node { - ast::stmt_decl(*) => { - oldvisit::visit_stmt(stmt, (cx, visitor)); - } - ast::stmt_expr(_, stmt_id) | - ast::stmt_semi(_, stmt_id) => { - parent_to_expr(cx, stmt_id, stmt.span); - let expr_cx = Context {parent: Some(stmt_id), ..cx}; - oldvisit::visit_stmt(stmt, (expr_cx, visitor)); - } - ast::stmt_mac(*) => cx.sess.bug("unexpanded macro") + // Descend. + let new_cx = Context {var_parent: Some(blk.id), + parent: Some(blk.id), + ..cx}; + visit::walk_block(self, blk, new_cx); } -} -fn resolve_expr(expr: @ast::expr, - (cx, visitor): (Context, oldvisit::vt)) { - parent_to_expr(cx, expr.id, expr.span); - - let mut new_cx = cx; - new_cx.parent = Some(expr.id); - match expr.node { - ast::expr_assign_op(*) | ast::expr_index(*) | ast::expr_binary(*) | - ast::expr_unary(*) | ast::expr_call(*) | ast::expr_method_call(*) => { - // FIXME(#6268) Nested method calls - // - // The lifetimes for a call or method call look as follows: - // - // call.id - // - arg0.id - // - ... - // - argN.id - // - call.callee_id - // - // The idea is that call.callee_id represents *the time when - // the invoked function is actually running* and call.id - // represents *the time to prepare the arguments and make the - // call*. See the section "Borrows in Calls" borrowck/doc.rs - // for an extended explanantion of why this distinction is - // important. - // - // parent_to_expr(new_cx, expr.callee_id); - } + fn visit_pat(&mut self, pat: @ast::pat, cx: Context) { + assert_eq!(cx.var_parent, cx.parent); + parent_to_expr(cx, pat.id, pat.span); + visit::walk_pat(self, pat, cx); + } - ast::expr_match(*) => { - new_cx.var_parent = Some(expr.id); + fn visit_stmt(&mut self, stmt: @ast::stmt, cx: Context) { + match stmt.node { + ast::stmt_decl(*) => { + visit::walk_stmt(self, stmt, cx); + } + ast::stmt_expr(_, stmt_id) | + ast::stmt_semi(_, stmt_id) => { + parent_to_expr(cx, stmt_id, stmt.span); + let expr_cx = Context {parent: Some(stmt_id), ..cx}; + visit::walk_stmt(self, stmt, expr_cx); + } + ast::stmt_mac(*) => cx.sess.bug("unexpanded macro") } + } - _ => {} - }; - - - oldvisit::visit_expr(expr, (new_cx, visitor)); -} + fn visit_expr(&mut self, expr: @ast::expr, cx: Context) { + parent_to_expr(cx, expr.id, expr.span); + + let mut new_cx = cx; + new_cx.parent = Some(expr.id); + match expr.node { + ast::expr_assign_op(*) | ast::expr_index(*) | ast::expr_binary(*) | + ast::expr_unary(*) | ast::expr_call(*) + | ast::expr_method_call(*) => { + // FIXME(#6268) Nested method calls + // + // The lifetimes for a call or method call look as follows: + // + // call.id + // - arg0.id + // - ... + // - argN.id + // - call.callee_id + // + // The idea is that call.callee_id represents *the time when + // the invoked function is actually running* and call.id + // represents *the time to prepare the arguments and make the + // call*. See the section "Borrows in Calls" borrowck/doc.rs + // for an extended explanantion of why this distinction is + // important. + // + // parent_to_expr(new_cx, expr.callee_id); + } -fn resolve_local(local: @ast::Local, - (cx, visitor): (Context, oldvisit::vt)) { - assert_eq!(cx.var_parent, cx.parent); - parent_to_expr(cx, local.id, local.span); - oldvisit::visit_local(local, (cx, visitor)); -} + ast::expr_match(*) => { + new_cx.var_parent = Some(expr.id); + } -fn resolve_item(item: @ast::item, - (cx, visitor): (Context, oldvisit::vt)) { - // Items create a new outer block scope as far as we're concerned. - let new_cx = Context {var_parent: None, parent: None, ..cx}; - oldvisit::visit_item(item, (new_cx, visitor)); -} + _ => {} + }; -fn resolve_fn(fk: &oldvisit::fn_kind, - decl: &ast::fn_decl, - body: &ast::Block, - sp: span, - id: ast::NodeId, - (cx, visitor): (Context, - oldvisit::vt)) { - debug!("region::resolve_fn(id=%?, \ - span=%?, \ - body.id=%?, \ - cx.parent=%?)", - id, - cx.sess.codemap.span_to_str(sp), - body.id, - cx.parent); - - // The arguments and `self` are parented to the body of the fn. - let decl_cx = Context {parent: Some(body.id), - var_parent: Some(body.id), - ..cx}; - match *fk { - oldvisit::fk_method(_, _, method) => { - cx.region_maps.record_parent(method.self_id, body.id); + visit::walk_expr(self, expr, new_cx); + } + + fn visit_local(&mut self, local: @ast::Local, cx: Context) { + assert_eq!(cx.var_parent, cx.parent); + parent_to_expr(cx, local.id, local.span); + visit::walk_local(self, local, cx); + } + + fn visit_item(&mut self, item: @ast::item, cx: Context) { + // Items create a new outer block scope as far as we're concerned. + let new_cx = Context {var_parent: None, parent: None, ..cx}; + visit::walk_item(self, item, new_cx); + } + + fn visit_fn(&mut self, + fk: &visit::fn_kind, + decl: &ast::fn_decl, + body: &ast::Block, + sp: span, + id: ast::NodeId, + cx: Context) { + debug!("region::resolve_fn(id=%?, \ + span=%?, \ + body.id=%?, \ + cx.parent=%?)", + id, + cx.sess.codemap.span_to_str(sp), + body.id, + cx.parent); + + // The arguments and `self` are parented to the body of the fn. + let decl_cx = Context {parent: Some(body.id), + var_parent: Some(body.id), + ..cx}; + match *fk { + visit::fk_method(_, _, method) => { + cx.region_maps.record_parent(method.self_id, body.id); + } + _ => {} } - _ => {} - } - oldvisit::visit_fn_decl(decl, (decl_cx, visitor)); + visit::walk_fn_decl(self, decl, decl_cx); + + // The body of the fn itself is either a root scope (top-level fn) + // or it continues with the inherited scope (closures). + let body_cx = match *fk { + visit::fk_item_fn(*) | + visit::fk_method(*) => { + Context {parent: None, var_parent: None, ..cx} + } + visit::fk_anon(*) | + visit::fk_fn_block(*) => { + cx + } + }; - // The body of the fn itself is either a root scope (top-level fn) - // or it continues with the inherited scope (closures). - let body_cx = match *fk { - oldvisit::fk_item_fn(*) | - oldvisit::fk_method(*) => { - Context {parent: None, var_parent: None, ..cx} - } - oldvisit::fk_anon(*) | - oldvisit::fk_fn_block(*) => { - cx - } - }; - (visitor.visit_block)(body, (body_cx, visitor)); + self.visit_block(body, body_cx); + } } pub fn resolve_crate(sess: Session, def_map: resolve::DefMap, - crate: &ast::Crate) -> @mut RegionMaps -{ + crate: &ast::Crate) -> @mut RegionMaps { let region_maps = @mut RegionMaps { scope_map: HashMap::new(), free_region_map: HashMap::new(), @@ -474,18 +472,10 @@ pub fn resolve_crate(sess: Session, region_maps: region_maps, parent: None, var_parent: None}; - let visitor = oldvisit::mk_vt(@oldvisit::Visitor { - visit_block: resolve_block, - visit_item: resolve_item, - visit_fn: resolve_fn, - visit_arm: resolve_arm, - visit_pat: resolve_pat, - visit_stmt: resolve_stmt, - visit_expr: resolve_expr, - visit_local: resolve_local, - .. *oldvisit::default_visitor() - }); - oldvisit::visit_crate(crate, (cx, visitor)); + let mut visitor = RegionVisitor { + contents: () + }; + visit::walk_crate(&mut visitor, crate, cx); return region_maps; } @@ -673,10 +663,10 @@ impl DetermineRpCtxt { } } - pub fn with(@mut self, + pub fn with(&mut self, item_id: ast::NodeId, anon_implies_rp: bool, - f: &fn()) { + f: &fn(&mut DetermineRpCtxt)) { let old_item_id = self.item_id; let old_anon_implies_rp = self.anon_implies_rp; self.item_id = item_id; @@ -685,203 +675,205 @@ impl DetermineRpCtxt { item_id, anon_implies_rp); let _i = ::util::common::indenter(); - f(); + f(self); self.item_id = old_item_id; self.anon_implies_rp = old_anon_implies_rp; } - pub fn with_ambient_variance(@mut self, + pub fn with_ambient_variance(&mut self, variance: region_variance, - f: &fn()) { + f: &fn(&mut DetermineRpCtxt)) { let old_ambient_variance = self.ambient_variance; self.ambient_variance = self.add_variance(variance); - f(); + f(self); self.ambient_variance = old_ambient_variance; } } -fn determine_rp_in_item(item: @ast::item, - (cx, visitor): (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - do cx.with(item.id, true) { - oldvisit::visit_item(item, (cx, visitor)); +impl DetermineRpCtxt { + fn visit_mt(&mut self, mt: &ast::mt, _: ()) { + // mutability is invariant + if mt.mutbl == ast::m_mutbl { + do self.with_ambient_variance(rv_invariant) |this| { + this.visit_ty(mt.ty, ()); + } + } else { + self.visit_ty(mt.ty, ()); + } } } -fn determine_rp_in_fn(fk: &oldvisit::fn_kind, - decl: &ast::fn_decl, - body: &ast::Block, - _: span, - _: ast::NodeId, - (cx, visitor): (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - do cx.with(cx.item_id, false) { - do cx.with_ambient_variance(rv_contravariant) { - for a in decl.inputs.iter() { - (visitor.visit_ty)(&a.ty, (cx, visitor)); +impl Visitor<()> for DetermineRpCtxt { + fn visit_item(&mut self, item: @ast::item, _: ()) { + do self.with(item.id, true) |this| { + visit::walk_item(this, item, ()); + } + } + + fn visit_fn(&mut self, + fk: &visit::fn_kind, + decl: &ast::fn_decl, + body: &ast::Block, + _: span, + _: ast::NodeId, + _: ()) { + do self.with(self.item_id, false) |this| { + do this.with_ambient_variance(rv_contravariant) |this| { + for a in decl.inputs.iter() { + this.visit_ty(&a.ty, ()); + } } + this.visit_ty(&decl.output, ()); + let generics = visit::generics_of_fn(fk); + this.visit_generics(&generics, ()); + this.visit_block(body, ()); } - (visitor.visit_ty)(&decl.output, (cx, visitor)); - let generics = oldvisit::generics_of_fn(fk); - (visitor.visit_generics)(&generics, (cx, visitor)); - (visitor.visit_block)(body, (cx, visitor)); } -} -fn determine_rp_in_ty_method(ty_m: &ast::TypeMethod, - (cx, visitor): - (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - do cx.with(cx.item_id, false) { - oldvisit::visit_ty_method(ty_m, (cx, visitor)); + fn visit_ty_method(&mut self, + ty_m: &ast::TypeMethod, + _: ()) { + do self.with(self.item_id, false) |this| { + visit::walk_ty_method(this, ty_m, ()); + } } -} -fn determine_rp_in_ty(ty: &ast::Ty, - (cx, visitor): (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - // we are only interested in types that will require an item to - // be region-parameterized. if cx.item_id is zero, then this type - // is not a member of a type defn nor is it a constitutent of an - // impl etc. So we can ignore it and its components. - if cx.item_id == 0 { return; } - - // if this type directly references a region pointer like &'r ty, - // add to the worklist/set. Note that &'r ty is contravariant with - // respect to &r, because &'r ty can be used whereever a *smaller* - // region is expected (and hence is a supertype of those - // locations) - let sess = cx.sess; - match ty.node { - ast::ty_rptr(ref r, _) => { - debug!("referenced rptr type %s", - pprust::ty_to_str(ty, sess.intr())); - - if cx.region_is_relevant(r) { - let rv = cx.add_variance(rv_contravariant); - cx.add_rp(cx.item_id, rv) - } + fn visit_ty(&mut self, ty: &ast::Ty, _: ()) { + // we are only interested in types that will require an item to + // be region-parameterized. if cx.item_id is zero, then this type + // is not a member of a type defn nor is it a constitutent of an + // impl etc. So we can ignore it and its components. + if self.item_id == 0 { + return; } - ast::ty_closure(ref f) => { - debug!("referenced fn type: %s", - pprust::ty_to_str(ty, sess.intr())); - match f.region { - Some(_) => { - if cx.region_is_relevant(&f.region) { - let rv = cx.add_variance(rv_contravariant); - cx.add_rp(cx.item_id, rv) - } + // if this type directly references a region pointer like &'r ty, + // add to the worklist/set. Note that &'r ty is contravariant with + // respect to &r, because &'r ty can be used whereever a *smaller* + // region is expected (and hence is a supertype of those + // locations) + let sess = self.sess; + match ty.node { + ast::ty_rptr(ref r, _) => { + debug!("referenced rptr type %s", + pprust::ty_to_str(ty, sess.intr())); + + if self.region_is_relevant(r) { + let rv = self.add_variance(rv_contravariant); + self.add_rp(self.item_id, rv) } - None => { - if f.sigil == ast::BorrowedSigil && cx.anon_implies_rp { - let rv = cx.add_variance(rv_contravariant); - cx.add_rp(cx.item_id, rv) + } + + ast::ty_closure(ref f) => { + debug!("referenced fn type: %s", + pprust::ty_to_str(ty, sess.intr())); + match f.region { + Some(_) => { + if self.region_is_relevant(&f.region) { + let rv = self.add_variance(rv_contravariant); + self.add_rp(self.item_id, rv) + } + } + None => { + if f.sigil == ast::BorrowedSigil && + self.anon_implies_rp { + let rv = self.add_variance(rv_contravariant); + self.add_rp(self.item_id, rv) + } } } } + + _ => {} } - _ => {} - } - - // if this references another named type, add the dependency - // to the dep_map. If the type is not defined in this crate, - // then check whether it is region-parameterized and consider - // that as a direct dependency. - match ty.node { - ast::ty_path(ref path, _, id) => { - match cx.def_map.find(&id) { - Some(&ast::def_ty(did)) | - Some(&ast::def_trait(did)) | - Some(&ast::def_struct(did)) => { - if did.crate == ast::LOCAL_CRATE { - if cx.region_is_relevant(&path.rp) { - cx.add_dep(did.node); - } - } else { - let cstore = sess.cstore; - match csearch::get_region_param(cstore, did) { - None => {} - Some(variance) => { - debug!("reference to external, rp'd type %s", - pprust::ty_to_str(ty, sess.intr())); - if cx.region_is_relevant(&path.rp) { - let rv = cx.add_variance(variance); - cx.add_rp(cx.item_id, rv) + // if this references another named type, add the dependency + // to the dep_map. If the type is not defined in this crate, + // then check whether it is region-parameterized and consider + // that as a direct dependency. + match ty.node { + ast::ty_path(ref path, _, id) => { + match self.def_map.find(&id) { + Some(&ast::def_ty(did)) | + Some(&ast::def_trait(did)) | + Some(&ast::def_struct(did)) => { + if did.crate == ast::LOCAL_CRATE { + if self.region_is_relevant(&path.segments + .last() + .lifetime) { + self.add_dep(did.node); + } + } else { + let cstore = sess.cstore; + match csearch::get_region_param(cstore, did) { + None => {} + Some(variance) => { + debug!("reference to external, rp'd type %s", + pprust::ty_to_str(ty, sess.intr())); + if self.region_is_relevant(&path.segments + .last() + .lifetime) { + let rv = self.add_variance(variance); + self.add_rp(self.item_id, rv) + } + } } - } } + } + _ => {} } } _ => {} } - } - _ => {} - } - match ty.node { - ast::ty_box(ref mt) | ast::ty_uniq(ref mt) | ast::ty_vec(ref mt) | - ast::ty_rptr(_, ref mt) | ast::ty_ptr(ref mt) => { - visit_mt(mt, (cx, visitor)); - } + match ty.node { + ast::ty_box(ref mt) | ast::ty_uniq(ref mt) | ast::ty_vec(ref mt) | + ast::ty_rptr(_, ref mt) | ast::ty_ptr(ref mt) => { + self.visit_mt(mt, ()); + } - ast::ty_path(ref path, _, _) => { - // type parameters are---for now, anyway---always invariant - do cx.with_ambient_variance(rv_invariant) { - for tp in path.types.iter() { - (visitor.visit_ty)(tp, (cx, visitor)); + ast::ty_path(ref path, _, _) => { + // type parameters are---for now, anyway---always invariant + do self.with_ambient_variance(rv_invariant) |this| { + for tp in path.segments.iter().flat_map(|s| s.types.iter()) { + this.visit_ty(tp, ()); + } } - } - } - - ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) | - ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => { - // fn() binds the & region, so do not consider &T types that - // appear *inside* a fn() type to affect the enclosing item: - do cx.with(cx.item_id, false) { - // parameters are contravariant - do cx.with_ambient_variance(rv_contravariant) { - for a in decl.inputs.iter() { - (visitor.visit_ty)(&a.ty, (cx, visitor)); + } + + ast::ty_closure(@ast::TyClosure {decl: ref decl, _}) | + ast::ty_bare_fn(@ast::TyBareFn {decl: ref decl, _}) => { + // fn() binds the & region, so do not consider &T types that + // appear *inside* a fn() type to affect the enclosing item: + do self.with(self.item_id, false) |this| { + // parameters are contravariant + do this.with_ambient_variance(rv_contravariant) |this| { + for a in decl.inputs.iter() { + this.visit_ty(&a.ty, ()); + } } + this.visit_ty(&decl.output, ()); } - (visitor.visit_ty)(&decl.output, (cx, visitor)); + } + + _ => { + visit::walk_ty(self, ty, ()); + } } - } - _ => { - oldvisit::visit_ty(ty, (cx, visitor)); - } } - fn visit_mt(mt: &ast::mt, - (cx, visitor): (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - // mutability is invariant - if mt.mutbl == ast::m_mutbl { - do cx.with_ambient_variance(rv_invariant) { - (visitor.visit_ty)(mt.ty, (cx, visitor)); - } - } else { - (visitor.visit_ty)(mt.ty, (cx, visitor)); - } + fn visit_struct_field(&mut self, cm: @ast::struct_field, _: ()) { + visit::walk_struct_field(self, cm, ()); } } -fn determine_rp_in_struct_field( - cm: @ast::struct_field, - (cx, visitor): (@mut DetermineRpCtxt, - oldvisit::vt<@mut DetermineRpCtxt>)) { - oldvisit::visit_struct_field(cm, (cx, visitor)); -} - pub fn determine_rp_in_crate(sess: Session, ast_map: ast_map::map, def_map: resolve::DefMap, crate: &ast::Crate) - -> region_paramd_items { - let cx = @mut DetermineRpCtxt { + -> region_paramd_items { + let mut cx = DetermineRpCtxt { sess: sess, ast_map: ast_map, def_map: def_map, @@ -894,15 +886,7 @@ pub fn determine_rp_in_crate(sess: Session, }; // Gather up the base set, worklist and dep_map - let visitor = oldvisit::mk_vt(@oldvisit::Visitor { - visit_fn: determine_rp_in_fn, - visit_item: determine_rp_in_item, - visit_ty: determine_rp_in_ty, - visit_ty_method: determine_rp_in_ty_method, - visit_struct_field: determine_rp_in_struct_field, - .. *oldvisit::default_visitor() - }); - oldvisit::visit_crate(crate, (cx, visitor)); + visit::walk_crate(&mut cx, crate, ()); // Propagate indirect dependencies // @@ -914,7 +898,7 @@ pub fn determine_rp_in_crate(sess: Session, // with the ambient variance where the reference occurred and then // update the region-parameterization of D to reflect the result. { - let cx = &mut *cx; + let cx = &mut cx; while cx.worklist.len() != 0 { let c_id = cx.worklist.pop(); let c_variance = cx.region_paramd_items.get_copy(&c_id); diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 4d95909404e18..150d56ad89250 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -58,6 +58,12 @@ pub type BindingMap = HashMap; // Trait method resolution pub type TraitMap = HashMap; +// A summary of the generics on a trait. +struct TraitGenerics { + has_lifetime: bool, + type_parameter_count: uint, +} + // This is the replacement export map. It maps a module to all of the exports // within. pub type ExportMap2 = @mut HashMap; @@ -1230,7 +1236,7 @@ impl Resolver { &Ty { node: ty_path(ref path, _, _), _ - } if path.idents.len() == 1 => { + } if path.segments.len() == 1 => { let name = path_to_ident(path); let new_parent = match parent.children.find(&name) { @@ -1274,9 +1280,12 @@ impl Resolver { method.span); let def = match method.explicit_self.node { sty_static => { - // Static methods become `def_fn`s. - def_fn(local_def(method.id), - method.purity) + // Static methods become + // `def_static_method`s. + def_static_method(local_def(method.id), + FromImpl(local_def( + item.id)), + method.purity) } _ => { // Non-static methods become @@ -1326,7 +1335,7 @@ impl Resolver { sty_static => { // Static methods become `def_static_method`s. def_static_method(local_def(ty_m.id), - Some(local_def(item.id)), + FromTrait(local_def(item.id)), ty_m.purity) } _ => { @@ -1430,20 +1439,22 @@ impl Resolver { let mut module_path = ~[]; match view_path.node { view_path_simple(_, ref full_path, _) => { - let path_len = full_path.idents.len(); + let path_len = full_path.segments.len(); assert!(path_len != 0); - for (i, ident) in full_path.idents.iter().enumerate() { + for (i, segment) in full_path.segments + .iter() + .enumerate() { if i != path_len - 1 { - module_path.push(*ident); + module_path.push(segment.identifier) } } } view_path_glob(ref module_ident_path, _) | view_path_list(ref module_ident_path, _, _) => { - for ident in module_ident_path.idents.iter() { - module_path.push(*ident); + for segment in module_ident_path.segments.iter() { + module_path.push(segment.identifier) } } } @@ -1452,7 +1463,8 @@ impl Resolver { let module_ = self.get_module_from_parent(parent); match view_path.node { view_path_simple(binding, ref full_path, id) => { - let source_ident = *full_path.idents.last(); + let source_ident = + full_path.segments.last().identifier; let subclass = @SingleImport(binding, source_ident); self.build_import_directive(privacy, @@ -2063,6 +2075,14 @@ impl Resolver { return result; } + fn path_idents_to_str(@mut self, path: &Path) -> ~str { + let identifiers: ~[ast::ident] = path.segments + .iter() + .map(|seg| seg.identifier) + .collect(); + self.idents_to_str(identifiers) + } + pub fn import_directive_subclass_to_str(@mut self, subclass: ImportDirectiveSubclass) -> @str { @@ -3811,8 +3831,7 @@ impl Resolver { reference_type: TraitReferenceType) { match self.resolve_path(id, &trait_reference.path, TypeNS, true, visitor) { None => { - let path_str = self.idents_to_str(trait_reference.path.idents); - + let path_str = self.path_idents_to_str(&trait_reference.path); let usage_str = match reference_type { TraitBoundingTypeParameter => "bound type parameter with", TraitImplementation => "implement", @@ -4111,8 +4130,8 @@ impl Resolver { let mut result_def = None; // First, check to see whether the name is a primitive type. - if path.idents.len() == 1 { - let name = *path.idents.last(); + if path.segments.len() == 1 { + let name = path.segments.last().identifier; match self.primitive_type_table .primitive_types @@ -4121,6 +4140,22 @@ impl Resolver { Some(&primitive_type) => { result_def = Some(def_prim_ty(primitive_type)); + + if path.segments + .iter() + .any(|s| s.lifetime.is_some()) { + self.session.span_err(path.span, + "lifetime parameters \ + are not allowed on \ + this type") + } else if path.segments + .iter() + .any(|s| s.types.len() > 0) { + self.session.span_err(path.span, + "type parameters are \ + not allowed on this \ + type") + } } None => { // Continue. @@ -4130,12 +4165,17 @@ impl Resolver { match result_def { None => { - match self.resolve_path(ty.id, path, TypeNS, true, visitor) { + match self.resolve_path(ty.id, + path, + TypeNS, + true, + visitor) { Some(def) => { debug!("(resolving type) resolved `%s` to \ type %?", - self.session.str_of( - *path.idents.last()), + self.session.str_of(path.segments + .last() + .identifier), def); result_def = Some(def); } @@ -4144,9 +4184,7 @@ impl Resolver { } } } - Some(_) => { - // Continue. - } + Some(_) => {} // Continue. } match result_def { @@ -4154,14 +4192,15 @@ impl Resolver { // Write the result into the def map. debug!("(resolving type) writing resolution for `%s` \ (id %d)", - self.idents_to_str(path.idents), + self.path_idents_to_str(path), path_id); self.record_def(path_id, def); } None => { self.session.span_err - (ty.span, fmt!("use of undeclared type name `%s`", - self.idents_to_str(path.idents))); + (ty.span, + fmt!("use of undeclared type name `%s`", + self.path_idents_to_str(path))) } } @@ -4200,7 +4239,7 @@ impl Resolver { do walk_pat(pattern) |pattern| { match pattern.node { pat_ident(binding_mode, ref path, _) - if !path.global && path.idents.len() == 1 => { + if !path.global && path.segments.len() == 1 => { // The meaning of pat_ident with no type parameters // depends on whether an enum variant or unit-like struct @@ -4211,7 +4250,7 @@ impl Resolver { // such a value is simply disallowed (since it's rarely // what you want). - let ident = path.idents[0]; + let ident = path.segments[0].identifier; match self.resolve_bare_identifier_pattern(ident) { FoundStructOrEnumVariant(def) @@ -4321,7 +4360,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map(|seg| seg.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4345,7 +4386,7 @@ impl Resolver { path.span, fmt!("`%s` is not an enum variant or constant", self.session.str_of( - *path.idents.last()))); + path.segments.last().identifier))) } None => { self.session.span_err(path.span, @@ -4354,7 +4395,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map(|s| s.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4372,8 +4415,10 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` is not an enum variant, struct or const", - self.session.str_of( - *path.idents.last()))); + self.session + .str_of(path.segments + .last() + .identifier))); } None => { self.session.span_err(path.span, @@ -4383,7 +4428,9 @@ impl Resolver { } // Check the types in the path pattern. - for ty in path.types.iter() { + for ty in path.segments + .iter() + .flat_map(|s| s.types.iter()) { self.resolve_type(ty, visitor); } } @@ -4418,7 +4465,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); + self.path_idents_to_str(path))); } } } @@ -4480,7 +4527,7 @@ impl Resolver { visitor: ResolveVisitor) -> Option { // First, resolve the types. - for ty in path.types.iter() { + for ty in path.segments.iter().flat_map(|s| s.types.iter()) { self.resolve_type(ty, visitor); } @@ -4490,20 +4537,27 @@ impl Resolver { namespace); } - let unqualified_def = self.resolve_identifier( - *path.idents.last(), namespace, check_ribs, path.span); + let unqualified_def = self.resolve_identifier(path.segments + .last() + .identifier, + namespace, + check_ribs, + path.span); - if path.idents.len() > 1 { - let def = self.resolve_module_relative_path( - path, self.xray_context, namespace); + if path.segments.len() > 1 { + let def = self.resolve_module_relative_path(path, + self.xray_context, + namespace); match (def, unqualified_def) { (Some(d), Some(ud)) if d == ud => { self.session.add_lint(unnecessary_qualification, - id, path.span, + id, + path.span, ~"unnecessary qualification"); } _ => () } + return def; } @@ -4610,12 +4664,12 @@ impl Resolver { pub fn intern_module_part_of_path(@mut self, path: &Path) -> ~[ident] { let mut module_path_idents = ~[]; - for (index, ident) in path.idents.iter().enumerate() { - if index == path.idents.len() - 1 { + for (index, segment) in path.segments.iter().enumerate() { + if index == path.segments.len() - 1 { break; } - module_path_idents.push(*ident); + module_path_idents.push(segment.identifier); } return module_path_idents; @@ -4651,7 +4705,7 @@ impl Resolver { } } - let name = *path.idents.last(); + let name = path.segments.last().identifier; let def = match self.resolve_definition_of_name_in_module(containing_module, name, namespace, @@ -4719,7 +4773,7 @@ impl Resolver { } } - let name = *path.idents.last(); + let name = path.segments.last().identifier; match self.resolve_definition_of_name_in_module(containing_module, name, namespace, @@ -4922,7 +4976,7 @@ impl Resolver { Some(def) => { // Write the result into the def map. debug!("(resolving expr) resolved `%s`", - self.idents_to_str(path.idents)); + self.path_idents_to_str(path)); // First-class methods are not supported yet; error // out here. @@ -4942,8 +4996,7 @@ impl Resolver { self.record_def(expr.id, def); } None => { - let wrong_name = self.idents_to_str( - path.idents); + let wrong_name = self.path_idents_to_str(path); if self.name_exists_in_scope_struct(wrong_name) { self.session.span_err(expr.span, fmt!("unresolved name `%s`. \ @@ -5001,7 +5054,7 @@ impl Resolver { self.session.span_err( path.span, fmt!("`%s` does not name a structure", - self.idents_to_str(path.idents))); + self.path_idents_to_str(path))); } } diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 4caaf38487351..09ed98140f7d6 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -114,10 +114,13 @@ pub fn trans(bcx: @mut Block, expr: @ast::expr) -> Callee { fn trans_def(bcx: @mut Block, def: ast::def, ref_expr: @ast::expr) -> Callee { match def { - ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { + ast::def_fn(did, _) | + ast::def_static_method(did, ast::FromImpl(_), _) => { fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id)) } - ast::def_static_method(impl_did, Some(trait_did), _) => { + ast::def_static_method(impl_did, + ast::FromTrait(trait_did), + _) => { fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, trait_did, ref_expr.id)) diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 87d26fa5ba07c..771decb4e6c1b 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -559,7 +559,9 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef { v } ast::expr_path(ref pth) => { - assert_eq!(pth.types.len(), 0); + // Assert that there are no type parameters in this path. + assert!(pth.segments.iter().all(|seg| seg.types.is_empty())); + let tcx = cx.tcx; match tcx.def_map.find(&e.id) { Some(&ast::def_fn(def_id, _purity)) => { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 04fd477a31738..fca04cfa6fe63 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -821,12 +821,14 @@ fn trans_def_datum_unadjusted(bcx: @mut Block, let _icx = push_ctxt("trans_def_datum_unadjusted"); match def { - ast::def_fn(did, _) | ast::def_static_method(did, None, _) => { + ast::def_fn(did, _) | + ast::def_static_method(did, ast::FromImpl(_), _) => { let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id); return fn_data_to_datum(bcx, ref_expr, did, fn_data); } - ast::def_static_method(impl_did, Some(trait_did), _) => { - let fn_data = meth::trans_static_method_callee(bcx, impl_did, + ast::def_static_method(impl_did, ast::FromTrait(trait_did), _) => { + let fn_data = meth::trans_static_method_callee(bcx, + impl_did, trait_did, ref_expr.id); return fn_data_to_datum(bcx, ref_expr, impl_did, fn_data); diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index c666e98c9c15f..735e9a8a37f4d 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -63,7 +63,6 @@ use middle::typeck::rscope::RegionParamNames; use middle::typeck::lookup_def_tcx; use std::result; -use std::vec; use syntax::abi::AbiSet; use syntax::{ast, ast_util}; use syntax::codemap::span; @@ -150,7 +149,8 @@ fn ast_path_substs( // If the type is parameterized by the this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). - let regions = match (&decl_generics.region_param, &path.rp) { + let regions = match (&decl_generics.region_param, + &path.segments.last().lifetime) { (&None, &None) => { opt_vec::Empty } @@ -169,20 +169,34 @@ fn ast_path_substs( } (&Some(_), &Some(_)) => { opt_vec::with( - ast_region_to_region(this, rscope, path.span, &path.rp)) + ast_region_to_region(this, + rscope, + path.span, + &path.segments.last().lifetime)) } }; // Convert the type parameters supplied by the user. - if !vec::same_length(*decl_generics.type_param_defs, path.types) { + let supplied_type_parameter_count = + path.segments.iter().flat_map(|s| s.types.iter()).len(); + if decl_generics.type_param_defs.len() != supplied_type_parameter_count { this.tcx().sess.span_fatal( path.span, fmt!("wrong number of type arguments: expected %u but found %u", - decl_generics.type_param_defs.len(), path.types.len())); + decl_generics.type_param_defs.len(), + supplied_type_parameter_count)); + } + let tps = path.segments + .iter() + .flat_map(|s| s.types.iter()) + .map(|a_t| ast_ty_to_ty(this, rscope, a_t)) + .collect(); + + substs { + regions: ty::NonerasedRegions(regions), + self_ty: self_ty, + tps: tps } - let tps = path.types.map(|a_t| ast_ty_to_ty(this, rscope, a_t)); - - substs {regions:ty::NonerasedRegions(regions), self_ty:self_ty, tps:tps} } pub fn ast_path_to_substs_and_ty( match a_seq_ty.ty.node { ast::ty_vec(ref mt) => { let mut mt = ast_mt_to_mt(this, rscope, mt); - if a_seq_ty.mutbl == ast::m_mutbl || - a_seq_ty.mutbl == ast::m_const { + if a_seq_ty.mutbl == ast::m_mutbl { mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl }; } return ty::mk_evec(tcx, mt, vst); @@ -326,7 +339,7 @@ pub fn ast_ty_to_ty( path: &ast::Path, flags: uint) { if (flags & NO_TPS) != 0u { - if path.types.len() > 0u { + if !path.segments.iter().all(|s| s.types.is_empty()) { tcx.sess.span_err( path.span, "type parameters are not allowed on this type"); @@ -334,7 +347,7 @@ pub fn ast_ty_to_ty( } if (flags & NO_REGIONS) != 0u { - if path.rp.is_some() { + if path.segments.last().lifetime.is_some() { tcx.sess.span_err( path.span, "region parameters are not allowed on this type"); diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index b7114e602830f..628ceccd61e7e 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -128,7 +128,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path, Some((enm, var)) => { // Assign the pattern the type of the *enum*, not the variant. let enum_tpt = ty::lookup_item_type(tcx, enm); - instantiate_path(pcx.fcx, path, enum_tpt, pat.span, pat.id); + instantiate_path(pcx.fcx, + path, + enum_tpt, + v_def, + pat.span, + pat.id); // check that the type of the value being matched is a subtype // of the type of the pattern: @@ -185,7 +190,12 @@ pub fn check_pat_variant(pcx: &pat_ctxt, pat: @ast::pat, path: &ast::Path, } else { ctor_tpt }; - instantiate_path(pcx.fcx, path, struct_tpt, pat.span, pat.id); + instantiate_path(pcx.fcx, + path, + struct_tpt, + s_def, + pat.span, + pat.id); // Check that the type of the value being matched is a subtype of // the type of the pattern. diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 352836d81e459..84f238496c2ff 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -102,7 +102,7 @@ use std::vec; use extra::list::Nil; use syntax::ast::{def_id, sty_value, sty_region, sty_box}; use syntax::ast::{sty_uniq, sty_static, NodeId}; -use syntax::ast::{m_const, m_mutbl, m_imm}; +use syntax::ast::{m_mutbl, m_imm}; use syntax::ast; use syntax::ast_map; @@ -653,7 +653,7 @@ impl<'self> LookupContext<'self> { ty_evec(mt, vstore_fixed(_)) => { // First try to borrow to a slice let entry = self.search_for_some_kind_of_autorefd_method( - AutoBorrowVec, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVec, autoderefs, [m_imm, m_mutbl], |m,r| ty::mk_evec(tcx, ty::mt {ty:mt.ty, mutbl:m}, vstore_slice(r))); @@ -662,7 +662,7 @@ impl<'self> LookupContext<'self> { // Then try to borrow to a slice *and* borrow a pointer. self.search_for_some_kind_of_autorefd_method( - AutoBorrowVecRef, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowVecRef, autoderefs, [m_imm, m_mutbl], |m,r| { let slice_ty = ty::mk_evec(tcx, ty::mt {ty:mt.ty, mutbl:m}, @@ -697,7 +697,7 @@ impl<'self> LookupContext<'self> { // Coerce ~/@/&Trait instances to &Trait. self.search_for_some_kind_of_autorefd_method( - AutoBorrowObj, autoderefs, [m_const, m_imm, m_mutbl], + AutoBorrowObj, autoderefs, [m_imm, m_mutbl], |trt_mut, reg| { ty::mk_trait(tcx, trt_did, trt_substs.clone(), RegionTraitStore(reg), trt_mut, b) @@ -732,7 +732,7 @@ impl<'self> LookupContext<'self> { ty_float(*) | ty_enum(*) | ty_ptr(*) | ty_struct(*) | ty_tup(*) | ty_estr(*) | ty_evec(*) | ty_trait(*) | ty_closure(*) => { self.search_for_some_kind_of_autorefd_method( - AutoPtr, autoderefs, [m_const, m_imm, m_mutbl], + AutoPtr, autoderefs, [m_imm, m_mutbl], |m,r| ty::mk_rptr(tcx, r, ty::mt {ty:self_ty, mutbl:m})) } @@ -1220,18 +1220,10 @@ impl<'self> LookupContext<'self> { } fn mutability_matches(self_mutbl: ast::mutability, - candidate_mutbl: ast::mutability) -> bool { + candidate_mutbl: ast::mutability) + -> bool { //! True if `self_mutbl <: candidate_mutbl` - - match (self_mutbl, candidate_mutbl) { - (_, m_const) => true, - (m_mutbl, m_mutbl) => true, - (m_imm, m_imm) => true, - (m_mutbl, m_imm) => false, - (m_imm, m_mutbl) => false, - (m_const, m_imm) => false, - (m_const, m_mutbl) => false, - } + self_mutbl == candidate_mutbl } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index a46ee330a8579..1063a5386b11f 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -490,7 +490,7 @@ pub fn check_fn(ccx: @mut CrateCtxt, if pat_util::pat_is_binding(fcx.ccx.tcx.def_map, p) => { assign(p.id, None); debug!("Pattern binding %s is assigned to %s", - tcx.sess.str_of(path.idents[0]), + tcx.sess.str_of(path.segments[0].identifier), fcx.infcx().ty_to_str( fcx.inh.locals.get_copy(&p.id))); } @@ -1135,8 +1135,160 @@ pub enum DerefArgs { DoDerefArgs } -pub fn break_here() { - debug!("break here!"); +// Given the provenance of a static method, returns the generics of the static +// method's container. +fn generics_of_static_method_container(type_context: ty::ctxt, + provenance: ast::MethodProvenance) + -> ty::Generics { + match provenance { + ast::FromTrait(trait_def_id) => { + ty::lookup_trait_def(type_context, trait_def_id).generics + } + ast::FromImpl(impl_def_id) => { + ty::lookup_item_type(type_context, impl_def_id).generics + } + } +} + +// Verifies that type parameters supplied in paths are in the right +// locations. +fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt, + path: &ast::Path, + def: ast::def) { + // We only care about checking the case in which the path has two or + // more segments. + if path.segments.len() < 2 { + return + } + + // Verify that no lifetimes or type parameters are present anywhere + // except the final two elements of the path. + for i in range(0, path.segments.len() - 2) { + match path.segments[i].lifetime { + None => {} + Some(lifetime) => { + function_context.tcx() + .sess + .span_err(lifetime.span, + "lifetime parameters may not \ + appear here") + } + } + + for typ in path.segments[i].types.iter() { + function_context.tcx() + .sess + .span_err(typ.span, + "type parameters may not appear here") + } + } + + // If there are no parameters at all, there is nothing more to do; the + // rest of typechecking will (attempt to) infer everything. + if path.segments + .iter() + .all(|s| s.lifetime.is_none() && s.types.is_empty()) { + return + } + + match def { + // If this is a static method of a trait or implementation, then + // ensure that the segment of the path which names the trait or + // implementation (the penultimate segment) is annotated with the + // right number of type parameters. + ast::def_static_method(_, provenance, _) => { + let generics = + generics_of_static_method_container(function_context.ccx.tcx, + provenance); + let name = match provenance { + ast::FromTrait(_) => "trait", + ast::FromImpl(_) => "impl", + }; + + let trait_segment = &path.segments[path.segments.len() - 2]; + + // Make sure lifetime parameterization agrees with the trait or + // implementation type. + match (generics.region_param, trait_segment.lifetime) { + (Some(_), None) => { + function_context.tcx() + .sess + .span_err(path.span, + fmt!("this %s has a lifetime \ + parameter but no \ + lifetime was specified", + name)) + } + (None, Some(_)) => { + function_context.tcx() + .sess + .span_err(path.span, + fmt!("this %s has no lifetime \ + parameter but a lifetime \ + was specified", + name)) + } + (Some(_), Some(_)) | (None, None) => {} + } + + // Make sure the number of type parameters supplied on the trait + // or implementation segment equals the number of type parameters + // on the trait or implementation definition. + let trait_type_parameter_count = generics.type_param_defs.len(); + let supplied_type_parameter_count = trait_segment.types.len(); + if trait_type_parameter_count != supplied_type_parameter_count { + let trait_count_suffix = if trait_type_parameter_count == 1 { + "" + } else { + "s" + }; + let supplied_count_suffix = + if supplied_type_parameter_count == 1 { + "" + } else { + "s" + }; + function_context.tcx() + .sess + .span_err(path.span, + fmt!("the %s referenced by this \ + path has %u type \ + parameter%s, but %u type \ + parameter%s were supplied", + name, + trait_type_parameter_count, + trait_count_suffix, + supplied_type_parameter_count, + supplied_count_suffix)) + } + } + _ => { + // Verify that no lifetimes or type parameters are present on + // the penultimate segment of the path. + let segment = &path.segments[path.segments.len() - 2]; + match segment.lifetime { + None => {} + Some(lifetime) => { + function_context.tcx() + .sess + .span_err(lifetime.span, + "lifetime parameters may not + appear here") + } + } + for typ in segment.types.iter() { + function_context.tcx() + .sess + .span_err(typ.span, + "type parameters may not appear \ + here"); + function_context.tcx() + .sess + .span_note(typ.span, + fmt!("this is a %?", def)); + } + } + } } /// Invariant: @@ -2336,8 +2488,9 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt, ast::expr_path(ref pth) => { let defn = lookup_def(fcx, pth.span, id); + check_type_parameter_positions_in_path(fcx, pth, defn); let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn); - instantiate_path(fcx, pth, tpt, expr.span, expr.id); + instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id); } ast::expr_self => { let definition = lookup_def(fcx, expr.span, id); @@ -3161,12 +3314,16 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @mut FnCtxt, pub fn instantiate_path(fcx: @mut FnCtxt, pth: &ast::Path, tpt: ty_param_bounds_and_ty, + def: ast::def, span: span, node_id: ast::NodeId) { debug!(">>> instantiate_path"); - let ty_param_count = tpt.generics.type_param_defs.len(); - let ty_substs_len = pth.types.len(); + let mut ty_param_count = tpt.generics.type_param_defs.len(); + let mut ty_substs_len = 0; + for segment in pth.segments.iter() { + ty_substs_len += segment.types.len() + } debug!("ty_param_count=%? ty_substs_len=%?", ty_param_count, @@ -3174,7 +3331,7 @@ pub fn instantiate_path(fcx: @mut FnCtxt, // determine the region bound, using the value given by the user // (if any) and otherwise using a fresh region variable - let regions = match pth.rp { + let regions = match pth.segments.last().lifetime { Some(_) => { // user supplied a lifetime parameter... match tpt.generics.region_param { None => { // ...but the type is not lifetime parameterized! @@ -3184,7 +3341,10 @@ pub fn instantiate_path(fcx: @mut FnCtxt, } Some(_) => { // ...and the type is lifetime parameterized, ok. opt_vec::with( - ast_region_to_region(fcx, fcx, span, &pth.rp)) + ast_region_to_region(fcx, + fcx, + span, + &pth.segments.last().lifetime)) } } } @@ -3193,6 +3353,21 @@ pub fn instantiate_path(fcx: @mut FnCtxt, } }; + // Special case: If there is a self parameter, omit it from the list of + // type parameters. + // + // Here we calculate the "user type parameter count", which is the number + // of type parameters actually manifest in the AST. This will differ from + // the internal type parameter count when there are self types involved. + let (user_type_parameter_count, self_parameter_index) = match def { + ast::def_static_method(_, provenance @ ast::FromTrait(_), _) => { + let generics = generics_of_static_method_container(fcx.ccx.tcx, + provenance); + (ty_param_count - 1, Some(generics.type_param_defs.len())) + } + _ => (ty_param_count, None), + }; + // determine values for type parameters, using the values given by // the user (if any) and otherwise using fresh type variables let tps = if ty_substs_len == 0 { @@ -3201,34 +3376,51 @@ pub fn instantiate_path(fcx: @mut FnCtxt, fcx.ccx.tcx.sess.span_err (span, "this item does not take type parameters"); fcx.infcx().next_ty_vars(ty_param_count) - } else if ty_substs_len > ty_param_count { + } else if ty_substs_len > user_type_parameter_count { fcx.ccx.tcx.sess.span_err (span, fmt!("too many type parameters provided: expected %u, found %u", - ty_param_count, ty_substs_len)); + user_type_parameter_count, ty_substs_len)); fcx.infcx().next_ty_vars(ty_param_count) - } else if ty_substs_len < ty_param_count { - let is_static_method = match fcx.ccx.tcx.def_map.find(&node_id) { - Some(&ast::def_static_method(*)) => true, - _ => false - }; + } else if ty_substs_len < user_type_parameter_count { fcx.ccx.tcx.sess.span_err (span, fmt!("not enough type parameters provided: expected %u, found %u", - ty_param_count, ty_substs_len)); - if is_static_method { - fcx.ccx.tcx.sess.span_note - (span, "Static methods have an extra implicit type parameter -- \ - did you omit the type parameter for the `Self` type?"); - } + user_type_parameter_count, ty_substs_len)); fcx.infcx().next_ty_vars(ty_param_count) } else { - pth.types.map(|aty| fcx.to_ty(aty)) + // Build up the list of type parameters, inserting the self parameter + // at the appropriate position. + let mut result = ~[]; + let mut pushed = false; + for (i, ast_type) in pth.segments + .iter() + .flat_map(|segment| segment.types.iter()) + .enumerate() { + match self_parameter_index { + Some(index) if index == i => { + result.push(fcx.infcx().next_ty_vars(1)[0]); + pushed = true; + } + _ => {} + } + result.push(fcx.to_ty(ast_type)) + } + + // If the self parameter goes at the end, insert it there. + if !pushed && self_parameter_index.is_some() { + result.push(fcx.infcx().next_ty_vars(1)[0]) + } + + assert_eq!(result.len(), ty_param_count) + result }; - let substs = substs {regions: ty::NonerasedRegions(regions), - self_ty: None, - tps: tps }; + let substs = substs { + regions: ty::NonerasedRegions(regions), + self_ty: None, + tps: tps + }; fcx.write_ty_substs(node_id, tpt.ty, substs); debug!("<<<"); diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index f05388344bc71..4b951d00677d6 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -22,7 +22,7 @@ use middle::typeck::infer::{TypeTrace, Subtype}; use middle::typeck::infer::fold_regions_in_sig; use middle::typeck::isr_alist; use syntax::ast; -use syntax::ast::{Many, Once, extern_fn, impure_fn, m_const, m_imm, m_mutbl}; +use syntax::ast::{Many, Once, extern_fn, impure_fn, m_imm, m_mutbl}; use syntax::ast::{unsafe_fn}; use syntax::ast::{Onceness, purity}; use syntax::abi::AbiSet; @@ -54,16 +54,6 @@ impl Combine for Glb { match (a.mutbl, b.mutbl) { // If one side or both is mut, then the GLB must use // the precise type from the mut side. - (m_mutbl, m_const) => { - Sub(**self).tys(a.ty, b.ty).chain(|_t| { - Ok(ty::mt {ty: a.ty, mutbl: m_mutbl}) - }) - } - (m_const, m_mutbl) => { - Sub(**self).tys(b.ty, a.ty).chain(|_t| { - Ok(ty::mt {ty: b.ty, mutbl: m_mutbl}) - }) - } (m_mutbl, m_mutbl) => { eq_tys(self, a.ty, b.ty).then(|| { Ok(ty::mt {ty: a.ty, mutbl: m_mutbl}) @@ -72,22 +62,12 @@ impl Combine for Glb { // If one side or both is immutable, we can use the GLB of // both sides but mutbl must be `m_imm`. - (m_imm, m_const) | - (m_const, m_imm) | (m_imm, m_imm) => { self.tys(a.ty, b.ty).chain(|t| { Ok(ty::mt {ty: t, mutbl: m_imm}) }) } - // If both sides are const, then we can use GLB of both - // sides and mutbl of only `m_const`. - (m_const, m_const) => { - self.tys(a.ty, b.ty).chain(|t| { - Ok(ty::mt {ty: t, mutbl: m_const}) - }) - } - // There is no mutual subtype of these combinations. (m_mutbl, m_imm) | (m_imm, m_mutbl) => { diff --git a/src/librustc/middle/typeck/infer/lub.rs b/src/librustc/middle/typeck/infer/lub.rs index 8afb5a18d4f6f..c97b99aaf0c08 100644 --- a/src/librustc/middle/typeck/infer/lub.rs +++ b/src/librustc/middle/typeck/infer/lub.rs @@ -26,7 +26,7 @@ use util::ppaux::mt_to_str; use extra::list; use syntax::abi::AbiSet; use syntax::ast; -use syntax::ast::{Many, Once, extern_fn, m_const, impure_fn}; +use syntax::ast::{Many, Once, extern_fn, impure_fn}; use syntax::ast::{unsafe_fn}; use syntax::ast::{Onceness, purity}; @@ -57,14 +57,13 @@ impl Combine for Lub { mt_to_str(tcx, a), mt_to_str(tcx, b)); - let m = if a.mutbl == b.mutbl { - a.mutbl - } else { - m_const - }; + if a.mutbl != b.mutbl { + return Err(ty::terr_mutability) + } + let m = a.mutbl; match m { - m_imm | m_const => { + m_imm => { self.tys(a.ty, b.ty).chain(|t| Ok(ty::mt {ty: t, mutbl: m}) ) } @@ -73,11 +72,7 @@ impl Combine for Lub { eq_tys(self, a.ty, b.ty).then(|| { Ok(ty::mt {ty: a.ty, mutbl: m}) }) - }).chain_err(|_e| { - self.tys(a.ty, b.ty).chain(|t| { - Ok(ty::mt {ty: t, mutbl: m_const}) - }) - }) + }).chain_err(|e| Err(e)) } } } diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 441e71d4722b8..3a4d7df6a5b93 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -28,7 +28,7 @@ use extra::list::Nil; use extra::list; use syntax::abi::AbiSet; use syntax::ast; -use syntax::ast::{Onceness, m_const, purity}; +use syntax::ast::{Onceness, purity}; pub struct Sub(CombineFields); // "subtype", "subregion" etc @@ -69,7 +69,7 @@ impl Combine for Sub { fn mts(&self, a: &ty::mt, b: &ty::mt) -> cres { debug!("mts(%s <: %s)", a.inf_str(self.infcx), b.inf_str(self.infcx)); - if a.mutbl != b.mutbl && b.mutbl != m_const { + if a.mutbl != b.mutbl { return Err(ty::terr_mutability); } @@ -79,7 +79,7 @@ impl Combine for Sub { // (i.e., invariant if mut): eq_tys(self, a.ty, b.ty).then(|| Ok(*a)) } - m_imm | m_const => { + m_imm => { // Otherwise we can be covariant: self.tys(a.ty, b.ty).chain(|_t| Ok(*a) ) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 3bc0a7167e9bd..7002e1a0858b1 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -239,7 +239,6 @@ fn mutability_to_str(m: ast::mutability) -> ~str { match m { ast::m_mutbl => ~"mut ", ast::m_imm => ~"", - ast::m_const => ~"const " } } diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 31de7bf82f827..6c574aceee0ba 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -278,7 +278,7 @@ pub mod raw { use rt::local::Local; use rt::task::Task; - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { task.heap.realloc(ptr as *libc::c_void, size) as *() } } diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs index 9d1d6e65901ae..7512dd3457a3a 100644 --- a/src/libstd/cast.rs +++ b/src/libstd/cast.rs @@ -10,6 +10,7 @@ //! Unsafe casting functions +use ptr::RawPtr; use sys; use unstable::intrinsics; @@ -91,13 +92,13 @@ pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T { /// Coerce an immutable reference to be mutable. #[inline] -pub unsafe fn transmute_mut_unsafe(ptr: *const T) -> *mut T { +pub unsafe fn transmute_mut_unsafe>(ptr: P) -> *mut T { transmute(ptr) } /// Coerce an immutable reference to be mutable. #[inline] -pub unsafe fn transmute_immut_unsafe(ptr: *const T) -> *T { +pub unsafe fn transmute_immut_unsafe>(ptr: P) -> *T { transmute(ptr) } diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs index 372effad61d3c..918731073ba8c 100644 --- a/src/libstd/cell.rs +++ b/src/libstd/cell.rs @@ -95,7 +95,7 @@ fn test_basic() { #[should_fail] #[ignore(cfg(windows))] fn test_take_empty() { - let value_cell = Cell::new_empty::<~int>(); + let value_cell: Cell<~int> = Cell::new_empty(); value_cell.take(); } diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index 7c2348a3533df..b8be0927664e8 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -11,7 +11,7 @@ #[doc(hidden)]; use libc::c_void; -use ptr::{mut_null}; +use ptr::null; use unstable::intrinsics::TyDesc; use unstable::raw; @@ -37,7 +37,7 @@ unsafe fn each_live_alloc(read_next_before: bool, use rt::local_heap; let mut box = local_heap::live_allocs(); - while box != mut_null() { + while box != null() { let next_before = (*box).next; let uniq = (*box).ref_count == managed::RC_MANAGED_UNIQUE; diff --git a/src/libstd/fmt/mod.rs b/src/libstd/fmt/mod.rs index 70ec5d9319984..6d30bf87b7121 100644 --- a/src/libstd/fmt/mod.rs +++ b/src/libstd/fmt/mod.rs @@ -844,10 +844,17 @@ impl Poly for T { } } -// n.b. use 'const' to get an implementation for both '*mut' and '*' at the same -// time. -impl Pointer for *const T { - fn fmt(t: &*const T, f: &mut Formatter) { +impl Pointer for *T { + fn fmt(t: &*T, f: &mut Formatter) { + f.flags |= 1 << (parse::FlagAlternate as uint); + do ::uint::to_str_bytes(*t as uint, 16) |buf| { + f.pad_integral(buf, "0x", true); + } + } +} + +impl Pointer for *mut T { + fn fmt(t: &*mut T, f: &mut Formatter) { f.flags |= 1 << (parse::FlagAlternate as uint); do ::uint::to_str_bytes(*t as uint, 16) |buf| { f.pad_integral(buf, "0x", true); diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs index 50e59cf438d0c..bcd658ece6653 100644 --- a/src/libstd/hashmap.rs +++ b/src/libstd/hashmap.rs @@ -869,21 +869,21 @@ mod test_map { #[test] fn test_find_or_insert() { - let mut m = HashMap::new::(); + let mut m: HashMap = HashMap::new(); assert_eq!(*m.find_or_insert(1, 2), 2); assert_eq!(*m.find_or_insert(1, 3), 2); } #[test] fn test_find_or_insert_with() { - let mut m = HashMap::new::(); + let mut m: HashMap = HashMap::new(); assert_eq!(*m.find_or_insert_with(1, |_| 2), 2); assert_eq!(*m.find_or_insert_with(1, |_| 3), 2); } #[test] fn test_insert_or_update_with() { - let mut m = HashMap::new::(); + let mut m: HashMap = HashMap::new(); assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 2); assert_eq!(*m.insert_or_update_with(1, 2, |_,x| *x+=1), 3); } diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs index 34bbe9292a5cb..e8558e6b1f01d 100644 --- a/src/libstd/iterator.rs +++ b/src/libstd/iterator.rs @@ -637,7 +637,10 @@ pub trait AdditiveIterator { impl + Zero, T: Iterator> AdditiveIterator for T { #[inline] - fn sum(&mut self) -> A { self.fold(Zero::zero::(), |s, x| s + x) } + fn sum(&mut self) -> A { + let zero: A = Zero::zero(); + self.fold(zero, |s, x| s + x) + } } /// A trait for iterators over elements whose elements can be multiplied @@ -662,7 +665,10 @@ pub trait MultiplicativeIterator { impl + One, T: Iterator> MultiplicativeIterator for T { #[inline] - fn product(&mut self) -> A { self.fold(One::one::(), |p, x| p * x) } + fn product(&mut self) -> A { + let one: A = One::one(); + self.fold(one, |p, x| p * x) + } } /// A trait for iterators over elements which can be compared to one another. diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs index 7de55f48317a5..215067ea72919 100644 --- a/src/libstd/logging.rs +++ b/src/libstd/logging.rs @@ -59,7 +59,8 @@ fn newsched_log_str(msg: ~str) { use rt::local::Local; unsafe { - match Local::try_unsafe_borrow::() { + let optional_task: Option<*mut Task> = Local::try_unsafe_borrow(); + match optional_task { Some(local) => { // Use the available logger (*local).logger.log(Left(msg)); diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index faf9b2e2390dc..9d7a5ca15d01c 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -182,7 +182,7 @@ impl ApproxEq for f32 { #[inline] fn approx_eq(&self, other: &f32) -> bool { - self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) + self.approx_eq_eps(other, &1.0e-6) } #[inline] @@ -561,11 +561,14 @@ impl Real for f32 { /// Converts to degrees, assuming the number is in radians #[inline] - fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::()) } + fn to_degrees(&self) -> f32 { *self * (180.0f32 / Real::pi()) } /// Converts to radians, assuming the number is in degrees #[inline] - fn to_radians(&self) -> f32 { *self * (Real::pi::() / 180.0) } + fn to_radians(&self) -> f32 { + let value: f32 = Real::pi(); + *self * (value / 180.0f32) + } } impl Bounded for f32 { @@ -578,10 +581,10 @@ impl Bounded for f32 { impl Primitive for f32 { #[inline] - fn bits() -> uint { 32 } + fn bits(_: Option) -> uint { 32 } #[inline] - fn bytes() -> uint { Primitive::bits::() / 8 } + fn bytes(_: Option) -> uint { Primitive::bits(Some(0f32)) / 8 } } impl Float for f32 { @@ -638,25 +641,25 @@ impl Float for f32 { } #[inline] - fn mantissa_digits() -> uint { 24 } + fn mantissa_digits(_: Option) -> uint { 24 } #[inline] - fn digits() -> uint { 6 } + fn digits(_: Option) -> uint { 6 } #[inline] fn epsilon() -> f32 { 1.19209290e-07 } #[inline] - fn min_exp() -> int { -125 } + fn min_exp(_: Option) -> int { -125 } #[inline] - fn max_exp() -> int { 128 } + fn max_exp(_: Option) -> int { 128 } #[inline] - fn min_10_exp() -> int { -37 } + fn min_10_exp(_: Option) -> int { -37 } #[inline] - fn max_10_exp() -> int { 38 } + fn max_10_exp(_: Option) -> int { 38 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` #[inline] @@ -956,9 +959,11 @@ mod tests { assert_eq!(1f32.clamp(&2f32, &4f32), 2f32); assert_eq!(8f32.clamp(&2f32, &4f32), 4f32); assert_eq!(3f32.clamp(&2f32, &4f32), 3f32); - assert!(3f32.clamp(&Float::NaN::(), &4f32).is_NaN()); - assert!(3f32.clamp(&2f32, &Float::NaN::()).is_NaN()); - assert!(Float::NaN::().clamp(&2f32, &4f32).is_NaN()); + + let nan: f32 = Float::NaN(); + assert!(3f32.clamp(&nan, &4f32).is_NaN()); + assert!(3f32.clamp(&2f32, &nan).is_NaN()); + assert!(nan.clamp(&2f32, &4f32).is_NaN()); } #[test] @@ -1035,9 +1040,13 @@ mod tests { fn test_asinh() { assert_eq!(0.0f32.asinh(), 0.0f32); assert_eq!((-0.0f32).asinh(), -0.0f32); - assert_eq!(Float::infinity::().asinh(), Float::infinity::()); - assert_eq!(Float::neg_infinity::().asinh(), Float::neg_infinity::()); - assert!(Float::NaN::().asinh().is_NaN()); + + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::NaN(); + assert_eq!(inf.asinh(), inf); + assert_eq!(neg_inf.asinh(), neg_inf); + assert!(nan.asinh().is_NaN()); assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32); assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32); } @@ -1046,9 +1055,13 @@ mod tests { fn test_acosh() { assert_eq!(1.0f32.acosh(), 0.0f32); assert!(0.999f32.acosh().is_NaN()); - assert_eq!(Float::infinity::().acosh(), Float::infinity::()); - assert!(Float::neg_infinity::().acosh().is_NaN()); - assert!(Float::NaN::().acosh().is_NaN()); + + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::NaN(); + assert_eq!(inf.acosh(), inf); + assert!(neg_inf.acosh().is_NaN()); + assert!(nan.acosh().is_NaN()); assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32); assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32); } @@ -1057,34 +1070,61 @@ mod tests { fn test_atanh() { assert_eq!(0.0f32.atanh(), 0.0f32); assert_eq!((-0.0f32).atanh(), -0.0f32); - assert_eq!(1.0f32.atanh(), Float::infinity::()); - assert_eq!((-1.0f32).atanh(), Float::neg_infinity::()); + + let inf32: f32 = Float::infinity(); + let neg_inf32: f32 = Float::neg_infinity(); + assert_eq!(1.0f32.atanh(), inf32); + assert_eq!((-1.0f32).atanh(), neg_inf32); + assert!(2f64.atanh().atanh().is_NaN()); assert!((-2f64).atanh().atanh().is_NaN()); - assert!(Float::infinity::().atanh().is_NaN()); - assert!(Float::neg_infinity::().atanh().is_NaN()); - assert!(Float::NaN::().atanh().is_NaN()); + + let inf64: f32 = Float::infinity(); + let neg_inf64: f32 = Float::neg_infinity(); + let nan32: f32 = Float::NaN(); + assert!(inf64.atanh().is_NaN()); + assert!(neg_inf64.atanh().is_NaN()); + assert!(nan32.atanh().is_NaN()); + assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32); assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32); } #[test] fn test_real_consts() { - assert_approx_eq!(Real::two_pi::(), 2f32 * Real::pi::()); - assert_approx_eq!(Real::frac_pi_2::(), Real::pi::() / 2f32); - assert_approx_eq!(Real::frac_pi_3::(), Real::pi::() / 3f32); - assert_approx_eq!(Real::frac_pi_4::(), Real::pi::() / 4f32); - assert_approx_eq!(Real::frac_pi_6::(), Real::pi::() / 6f32); - assert_approx_eq!(Real::frac_pi_8::(), Real::pi::() / 8f32); - assert_approx_eq!(Real::frac_1_pi::(), 1f32 / Real::pi::()); - assert_approx_eq!(Real::frac_2_pi::(), 2f32 / Real::pi::()); - assert_approx_eq!(Real::frac_2_sqrtpi::(), 2f32 / Real::pi::().sqrt()); - assert_approx_eq!(Real::sqrt2::(), 2f32.sqrt()); - assert_approx_eq!(Real::frac_1_sqrt2::(), 1f32 / 2f32.sqrt()); - assert_approx_eq!(Real::log2_e::(), Real::e::().log2()); - assert_approx_eq!(Real::log10_e::(), Real::e::().log10()); - assert_approx_eq!(Real::ln_2::(), 2f32.ln()); - assert_approx_eq!(Real::ln_10::(), 10f32.ln()); + let pi: f32 = Real::pi(); + let two_pi: f32 = Real::two_pi(); + let frac_pi_2: f32 = Real::frac_pi_2(); + let frac_pi_3: f32 = Real::frac_pi_3(); + let frac_pi_4: f32 = Real::frac_pi_4(); + let frac_pi_6: f32 = Real::frac_pi_6(); + let frac_pi_8: f32 = Real::frac_pi_8(); + let frac_1_pi: f32 = Real::frac_1_pi(); + let frac_2_pi: f32 = Real::frac_2_pi(); + let frac_2_sqrtpi: f32 = Real::frac_2_sqrtpi(); + let sqrt2: f32 = Real::sqrt2(); + let frac_1_sqrt2: f32 = Real::frac_1_sqrt2(); + let e: f32 = Real::e(); + let log2_e: f32 = Real::log2_e(); + let log10_e: f32 = Real::log10_e(); + let ln_2: f32 = Real::ln_2(); + let ln_10: f32 = Real::ln_10(); + + assert_approx_eq!(two_pi, 2f32 * pi); + assert_approx_eq!(frac_pi_2, pi / 2f32); + assert_approx_eq!(frac_pi_3, pi / 3f32); + assert_approx_eq!(frac_pi_4, pi / 4f32); + assert_approx_eq!(frac_pi_6, pi / 6f32); + assert_approx_eq!(frac_pi_8, pi / 8f32); + assert_approx_eq!(frac_1_pi, 1f32 / pi); + assert_approx_eq!(frac_2_pi, 2f32 / pi); + assert_approx_eq!(frac_2_sqrtpi, 2f32 / pi.sqrt()); + assert_approx_eq!(sqrt2, 2f32.sqrt()); + assert_approx_eq!(frac_1_sqrt2, 1f32 / 2f32.sqrt()); + assert_approx_eq!(log2_e, e.log2()); + assert_approx_eq!(log10_e, e.log10()); + assert_approx_eq!(ln_2, 2f32.ln()); + assert_approx_eq!(ln_10, 10f32.ln()); } #[test] @@ -1160,17 +1200,23 @@ mod tests { #[test] fn test_primitive() { - assert_eq!(Primitive::bits::(), sys::size_of::() * 8); - assert_eq!(Primitive::bytes::(), sys::size_of::()); + let none: Option = None; + assert_eq!(Primitive::bits(none), sys::size_of::() * 8); + assert_eq!(Primitive::bytes(none), sys::size_of::()); } #[test] fn test_is_normal() { - assert!(!Float::NaN::().is_normal()); - assert!(!Float::infinity::().is_normal()); - assert!(!Float::neg_infinity::().is_normal()); - assert!(!Zero::zero::().is_normal()); - assert!(!Float::neg_zero::().is_normal()); + let nan: f32 = Float::NaN(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let zero: f32 = Zero::zero(); + let neg_zero: f32 = Float::neg_zero(); + assert!(!nan.is_normal()); + assert!(!inf.is_normal()); + assert!(!neg_inf.is_normal()); + assert!(!zero.is_normal()); + assert!(!neg_zero.is_normal()); assert!(1f32.is_normal()); assert!(1e-37f32.is_normal()); assert!(!1e-38f32.is_normal()); @@ -1178,11 +1224,16 @@ mod tests { #[test] fn test_classify() { - assert_eq!(Float::NaN::().classify(), FPNaN); - assert_eq!(Float::infinity::().classify(), FPInfinite); - assert_eq!(Float::neg_infinity::().classify(), FPInfinite); - assert_eq!(Zero::zero::().classify(), FPZero); - assert_eq!(Float::neg_zero::().classify(), FPZero); + let nan: f32 = Float::NaN(); + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let zero: f32 = Zero::zero(); + let neg_zero: f32 = Float::neg_zero(); + assert_eq!(nan.classify(), FPNaN); + assert_eq!(inf.classify(), FPInfinite); + assert_eq!(neg_inf.classify(), FPInfinite); + assert_eq!(zero.classify(), FPZero); + assert_eq!(neg_zero.classify(), FPZero); assert_eq!(1f32.classify(), FPNormal); assert_eq!(1e-37f32.classify(), FPNormal); assert_eq!(1e-38f32.classify(), FPSubnormal); @@ -1199,11 +1250,13 @@ mod tests { assert_eq!(Float::ldexp(0f32, -123), 0f32); assert_eq!(Float::ldexp(-0f32, -123), -0f32); - assert_eq!(Float::ldexp(Float::infinity::(), -123), - Float::infinity::()); - assert_eq!(Float::ldexp(Float::neg_infinity::(), -123), - Float::neg_infinity::()); - assert!(Float::ldexp(Float::NaN::(), -123).is_NaN()); + + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::NaN(); + assert_eq!(Float::ldexp(inf, -123), inf); + assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); + assert!(Float::ldexp(nan, -123).is_NaN()); } #[test] @@ -1221,10 +1274,12 @@ mod tests { assert_eq!(0f32.frexp(), (0f32, 0)); assert_eq!((-0f32).frexp(), (-0f32, 0)); - assert_eq!(match Float::infinity::().frexp() { (x, _) => x }, - Float::infinity::()) - assert_eq!(match Float::neg_infinity::().frexp() { (x, _) => x }, - Float::neg_infinity::()) - assert!(match Float::NaN::().frexp() { (x, _) => x.is_NaN() }) + + let inf: f32 = Float::infinity(); + let neg_inf: f32 = Float::neg_infinity(); + let nan: f32 = Float::NaN(); + assert_eq!(match inf.frexp() { (x, _) => x }, inf) + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) + assert!(match nan.frexp() { (x, _) => x.is_NaN() }) } } diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 60527905779f0..34c8de780459c 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -205,7 +205,7 @@ impl ApproxEq for f64 { #[inline] fn approx_eq(&self, other: &f64) -> bool { - self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) + self.approx_eq_eps(other, &1.0e-6) } #[inline] @@ -578,11 +578,14 @@ impl Real for f64 { /// Converts to degrees, assuming the number is in radians #[inline] - fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::()) } + fn to_degrees(&self) -> f64 { *self * (180.0f64 / Real::pi()) } /// Converts to radians, assuming the number is in degrees #[inline] - fn to_radians(&self) -> f64 { *self * (Real::pi::() / 180.0) } + fn to_radians(&self) -> f64 { + let value: f64 = Real::pi(); + *self * (value / 180.0) + } } impl RealExt for f64 { @@ -625,10 +628,10 @@ impl Bounded for f64 { impl Primitive for f64 { #[inline] - fn bits() -> uint { 64 } + fn bits(_: Option) -> uint { 64 } #[inline] - fn bytes() -> uint { Primitive::bits::() / 8 } + fn bytes(_: Option) -> uint { Primitive::bits(Some(0f64)) / 8 } } impl Float for f64 { @@ -685,25 +688,25 @@ impl Float for f64 { } #[inline] - fn mantissa_digits() -> uint { 53 } + fn mantissa_digits(_: Option) -> uint { 53 } #[inline] - fn digits() -> uint { 15 } + fn digits(_: Option) -> uint { 15 } #[inline] fn epsilon() -> f64 { 2.2204460492503131e-16 } #[inline] - fn min_exp() -> int { -1021 } + fn min_exp(_: Option) -> int { -1021 } #[inline] - fn max_exp() -> int { 1024 } + fn max_exp(_: Option) -> int { 1024 } #[inline] - fn min_10_exp() -> int { -307 } + fn min_10_exp(_: Option) -> int { -307 } #[inline] - fn max_10_exp() -> int { 308 } + fn max_10_exp(_: Option) -> int { 308 } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` #[inline] @@ -990,16 +993,20 @@ mod tests { fn test_min() { assert_eq!(1f64.min(&2f64), 1f64); assert_eq!(2f64.min(&1f64), 1f64); - assert!(1f64.min(&Float::NaN::()).is_NaN()); - assert!(Float::NaN::().min(&1f64).is_NaN()); + + let nan: f64 = Float::NaN(); + assert!(1f64.min(&nan).is_NaN()); + assert!(nan.min(&1f64).is_NaN()); } #[test] fn test_max() { assert_eq!(1f64.max(&2f64), 2f64); assert_eq!(2f64.max(&1f64), 2f64); - assert!(1f64.max(&Float::NaN::()).is_NaN()); - assert!(Float::NaN::().max(&1f64).is_NaN()); + + let nan: f64 = Float::NaN(); + assert!(1f64.max(&nan).is_NaN()); + assert!(nan.max(&1f64).is_NaN()); } #[test] @@ -1007,9 +1014,11 @@ mod tests { assert_eq!(1f64.clamp(&2f64, &4f64), 2f64); assert_eq!(8f64.clamp(&2f64, &4f64), 4f64); assert_eq!(3f64.clamp(&2f64, &4f64), 3f64); - assert!(3f64.clamp(&Float::NaN::(), &4f64).is_NaN()); - assert!(3f64.clamp(&2f64, &Float::NaN::()).is_NaN()); - assert!(Float::NaN::().clamp(&2f64, &4f64).is_NaN()); + + let nan: f64 = Float::NaN(); + assert!(3f64.clamp(&nan, &4f64).is_NaN()); + assert!(3f64.clamp(&2f64, &nan).is_NaN()); + assert!(nan.clamp(&2f64, &4f64).is_NaN()); } #[test] @@ -1086,9 +1095,13 @@ mod tests { fn test_asinh() { assert_eq!(0.0f64.asinh(), 0.0f64); assert_eq!((-0.0f64).asinh(), -0.0f64); - assert_eq!(Float::infinity::().asinh(), Float::infinity::()); - assert_eq!(Float::neg_infinity::().asinh(), Float::neg_infinity::()); - assert!(Float::NaN::().asinh().is_NaN()); + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::NaN(); + assert_eq!(inf.asinh(), inf); + assert_eq!(neg_inf.asinh(), neg_inf); + assert!(nan.asinh().is_NaN()); assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64); assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64); } @@ -1097,9 +1110,13 @@ mod tests { fn test_acosh() { assert_eq!(1.0f64.acosh(), 0.0f64); assert!(0.999f64.acosh().is_NaN()); - assert_eq!(Float::infinity::().acosh(), Float::infinity::()); - assert!(Float::neg_infinity::().acosh().is_NaN()); - assert!(Float::NaN::().acosh().is_NaN()); + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::NaN(); + assert_eq!(inf.acosh(), inf); + assert!(neg_inf.acosh().is_NaN()); + assert!(nan.acosh().is_NaN()); assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64); assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64); } @@ -1108,34 +1125,56 @@ mod tests { fn test_atanh() { assert_eq!(0.0f64.atanh(), 0.0f64); assert_eq!((-0.0f64).atanh(), -0.0f64); - assert_eq!(1.0f64.atanh(), Float::infinity::()); - assert_eq!((-1.0f64).atanh(), Float::neg_infinity::()); + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::NaN(); + assert_eq!(1.0f64.atanh(), inf); + assert_eq!((-1.0f64).atanh(), neg_inf); assert!(2f64.atanh().atanh().is_NaN()); assert!((-2f64).atanh().atanh().is_NaN()); - assert!(Float::infinity::().atanh().is_NaN()); - assert!(Float::neg_infinity::().atanh().is_NaN()); - assert!(Float::NaN::().atanh().is_NaN()); + assert!(inf.atanh().is_NaN()); + assert!(neg_inf.atanh().is_NaN()); + assert!(nan.atanh().is_NaN()); assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64); assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64); } #[test] fn test_real_consts() { - assert_approx_eq!(Real::two_pi::(), 2.0 * Real::pi::()); - assert_approx_eq!(Real::frac_pi_2::(), Real::pi::() / 2f64); - assert_approx_eq!(Real::frac_pi_3::(), Real::pi::() / 3f64); - assert_approx_eq!(Real::frac_pi_4::(), Real::pi::() / 4f64); - assert_approx_eq!(Real::frac_pi_6::(), Real::pi::() / 6f64); - assert_approx_eq!(Real::frac_pi_8::(), Real::pi::() / 8f64); - assert_approx_eq!(Real::frac_1_pi::(), 1f64 / Real::pi::()); - assert_approx_eq!(Real::frac_2_pi::(), 2f64 / Real::pi::()); - assert_approx_eq!(Real::frac_2_sqrtpi::(), 2f64 / Real::pi::().sqrt()); - assert_approx_eq!(Real::sqrt2::(), 2f64.sqrt()); - assert_approx_eq!(Real::frac_1_sqrt2::(), 1f64 / 2f64.sqrt()); - assert_approx_eq!(Real::log2_e::(), Real::e::().log2()); - assert_approx_eq!(Real::log10_e::(), Real::e::().log10()); - assert_approx_eq!(Real::ln_2::(), 2f64.ln()); - assert_approx_eq!(Real::ln_10::(), 10f64.ln()); + let pi: f64 = Real::pi(); + let two_pi: f64 = Real::two_pi(); + let frac_pi_2: f64 = Real::frac_pi_2(); + let frac_pi_3: f64 = Real::frac_pi_3(); + let frac_pi_4: f64 = Real::frac_pi_4(); + let frac_pi_6: f64 = Real::frac_pi_6(); + let frac_pi_8: f64 = Real::frac_pi_8(); + let frac_1_pi: f64 = Real::frac_1_pi(); + let frac_2_pi: f64 = Real::frac_2_pi(); + let frac_2_sqrtpi: f64 = Real::frac_2_sqrtpi(); + let sqrt2: f64 = Real::sqrt2(); + let frac_1_sqrt2: f64 = Real::frac_1_sqrt2(); + let e: f64 = Real::e(); + let log2_e: f64 = Real::log2_e(); + let log10_e: f64 = Real::log10_e(); + let ln_2: f64 = Real::ln_2(); + let ln_10: f64 = Real::ln_10(); + + assert_approx_eq!(two_pi, 2.0 * pi); + assert_approx_eq!(frac_pi_2, pi / 2f64); + assert_approx_eq!(frac_pi_3, pi / 3f64); + assert_approx_eq!(frac_pi_4, pi / 4f64); + assert_approx_eq!(frac_pi_6, pi / 6f64); + assert_approx_eq!(frac_pi_8, pi / 8f64); + assert_approx_eq!(frac_1_pi, 1f64 / pi); + assert_approx_eq!(frac_2_pi, 2f64 / pi); + assert_approx_eq!(frac_2_sqrtpi, 2f64 / pi.sqrt()); + assert_approx_eq!(sqrt2, 2f64.sqrt()); + assert_approx_eq!(frac_1_sqrt2, 1f64 / 2f64.sqrt()); + assert_approx_eq!(log2_e, e.log2()); + assert_approx_eq!(log10_e, e.log10()); + assert_approx_eq!(ln_2, 2f64.ln()); + assert_approx_eq!(ln_10, 10f64.ln()); } #[test] @@ -1211,17 +1250,23 @@ mod tests { #[test] fn test_primitive() { - assert_eq!(Primitive::bits::(), sys::size_of::() * 8); - assert_eq!(Primitive::bytes::(), sys::size_of::()); + let none: Option = None; + assert_eq!(Primitive::bits(none), sys::size_of::() * 8); + assert_eq!(Primitive::bytes(none), sys::size_of::()); } #[test] fn test_is_normal() { - assert!(!Float::NaN::().is_normal()); - assert!(!Float::infinity::().is_normal()); - assert!(!Float::neg_infinity::().is_normal()); - assert!(!Zero::zero::().is_normal()); - assert!(!Float::neg_zero::().is_normal()); + let nan: f64 = Float::NaN(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let zero: f64 = Zero::zero(); + let neg_zero: f64 = Float::neg_zero(); + assert!(!nan.is_normal()); + assert!(!inf.is_normal()); + assert!(!neg_inf.is_normal()); + assert!(!zero.is_normal()); + assert!(!neg_zero.is_normal()); assert!(1f64.is_normal()); assert!(1e-307f64.is_normal()); assert!(!1e-308f64.is_normal()); @@ -1229,11 +1274,16 @@ mod tests { #[test] fn test_classify() { - assert_eq!(Float::NaN::().classify(), FPNaN); - assert_eq!(Float::infinity::().classify(), FPInfinite); - assert_eq!(Float::neg_infinity::().classify(), FPInfinite); - assert_eq!(Zero::zero::().classify(), FPZero); - assert_eq!(Float::neg_zero::().classify(), FPZero); + let nan: f64 = Float::NaN(); + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let zero: f64 = Zero::zero(); + let neg_zero: f64 = Float::neg_zero(); + assert_eq!(nan.classify(), FPNaN); + assert_eq!(inf.classify(), FPInfinite); + assert_eq!(neg_inf.classify(), FPInfinite); + assert_eq!(zero.classify(), FPZero); + assert_eq!(neg_zero.classify(), FPZero); assert_eq!(1e-307f64.classify(), FPNormal); assert_eq!(1e-308f64.classify(), FPSubnormal); } @@ -1249,11 +1299,13 @@ mod tests { assert_eq!(Float::ldexp(0f64, -123), 0f64); assert_eq!(Float::ldexp(-0f64, -123), -0f64); - assert_eq!(Float::ldexp(Float::infinity::(), -123), - Float::infinity::()); - assert_eq!(Float::ldexp(Float::neg_infinity::(), -123), - Float::neg_infinity::()); - assert!(Float::ldexp(Float::NaN::(), -123).is_NaN()); + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::NaN(); + assert_eq!(Float::ldexp(inf, -123), inf); + assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); + assert!(Float::ldexp(nan, -123).is_NaN()); } #[test] @@ -1271,10 +1323,12 @@ mod tests { assert_eq!(0f64.frexp(), (0f64, 0)); assert_eq!((-0f64).frexp(), (-0f64, 0)); - assert_eq!(match Float::infinity::().frexp() { (x, _) => x }, - Float::infinity::()) - assert_eq!(match Float::neg_infinity::().frexp() { (x, _) => x }, - Float::neg_infinity::()) - assert!(match Float::NaN::().frexp() { (x, _) => x.is_NaN() }) + + let inf: f64 = Float::infinity(); + let neg_inf: f64 = Float::neg_infinity(); + let nan: f64 = Float::NaN(); + assert_eq!(match inf.frexp() { (x, _) => x }, inf) + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf) + assert!(match nan.frexp() { (x, _) => x.is_NaN() }) } } diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs index 486d35620899a..360a37ccbd1a9 100644 --- a/src/libstd/num/float.rs +++ b/src/libstd/num/float.rs @@ -349,7 +349,7 @@ impl ApproxEq for float { #[inline] fn approx_eq(&self, other: &float) -> bool { - self.approx_eq_eps(other, &ApproxEq::approx_epsilon::()) + self.approx_eq_eps(other, &1.0e-6) } #[inline] @@ -790,32 +790,56 @@ impl Signed for float { impl Bounded for float { #[inline] - fn min_value() -> float { Bounded::min_value::() as float } + fn min_value() -> float { + let x: f64 = Bounded::min_value(); + x as float + } #[inline] - fn max_value() -> float { Bounded::max_value::() as float } + fn max_value() -> float { + let x: f64 = Bounded::max_value(); + x as float + } } impl Primitive for float { #[inline] - fn bits() -> uint { Primitive::bits::() } + fn bits(_: Option) -> uint { + let bits: uint = Primitive::bits(Some(0f64)); + bits + } #[inline] - fn bytes() -> uint { Primitive::bytes::() } + fn bytes(_: Option) -> uint { + let bytes: uint = Primitive::bytes(Some(0f64)); + bytes + } } impl Float for float { #[inline] - fn NaN() -> float { Float::NaN::() as float } + fn NaN() -> float { + let value: f64 = Float::NaN(); + value as float + } #[inline] - fn infinity() -> float { Float::infinity::() as float } + fn infinity() -> float { + let value: f64 = Float::infinity(); + value as float + } #[inline] - fn neg_infinity() -> float { Float::neg_infinity::() as float } + fn neg_infinity() -> float { + let value: f64 = Float::neg_infinity(); + value as float + } #[inline] - fn neg_zero() -> float { Float::neg_zero::() as float } + fn neg_zero() -> float { + let value: f64 = Float::neg_zero(); + value as float + } /// Returns `true` if the number is NaN #[inline] @@ -839,30 +863,46 @@ impl Float for float { fn classify(&self) -> FPCategory { (*self as f64).classify() } #[inline] - fn mantissa_digits() -> uint { Float::mantissa_digits::() } + fn mantissa_digits(_: Option) -> uint { + Float::mantissa_digits(Some(0f64)) + } #[inline] - fn digits() -> uint { Float::digits::() } + fn digits(_: Option) -> uint { + Float::digits(Some(0f64)) + } #[inline] - fn epsilon() -> float { Float::epsilon::() as float } + fn epsilon() -> float { + let value: f64 = Float::epsilon(); + value as float + } #[inline] - fn min_exp() -> int { Float::min_exp::() } + fn min_exp(_: Option) -> int { + Float::min_exp(Some(0f64)) + } #[inline] - fn max_exp() -> int { Float::max_exp::() } + fn max_exp(_: Option) -> int { + Float::max_exp(Some(0f64)) + } #[inline] - fn min_10_exp() -> int { Float::min_10_exp::() } + fn min_10_exp(_: Option) -> int { + Float::min_10_exp(Some(0f64)) + } #[inline] - fn max_10_exp() -> int { Float::max_10_exp::() } + fn max_10_exp(_: Option) -> int { + Float::max_10_exp(Some(0f64)) + } /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp` #[inline] fn ldexp(x: float, exp: int) -> float { - Float::ldexp(x as f64, exp) as float + let value: f64 = Float::ldexp(x as f64, exp); + value as float } /// @@ -944,9 +984,10 @@ mod tests { assert_eq!(1f.clamp(&2f, &4f), 2f); assert_eq!(8f.clamp(&2f, &4f), 4f); assert_eq!(3f.clamp(&2f, &4f), 3f); - assert!(3f.clamp(&Float::NaN::(), &4f).is_NaN()); - assert!(3f.clamp(&2f, &Float::NaN::()).is_NaN()); - assert!(Float::NaN::().clamp(&2f, &4f).is_NaN()); + let nan: float = Float::NaN(); + assert!(3f.clamp(&nan, &4f).is_NaN()); + assert!(3f.clamp(&2f, &nan).is_NaN()); + assert!(nan.clamp(&2f, &4f).is_NaN()); } #[test] @@ -1023,9 +1064,13 @@ mod tests { fn test_asinh() { assert_eq!(0.0f.asinh(), 0.0f); assert_eq!((-0.0f).asinh(), -0.0f); - assert_eq!(Float::infinity::().asinh(), Float::infinity::()); - assert_eq!(Float::neg_infinity::().asinh(), Float::neg_infinity::()); - assert!(Float::NaN::().asinh().is_NaN()); + + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let nan: float = Float::NaN(); + assert_eq!(inf.asinh(), inf); + assert_eq!(neg_inf.asinh(), neg_inf); + assert!(nan.asinh().is_NaN()); assert_approx_eq!(2.0f.asinh(), 1.443635475178810342493276740273105f); assert_approx_eq!((-2.0f).asinh(), -1.443635475178810342493276740273105f); } @@ -1034,9 +1079,13 @@ mod tests { fn test_acosh() { assert_eq!(1.0f.acosh(), 0.0f); assert!(0.999f.acosh().is_NaN()); - assert_eq!(Float::infinity::().acosh(), Float::infinity::()); - assert!(Float::neg_infinity::().acosh().is_NaN()); - assert!(Float::NaN::().acosh().is_NaN()); + + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let nan: float = Float::NaN(); + assert_eq!(inf.acosh(), inf); + assert!(neg_inf.acosh().is_NaN()); + assert!(nan.acosh().is_NaN()); assert_approx_eq!(2.0f.acosh(), 1.31695789692481670862504634730796844f); assert_approx_eq!(3.0f.acosh(), 1.76274717403908605046521864995958461f); } @@ -1045,34 +1094,58 @@ mod tests { fn test_atanh() { assert_eq!(0.0f.atanh(), 0.0f); assert_eq!((-0.0f).atanh(), -0.0f); - assert_eq!(1.0f.atanh(), Float::infinity::()); - assert_eq!((-1.0f).atanh(), Float::neg_infinity::()); + + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let inf64: f64 = Float::infinity(); + let neg_inf64: f64 = Float::neg_infinity(); + let nan: float = Float::NaN(); + assert_eq!(1.0f.atanh(), inf); + assert_eq!((-1.0f).atanh(), neg_inf); assert!(2f64.atanh().atanh().is_NaN()); assert!((-2f64).atanh().atanh().is_NaN()); - assert!(Float::infinity::().atanh().is_NaN()); - assert!(Float::neg_infinity::().atanh().is_NaN()); - assert!(Float::NaN::().atanh().is_NaN()); + assert!(inf64.atanh().is_NaN()); + assert!(neg_inf64.atanh().is_NaN()); + assert!(nan.atanh().is_NaN()); assert_approx_eq!(0.5f.atanh(), 0.54930614433405484569762261846126285f); assert_approx_eq!((-0.5f).atanh(), -0.54930614433405484569762261846126285f); } #[test] fn test_real_consts() { - assert_approx_eq!(Real::two_pi::(), 2f * Real::pi::()); - assert_approx_eq!(Real::frac_pi_2::(), Real::pi::() / 2f); - assert_approx_eq!(Real::frac_pi_3::(), Real::pi::() / 3f); - assert_approx_eq!(Real::frac_pi_4::(), Real::pi::() / 4f); - assert_approx_eq!(Real::frac_pi_6::(), Real::pi::() / 6f); - assert_approx_eq!(Real::frac_pi_8::(), Real::pi::() / 8f); - assert_approx_eq!(Real::frac_1_pi::(), 1f / Real::pi::()); - assert_approx_eq!(Real::frac_2_pi::(), 2f / Real::pi::()); - assert_approx_eq!(Real::frac_2_sqrtpi::(), 2f / Real::pi::().sqrt()); - assert_approx_eq!(Real::sqrt2::(), 2f.sqrt()); - assert_approx_eq!(Real::frac_1_sqrt2::(), 1f / 2f.sqrt()); - assert_approx_eq!(Real::log2_e::(), Real::e::().log2()); - assert_approx_eq!(Real::log10_e::(), Real::e::().log10()); - assert_approx_eq!(Real::ln_2::(), 2f.ln()); - assert_approx_eq!(Real::ln_10::(), 10f.ln()); + let pi: float = Real::pi(); + let two_pi: float = Real::two_pi(); + let frac_pi_2: float = Real::frac_pi_2(); + let frac_pi_3: float = Real::frac_pi_3(); + let frac_pi_4: float = Real::frac_pi_4(); + let frac_pi_6: float = Real::frac_pi_6(); + let frac_pi_8: float = Real::frac_pi_8(); + let frac_1_pi: float = Real::frac_1_pi(); + let frac_2_pi: float = Real::frac_2_pi(); + let frac_2_sqrtpi: float = Real::frac_2_sqrtpi(); + let sqrt2: float = Real::sqrt2(); + let frac_1_sqrt2: float = Real::frac_1_sqrt2(); + let e: float = Real::e(); + let log2_e: float = Real::log2_e(); + let log10_e: float = Real::log10_e(); + let ln_2: float = Real::ln_2(); + let ln_10: float = Real::ln_10(); + + assert_approx_eq!(two_pi, 2f * pi); + assert_approx_eq!(frac_pi_2, pi / 2f); + assert_approx_eq!(frac_pi_3, pi / 3f); + assert_approx_eq!(frac_pi_4, pi / 4f); + assert_approx_eq!(frac_pi_6, pi / 6f); + assert_approx_eq!(frac_pi_8, pi / 8f); + assert_approx_eq!(frac_1_pi, 1f / pi); + assert_approx_eq!(frac_2_pi, 2f / pi); + assert_approx_eq!(frac_2_sqrtpi, 2f / pi.sqrt()); + assert_approx_eq!(sqrt2, 2f.sqrt()); + assert_approx_eq!(frac_1_sqrt2, 1f / 2f.sqrt()); + assert_approx_eq!(log2_e, e.log2()); + assert_approx_eq!(log10_e, e.log10()); + assert_approx_eq!(ln_2, 2f.ln()); + assert_approx_eq!(ln_10, 10f.ln()); } #[test] @@ -1148,17 +1221,23 @@ mod tests { #[test] fn test_primitive() { - assert_eq!(Primitive::bits::(), sys::size_of::() * 8); - assert_eq!(Primitive::bytes::(), sys::size_of::()); + let none: Option = None; + assert_eq!(Primitive::bits(none), sys::size_of::() * 8); + assert_eq!(Primitive::bytes(none), sys::size_of::()); } #[test] fn test_is_normal() { - assert!(!Float::NaN::().is_normal()); - assert!(!Float::infinity::().is_normal()); - assert!(!Float::neg_infinity::().is_normal()); - assert!(!Zero::zero::().is_normal()); - assert!(!Float::neg_zero::().is_normal()); + let nan: float = Float::NaN(); + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let zero: float = Zero::zero(); + let neg_zero: float = Float::neg_zero(); + assert!(!nan.is_normal()); + assert!(!inf.is_normal()); + assert!(!neg_inf.is_normal()); + assert!(!zero.is_normal()); + assert!(!neg_zero.is_normal()); assert!(1f.is_normal()); assert!(1e-307f.is_normal()); assert!(!1e-308f.is_normal()); @@ -1166,11 +1245,16 @@ mod tests { #[test] fn test_classify() { - assert_eq!(Float::NaN::().classify(), FPNaN); - assert_eq!(Float::infinity::().classify(), FPInfinite); - assert_eq!(Float::neg_infinity::().classify(), FPInfinite); - assert_eq!(Zero::zero::().classify(), FPZero); - assert_eq!(Float::neg_zero::().classify(), FPZero); + let nan: float = Float::NaN(); + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let zero: float = Zero::zero(); + let neg_zero: float = Float::neg_zero(); + assert_eq!(nan.classify(), FPNaN); + assert_eq!(inf.classify(), FPInfinite); + assert_eq!(neg_inf.classify(), FPInfinite); + assert_eq!(zero.classify(), FPZero); + assert_eq!(neg_zero.classify(), FPZero); assert_eq!(1f.classify(), FPNormal); assert_eq!(1e-307f.classify(), FPNormal); assert_eq!(1e-308f.classify(), FPSubnormal); @@ -1187,11 +1271,13 @@ mod tests { assert_eq!(Float::ldexp(0f, -123), 0f); assert_eq!(Float::ldexp(-0f, -123), -0f); - assert_eq!(Float::ldexp(Float::infinity::(), -123), - Float::infinity::()); - assert_eq!(Float::ldexp(Float::neg_infinity::(), -123), - Float::neg_infinity::()); - assert!(Float::ldexp(Float::NaN::(), -123).is_NaN()); + + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let nan: float = Float::NaN(); + assert_eq!(Float::ldexp(inf, -123), inf); + assert_eq!(Float::ldexp(neg_inf, -123), neg_inf); + assert!(Float::ldexp(nan, -123).is_NaN()); } #[test] @@ -1209,11 +1295,13 @@ mod tests { assert_eq!(0f.frexp(), (0f, 0)); assert_eq!((-0f).frexp(), (-0f, 0)); - assert_eq!(match Float::infinity::().frexp() { (x, _) => x }, - Float::infinity::()) - assert_eq!(match Float::neg_infinity::().frexp() { (x, _) => x }, - Float::neg_infinity::()) - assert!(match Float::NaN::().frexp() { (x, _) => x.is_NaN() }) + + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + let nan: float = Float::NaN(); + assert_eq!(match inf.frexp() { (x, _) => x }, inf); + assert_eq!(match neg_inf.frexp() { (x, _) => x }, neg_inf); + assert!(match nan.frexp() { (x, _) => x.is_NaN() }) } #[test] diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 41da9a6ccbe48..55a2bcb9f69c3 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -455,10 +455,10 @@ impl Int for $T {} impl Primitive for $T { #[inline] - fn bits() -> uint { bits } + fn bits(_: Option<$T>) -> uint { bits } #[inline] - fn bytes() -> uint { bits / 8 } + fn bytes(_: Option<$T>) -> uint { bits / 8 } } // String conversion functions and impl str -> num @@ -752,8 +752,9 @@ mod tests { #[test] fn test_primitive() { - assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8); - assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>()); + let none: Option<$T> = None; + assert_eq!(Primitive::bits(none), sys::size_of::<$T>() * 8); + assert_eq!(Primitive::bytes(none), sys::size_of::<$T>()); } #[test] diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs index 04a1cc11b2673..1ad0048e0371b 100644 --- a/src/libstd/num/num.rs +++ b/src/libstd/num/num.rs @@ -272,8 +272,8 @@ pub trait Primitive: Num + Div + Rem { // FIXME (#5527): These should be associated constants - fn bits() -> uint; - fn bytes() -> uint; + fn bits(unused_self: Option) -> uint; + fn bytes(unused_self: Option) -> uint; } /// A collection of traits relevant to primitive signed and unsigned integers @@ -314,13 +314,13 @@ pub trait Float: Real fn is_normal(&self) -> bool; fn classify(&self) -> FPCategory; - fn mantissa_digits() -> uint; - fn digits() -> uint; + fn mantissa_digits(unused_self: Option) -> uint; + fn digits(unused_self: Option) -> uint; fn epsilon() -> Self; - fn min_exp() -> int; - fn max_exp() -> int; - fn min_10_exp() -> int; - fn max_10_exp() -> int; + fn min_exp(unused_self: Option) -> int; + fn max_exp(unused_self: Option) -> int; + fn min_10_exp(unused_self: Option) -> int; + fn max_10_exp(unused_self: Option) -> int; fn ldexp(x: Self, exp: int) -> Self; fn frexp(&self) -> (Self, int); @@ -484,9 +484,9 @@ impl Saturating for T { match self.checked_add(&v) { Some(x) => x, None => if v >= Zero::zero() { - Bounded::max_value::() + Bounded::max_value() } else { - Bounded::min_value::() + Bounded::min_value() } } } @@ -496,9 +496,9 @@ impl Saturating for T { match self.checked_sub(&v) { Some(x) => x, None => if v >= Zero::zero() { - Bounded::min_value::() + Bounded::min_value() } else { - Bounded::max_value::() + Bounded::max_value() } } } diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index 86b5b4ddfc09f..aa4bca2462ef6 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -403,10 +403,10 @@ impl ToStrRadix for $T { impl Primitive for $T { #[inline] - fn bits() -> uint { bits } + fn bits(_: Option<$T>) -> uint { bits } #[inline] - fn bytes() -> uint { bits / 8 } + fn bytes(_: Option<$T>) -> uint { bits / 8 } } impl BitCount for $T { @@ -519,8 +519,9 @@ mod tests { #[test] fn test_primitive() { - assert_eq!(Primitive::bits::<$T>(), sys::size_of::<$T>() * 8); - assert_eq!(Primitive::bytes::<$T>(), sys::size_of::<$T>()); + let none: Option<$T> = None; + assert_eq!(Primitive::bits(none), sys::size_of::<$T>() * 8); + assert_eq!(Primitive::bytes(none), sys::size_of::<$T>()); } #[test] diff --git a/src/libstd/os.rs b/src/libstd/os.rs index b357489d62ff8..fbc5193cacbac 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -1434,7 +1434,7 @@ impl MemoryMap { let r = unsafe { libc::mmap(addr, len, prot, flags, fd, offset) }; - if r == libc::MAP_FAILED { + if r.equiv(&libc::MAP_FAILED) { Err(match errno() as c_int { libc::EACCES => ErrFdNotAvail, libc::EBADF => ErrInvalidFd, diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs index de8f8c69e8432..b1c5110165299 100644 --- a/src/libstd/ptr.rs +++ b/src/libstd/ptr.rs @@ -12,8 +12,11 @@ use cast; use clone::Clone; +use cmp::Equiv; use iterator::{range, Iterator}; use option::{Option, Some, None}; +#[cfg(stage0)] +use sys; use unstable::intrinsics; use util::swap; @@ -24,18 +27,28 @@ use util::swap; /// Calculate the offset from a pointer #[inline] +#[cfg(stage0)] pub fn offset(ptr: *T, count: int) -> *T { - unsafe { intrinsics::offset(ptr, count) } + (ptr as uint + (count as uint) * sys::size_of::()) as *T } -/// Calculate the offset from a const pointer +/// Calculate the offset from a mut pointer #[inline] -pub fn const_offset(ptr: *const T, count: int) -> *const T { - unsafe { intrinsics::offset(ptr as *T, count) } +#[cfg(stage0)] +pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { + (ptr as uint + (count as uint) * sys::size_of::()) as *mut T +} + +/// Calculate the offset from a pointer +#[inline] +#[cfg(not(stage0))] +pub fn offset(ptr: *T, count: int) -> *T { + unsafe { intrinsics::offset(ptr, count) } } /// Calculate the offset from a mut pointer #[inline] +#[cfg(not(stage0))] pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { unsafe { intrinsics::offset(ptr as *T, count) as *mut T } } @@ -73,11 +86,11 @@ pub fn mut_null() -> *mut T { 0 as *mut T } /// Returns true if the pointer is equal to the null pointer. #[inline] -pub fn is_null(ptr: *const T) -> bool { ptr == null() } +pub fn is_null>(ptr: P) -> bool { ptr.is_null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] -pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } +pub fn is_not_null>(ptr: P) -> bool { ptr.is_not_null() } /** * Copies data from one location to another. @@ -87,8 +100,10 @@ pub fn is_not_null(ptr: *const T) -> bool { !is_null(ptr) } */ #[inline] #[cfg(target_word_size = "32")] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memmove32(dst, src as *T, count as u32); +pub unsafe fn copy_memory>(dst: *mut T, src: P, count: uint) { + intrinsics::memmove32(dst, + cast::transmute_immut_unsafe(src), + count as u32); } /** @@ -99,8 +114,10 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { */ #[inline] #[cfg(target_word_size = "64")] -pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memmove64(dst, src as *T, count as u64); +pub unsafe fn copy_memory>(dst: *mut T, src: P, count: uint) { + intrinsics::memmove64(dst, + cast::transmute_immut_unsafe(src), + count as u64); } /** @@ -111,8 +128,12 @@ pub unsafe fn copy_memory(dst: *mut T, src: *const T, count: uint) { */ #[inline] #[cfg(target_word_size = "32")] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memcpy32(dst, src as *T, count as u32); +pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, + src: P, + count: uint) { + intrinsics::memcpy32(dst, + cast::transmute_immut_unsafe(src), + count as u32); } /** @@ -123,8 +144,12 @@ pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: u */ #[inline] #[cfg(target_word_size = "64")] -pub unsafe fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint) { - intrinsics::memcpy64(dst, src as *T, count as u64); +pub unsafe fn copy_nonoverlapping_memory>(dst: *mut T, + src: P, + count: uint) { + intrinsics::memcpy64(dst, + cast::transmute_immut_unsafe(src), + count as u64); } /** @@ -216,12 +241,6 @@ pub fn to_unsafe_ptr(thing: &T) -> *T { thing as *T } -/// Transform a const region pointer - &const T - to a const unsafe pointer - *const T. -#[inline] -pub fn to_const_unsafe_ptr(thing: &const T) -> *const T { - thing as *const T -} - /// Transform a mutable region pointer - &mut T - to a mutable unsafe pointer - *mut T. #[inline] pub fn to_mut_unsafe_ptr(thing: &mut T) -> *mut T { @@ -269,8 +288,10 @@ pub unsafe fn array_each(arr: **T, cb: &fn(*T)) { #[allow(missing_doc)] pub trait RawPtr { + fn null() -> Self; fn is_null(&self) -> bool; fn is_not_null(&self) -> bool; + fn to_uint(&self) -> uint; unsafe fn to_option(&self) -> Option<&T>; fn offset(&self, count: int) -> Self; unsafe fn offset_inbounds(self, count: int) -> Self; @@ -278,13 +299,21 @@ pub trait RawPtr { /// Extension methods for immutable pointers impl RawPtr for *T { + /// Returns the null pointer. + #[inline] + fn null() -> *T { null() } + /// Returns true if the pointer is equal to the null pointer. #[inline] - fn is_null(&self) -> bool { is_null(*self) } + fn is_null(&self) -> bool { *self == RawPtr::null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] - fn is_not_null(&self) -> bool { is_not_null(*self) } + fn is_not_null(&self) -> bool { *self != RawPtr::null() } + + /// Returns the address of this pointer. + #[inline] + fn to_uint(&self) -> uint { *self as uint } /// /// Returns `None` if the pointer is null, or else returns the value wrapped @@ -317,13 +346,21 @@ impl RawPtr for *T { /// Extension methods for mutable pointers impl RawPtr for *mut T { + /// Returns the null pointer. + #[inline] + fn null() -> *mut T { mut_null() } + /// Returns true if the pointer is equal to the null pointer. #[inline] - fn is_null(&self) -> bool { is_null(*self) } + fn is_null(&self) -> bool { *self == RawPtr::null() } /// Returns true if the pointer is not equal to the null pointer. #[inline] - fn is_not_null(&self) -> bool { is_not_null(*self) } + fn is_not_null(&self) -> bool { *self != RawPtr::null() } + + /// Returns the address of this pointer. + #[inline] + fn to_uint(&self) -> uint { *self as uint } /// /// Returns `None` if the pointer is null, or else returns the value wrapped @@ -360,32 +397,77 @@ impl RawPtr for *mut T { // Equality for pointers #[cfg(not(test))] -impl Eq for *const T { +impl Eq for *T { + #[inline] + fn eq(&self, other: &*T) -> bool { + (*self as uint) == (*other as uint) + } + #[inline] + fn ne(&self, other: &*T) -> bool { !self.eq(other) } +} + +#[cfg(not(test))] +impl Eq for *mut T { #[inline] - fn eq(&self, other: &*const T) -> bool { + fn eq(&self, other: &*mut T) -> bool { (*self as uint) == (*other as uint) } #[inline] - fn ne(&self, other: &*const T) -> bool { !self.eq(other) } + fn ne(&self, other: &*mut T) -> bool { !self.eq(other) } +} + +// Equivalence for pointers +#[cfg(not(test))] +impl Equiv<*mut T> for *T { + fn equiv(&self, other: &*mut T) -> bool { + self.to_uint() == other.to_uint() + } +} + +#[cfg(not(test))] +impl Equiv<*T> for *mut T { + fn equiv(&self, other: &*T) -> bool { + self.to_uint() == other.to_uint() + } } // Comparison for pointers #[cfg(not(test))] -impl Ord for *const T { +impl Ord for *T { + #[inline] + fn lt(&self, other: &*T) -> bool { + (*self as uint) < (*other as uint) + } + #[inline] + fn le(&self, other: &*T) -> bool { + (*self as uint) <= (*other as uint) + } + #[inline] + fn ge(&self, other: &*T) -> bool { + (*self as uint) >= (*other as uint) + } + #[inline] + fn gt(&self, other: &*T) -> bool { + (*self as uint) > (*other as uint) + } +} + +#[cfg(not(test))] +impl Ord for *mut T { #[inline] - fn lt(&self, other: &*const T) -> bool { + fn lt(&self, other: &*mut T) -> bool { (*self as uint) < (*other as uint) } #[inline] - fn le(&self, other: &*const T) -> bool { + fn le(&self, other: &*mut T) -> bool { (*self as uint) <= (*other as uint) } #[inline] - fn ge(&self, other: &*const T) -> bool { + fn ge(&self, other: &*mut T) -> bool { (*self as uint) >= (*other as uint) } #[inline] - fn gt(&self, other: &*const T) -> bool { + fn gt(&self, other: &*mut T) -> bool { (*self as uint) > (*other as uint) } } diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs index ba4cbc668038f..a7e466e3d846e 100644 --- a/src/libstd/rt/borrowck.rs +++ b/src/libstd/rt/borrowck.rs @@ -10,14 +10,15 @@ use c_str::ToCStr; use cast::transmute; -use libc::{c_char, size_t, STDERR_FILENO}; -use io; use io::{Writer, WriterUtil}; +use io; +use libc::{c_char, size_t, STDERR_FILENO}; use option::{Option, None, Some}; -use uint; -use str; +use ptr::RawPtr; use str::{OwnedStr, StrSlice}; +use str; use sys; +use uint; use unstable::raw; use vec::ImmutableVector; @@ -80,12 +81,12 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) { static ENABLE_DEBUG: bool = false; #[inline] -unsafe fn debug_borrow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { +unsafe fn debug_borrow>(tag: &'static str, + p: P, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { //! A useful debugging function that prints a pointer + tag + newline //! without allocating memory. @@ -94,15 +95,15 @@ unsafe fn debug_borrow(tag: &'static str, debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); } - unsafe fn debug_borrow_slow(tag: &'static str, - p: *const T, - old_bits: uint, - new_bits: uint, - filename: *c_char, - line: size_t) { + unsafe fn debug_borrow_slow>(tag: &'static str, + p: P, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { let dbg = STDERR_FILENO as io::fd_t; dbg.write_str(tag); - dbg.write_hex(p as uint); + dbg.write_hex(p.to_uint()); dbg.write_str(" "); dbg.write_hex(old_bits); dbg.write_str(" "); diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 42d59ccdf958e..2a814b804687d 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -144,13 +144,13 @@ impl ChanOne { match oldstate { STATE_BOTH => { // Port is not waiting yet. Nothing to do - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { rtdebug!("non-rendezvous send"); sched.metrics.non_rendezvous_sends += 1; } } STATE_ONE => { - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { rtdebug!("rendezvous send"); sched.metrics.rendezvous_sends += 1; } @@ -167,7 +167,7 @@ impl ChanOne { }; } else { let recvr = Cell::new(recvr); - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { sched.enqueue_blocked_task(recvr.take()); } } @@ -207,7 +207,7 @@ impl PortOne { if !this.optimistic_check() { // No data available yet. // Switch to the scheduler to put the ~Task into the Packet state. - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { this.block_on(sched, task); } @@ -229,7 +229,7 @@ impl SelectInner for PortOne { // The optimistic check is never necessary for correctness. For testing // purposes, making it randomly return false simulates a racing sender. use rand::{Rand}; - let actually_check = do Local::borrow:: |sched| { + let actually_check = do Local::borrow |sched: &mut Scheduler| { Rand::rand(&mut sched.rng) }; if actually_check { diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs index 77176088801de..7b2d38caaaf05 100644 --- a/src/libstd/rt/io/net/ip.rs +++ b/src/libstd/rt/io/net/ip.rs @@ -359,7 +359,7 @@ impl FromStr for SocketAddr { mod test { use super::*; use from_str::FromStr; - use option::{Some, None}; + use option::{Option, Some, None}; #[test] fn test_from_str_ipv4() { @@ -368,13 +368,17 @@ mod test { assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0")); // out of range - assert_eq!(None, FromStr::from_str::("256.0.0.1")); + let none: Option = FromStr::from_str("256.0.0.1"); + assert_eq!(None, none); // too short - assert_eq!(None, FromStr::from_str::("255.0.0")); + let none: Option = FromStr::from_str("255.0.0"); + assert_eq!(None, none); // too long - assert_eq!(None, FromStr::from_str::("255.0.0.1.2")); + let none: Option = FromStr::from_str("255.0.0.1.2"); + assert_eq!(None, none); // no number between dots - assert_eq!(None, FromStr::from_str::("255.0..1")); + let none: Option = FromStr::from_str("255.0..1"); + assert_eq!(None, none); } #[test] @@ -389,15 +393,20 @@ mod test { FromStr::from_str("2a02:6b8::11:11")); // too long group - assert_eq!(None, FromStr::from_str::("::00000")); + let none: Option = FromStr::from_str("::00000"); + assert_eq!(None, none); // too short - assert_eq!(None, FromStr::from_str::("1:2:3:4:5:6:7")); + let none: Option = FromStr::from_str("1:2:3:4:5:6:7"); + assert_eq!(None, none); // too long - assert_eq!(None, FromStr::from_str::("1:2:3:4:5:6:7:8:9")); + let none: Option = FromStr::from_str("1:2:3:4:5:6:7:8:9"); + assert_eq!(None, none); // triple colon - assert_eq!(None, FromStr::from_str::("1:2:::6:7:8")); + let none: Option = FromStr::from_str("1:2:::6:7:8"); + assert_eq!(None, none); // two double colons - assert_eq!(None, FromStr::from_str::("1:2::6::8")); + let none: Option = FromStr::from_str("1:2::6::8"); + assert_eq!(None, none); } #[test] @@ -412,11 +421,15 @@ mod test { FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33")); // colon after v4 - assert_eq!(None, FromStr::from_str::("::127.0.0.1:")); + let none: Option = FromStr::from_str("::127.0.0.1:"); + assert_eq!(None, none); // not enought groups - assert_eq!(None, FromStr::from_str::("1.2.3.4.5:127.0.0.1")); + let none: Option = FromStr::from_str("1.2.3.4.5:127.0.0.1"); + assert_eq!(None, none); // too many groups - assert_eq!(None, FromStr::from_str::("1.2.3.4.5:6:7:127.0.0.1")); + let none: Option = + FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1"); + assert_eq!(None, none); } #[test] @@ -429,13 +442,17 @@ mod test { FromStr::from_str("[::127.0.0.1]:22")); // without port - assert_eq!(None, FromStr::from_str::("127.0.0.1")); + let none: Option = FromStr::from_str("127.0.0.1"); + assert_eq!(None, none); // without port - assert_eq!(None, FromStr::from_str::("127.0.0.1:")); + let none: Option = FromStr::from_str("127.0.0.1:"); + assert_eq!(None, none); // wrong brackets around v4 - assert_eq!(None, FromStr::from_str::("[127.0.0.1]:22")); + let none: Option = FromStr::from_str("[127.0.0.1]:22"); + assert_eq!(None, none); // port out of range - assert_eq!(None, FromStr::from_str::("127.0.0.1:123456")); + let none: Option = FromStr::from_str("127.0.0.1:123456"); + assert_eq!(None, none); } #[test] diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs index 27222542e087d..52c350951014e 100644 --- a/src/libstd/rt/io/net/tcp.rs +++ b/src/libstd/rt/io/net/tcp.rs @@ -29,7 +29,7 @@ impl TcpStream { pub fn connect(addr: SocketAddr) -> Option { let stream = unsafe { rtdebug!("borrowing io to connect"); - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); rtdebug!("about to connect"); (*io).tcp_connect(addr) }; @@ -102,7 +102,7 @@ pub struct TcpListener(~RtioTcpListenerObject); impl TcpListener { pub fn bind(addr: SocketAddr) -> Option { let listener = unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); (*io).tcp_bind(addr) }; match listener { diff --git a/src/libstd/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs index 644abcbe145ec..132ca064515c1 100644 --- a/src/libstd/rt/io/net/udp.rs +++ b/src/libstd/rt/io/net/udp.rs @@ -20,7 +20,10 @@ pub struct UdpSocket(~RtioUdpSocketObject); impl UdpSocket { pub fn bind(addr: SocketAddr) -> Option { - let socket = unsafe { (*Local::unsafe_borrow::()).udp_bind(addr) }; + let socket = unsafe { + let factory: *mut IoFactoryObject = Local::unsafe_borrow(); + (*factory).udp_bind(addr) + }; match socket { Ok(s) => Some(UdpSocket(s)), Err(ioerr) => { diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs index c7820ebf6238b..36a3e8bb08030 100644 --- a/src/libstd/rt/io/timer.rs +++ b/src/libstd/rt/io/timer.rs @@ -25,7 +25,7 @@ impl Timer { pub fn new() -> Option { let timer = unsafe { rtdebug!("Timer::init: borrowing io to init timer"); - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); rtdebug!("about to init timer"); (*io).timer_init() }; @@ -61,4 +61,4 @@ mod test { } } } -} \ No newline at end of file +} diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs index 1faad913b5025..5b26b073f747a 100644 --- a/src/libstd/rt/local.rs +++ b/src/libstd/rt/local.rs @@ -19,7 +19,7 @@ use cell::Cell; pub trait Local { fn put(value: ~Self); fn take() -> ~Self; - fn exists() -> bool; + fn exists(unused_value: Option) -> bool; fn borrow(f: &fn(&mut Self) -> T) -> T; unsafe fn unsafe_borrow() -> *mut Self; unsafe fn try_unsafe_borrow() -> Option<*mut Self>; @@ -28,7 +28,7 @@ pub trait Local { impl Local for Task { fn put(value: ~Task) { unsafe { local_ptr::put(value) } } fn take() -> ~Task { unsafe { local_ptr::take() } } - fn exists() -> bool { local_ptr::exists() } + fn exists(_: Option) -> bool { local_ptr::exists() } fn borrow(f: &fn(&mut Task) -> T) -> T { let mut res: Option = None; let res_ptr: *mut Option = &mut res; @@ -52,21 +52,21 @@ impl Local for Task { impl Local for Scheduler { fn put(value: ~Scheduler) { let value = Cell::new(value); - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { let task = task; task.sched = Some(value.take()); }; } fn take() -> ~Scheduler { - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { let sched = task.sched.take_unwrap(); let task = task; task.sched = None; sched } } - fn exists() -> bool { - do Local::borrow:: |task| { + fn exists(_: Option) -> bool { + do Local::borrow |task: &mut Task| { match task.sched { Some(ref _task) => true, None => false @@ -74,7 +74,7 @@ impl Local for Scheduler { } } fn borrow(f: &fn(&mut Scheduler) -> T) -> T { - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { match task.sched { Some(~ref mut task) => { f(task) @@ -86,7 +86,8 @@ impl Local for Scheduler { } } unsafe fn unsafe_borrow() -> *mut Scheduler { - match (*Local::unsafe_borrow::()).sched { + let task: *mut Task = Local::unsafe_borrow(); + match (*task).sched { Some(~ref mut sched) => { let s: *mut Scheduler = &mut *sched; return s; @@ -97,7 +98,8 @@ impl Local for Scheduler { } } unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { - if Local::exists::() { + let no_scheduler: Option = None; + if Local::exists(no_scheduler) { Some(Local::unsafe_borrow()) } else { None @@ -109,14 +111,16 @@ impl Local for Scheduler { impl Local for IoFactoryObject { fn put(_value: ~IoFactoryObject) { rtabort!("unimpl") } fn take() -> ~IoFactoryObject { rtabort!("unimpl") } - fn exists() -> bool { rtabort!("unimpl") } + fn exists(_: Option) -> bool { rtabort!("unimpl") } fn borrow(_f: &fn(&mut IoFactoryObject) -> T) -> T { rtabort!("unimpl") } unsafe fn unsafe_borrow() -> *mut IoFactoryObject { - let sched = Local::unsafe_borrow::(); + let sched: *mut Scheduler = Local::unsafe_borrow(); let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); return io; } - unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { rtabort!("unimpl") } + unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { + rtabort!("unimpl") + } } @@ -182,7 +186,7 @@ mod test { let task = ~Task::new_root(&mut sched.stack_pool, None, || {}); Local::put(task); - let res = do Local::borrow:: |_task| { + let res = do Local::borrow |_task: &mut Task| { true }; assert!(res) diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs index 8715e768e3276..3054e7d698273 100644 --- a/src/libstd/rt/local_heap.rs +++ b/src/libstd/rt/local_heap.rs @@ -13,7 +13,7 @@ use libc; use libc::{c_void, uintptr_t, size_t}; use ops::Drop; -use option::{Some, None}; +use option::{Option, None, Some}; use rt::local::Local; use rt::task::Task; use unstable::raw; @@ -86,7 +86,8 @@ impl Drop for LocalHeap { // A little compatibility function pub unsafe fn local_free(ptr: *libc::c_char) { // XXX: Unsafe borrow for speed. Lame. - match Local::try_unsafe_borrow::() { + let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow(); + match task_ptr { Some(task) => { (*task).heap.free(ptr as *libc::c_void); } @@ -95,7 +96,7 @@ pub unsafe fn local_free(ptr: *libc::c_char) { } pub fn live_allocs() -> *raw::Box<()> { - let region = do Local::borrow:: |task| { + let region = do Local::borrow |task: &mut Task| { task.heap.boxed_region }; diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs index 65214d0cea78a..822e0f799496a 100644 --- a/src/libstd/rt/mod.rs +++ b/src/libstd/rt/mod.rs @@ -64,7 +64,7 @@ use cell::Cell; use clone::Clone; use container::Container; use iterator::{Iterator, range}; -use option::{Some, None}; +use option::{Option, None, Some}; use ptr::RawPtr; use rt::local::Local; use rt::sched::{Scheduler, Shutdown}; @@ -402,7 +402,8 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int { pub fn in_sched_context() -> bool { unsafe { - match Local::try_unsafe_borrow::() { + let task_ptr: Option<*mut Task> = Local::try_unsafe_borrow(); + match task_ptr { Some(task) => { match (*task).task_type { SchedTask => true, @@ -416,7 +417,8 @@ pub fn in_sched_context() -> bool { pub fn in_green_task_context() -> bool { unsafe { - match Local::try_unsafe_borrow::() { + let task: Option<*mut Task> = Local::try_unsafe_borrow(); + match task { Some(task) => { match (*task).task_type { GreenTask(_) => true, diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs index ce4e64c47d2ef..fe644a76466b6 100644 --- a/src/libstd/rt/sched.rs +++ b/src/libstd/rt/sched.rs @@ -170,7 +170,7 @@ impl Scheduler { // successfully run the input task. Start by running the // scheduler. Grab it out of TLS - performing the scheduler // action will have given it away. - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); rtdebug!("starting scheduler %u", sched.sched_id()); @@ -181,7 +181,7 @@ impl Scheduler { // cleaning up the memory it uses. As we didn't actually call // task.run() on the scheduler task we never get through all // the cleanup code it runs. - let mut stask = Local::take::(); + let mut stask: ~Task = Local::take(); rtdebug!("stopping scheduler %u", stask.sched.get_ref().sched_id()); @@ -213,7 +213,7 @@ impl Scheduler { // Our scheduler must be in the task before the event loop // is started. let self_sched = Cell::new(self_sched); - do Local::borrow:: |stask| { + do Local::borrow |stask: &mut Task| { stask.sched = Some(self_sched.take()); }; @@ -235,7 +235,7 @@ impl Scheduler { // already have a scheduler stored in our local task, so we // start off by taking it. This is the only path through the // scheduler where we get the scheduler this way. - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); // Our first task is to read mail to see if we have important // messages. @@ -307,7 +307,6 @@ impl Scheduler { /// event loop to run it later. Always use this instead of pushing /// to the work queue directly. pub fn enqueue_task(&mut self, task: ~Task) { - let this = self; // We push the task onto our local queue clone. @@ -591,7 +590,7 @@ impl Scheduler { // Task context case - use TLS. pub fn run_task(task: ~Task) { - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); let opt = do sched.schedule_task(task) |sched, next_task| { do sched.switch_running_tasks_and_then(next_task) |sched, last_task| { sched.enqueue_blocked_task(last_task); @@ -614,7 +613,7 @@ impl Scheduler { let mut this = self; // The current task is grabbed from TLS, not taken as an input. - let current_task: ~Task = Local::take::(); + let current_task: ~Task = Local::take(); // Check that the task is not in an atomically() section (e.g., // holding a pthread mutex, which could deadlock the scheduler). @@ -646,7 +645,8 @@ impl Scheduler { let current_task: &mut Task = match sched.cleanup_job { Some(GiveTask(ref task, _)) => { - transmute_mut_region(*transmute_mut_unsafe(task)) + let task_ptr: *~Task = task; + transmute_mut_region(*transmute_mut_unsafe(task_ptr)) } Some(DoNothing) => { rtabort!("no next task"); @@ -675,11 +675,11 @@ impl Scheduler { // run the cleanup job, as expected by the previously called // swap_contexts function. unsafe { - let sched = Local::unsafe_borrow::(); + let sched: *mut Scheduler = Local::unsafe_borrow(); (*sched).run_cleanup_job(); // Must happen after running the cleanup job (of course). - let task = Local::unsafe_borrow::(); + let task: *mut Task = Local::unsafe_borrow(); (*task).death.check_killed((*task).unwinder.unwinding); } } @@ -741,7 +741,7 @@ impl Scheduler { // We aren't performing a scheduler operation, so we want to // put the Scheduler back when we finish. let next_task = Cell::new(next_task); - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { sched.enqueue_task(next_task.take()); }; } @@ -1054,12 +1054,12 @@ mod test { // exit before emptying the work queue do run_in_newsched_task { do spawntask { - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { let task = Cell::new(task); do sched.event_loop.callback_ms(10) { rtdebug!("in callback"); - let mut sched = Local::take::(); + let mut sched: ~Scheduler = Local::take(); sched.enqueue_blocked_task(task.take()); Local::put(sched); } diff --git a/src/libstd/rt/select.rs b/src/libstd/rt/select.rs index 19a4948af3c5a..6cde0a1f2169f 100644 --- a/src/libstd/rt/select.rs +++ b/src/libstd/rt/select.rs @@ -26,3 +26,4 @@ pub trait SelectInner { pub trait SelectPortInner { fn recv_ready(self) -> Option; } + diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 708166518bb89..437aa0ca01574 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -89,7 +89,7 @@ impl Task { pub fn build_homed_child(stack_size: Option, f: ~fn(), home: SchedHome) -> ~Task { let f = Cell::new(f); let home = Cell::new(home); - do Local::borrow:: |running_task| { + do Local::borrow |running_task: &mut Task| { let mut sched = running_task.sched.take_unwrap(); let new_task = ~running_task.new_child_homed(&mut sched.stack_pool, stack_size, @@ -107,7 +107,7 @@ impl Task { pub fn build_homed_root(stack_size: Option, f: ~fn(), home: SchedHome) -> ~Task { let f = Cell::new(f); let home = Cell::new(home); - do Local::borrow:: |running_task| { + do Local::borrow |running_task: &mut Task| { let mut sched = running_task.sched.take_unwrap(); let new_task = ~Task::new_root_homed(&mut sched.stack_pool, stack_size, @@ -295,7 +295,7 @@ impl Task { // Grab both the scheduler and the task from TLS and check if the // task is executing on an appropriate scheduler. pub fn on_appropriate_sched() -> bool { - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { let sched_id = task.sched.get_ref().sched_id(); let sched_run_anything = task.sched.get_ref().run_anything; match task.task_type { @@ -359,7 +359,7 @@ impl Coroutine { unsafe { // Again - might work while safe, or it might not. - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { (sched).run_cleanup_job(); } @@ -368,7 +368,7 @@ impl Coroutine { // simply unsafe_borrow it to get this reference. We // need to still have the task in TLS though, so we // need to unsafe_borrow. - let task = Local::unsafe_borrow::(); + let task: *mut Task = Local::unsafe_borrow(); do (*task).run { // N.B. Removing `start` from the start wrapper @@ -387,7 +387,7 @@ impl Coroutine { } // We remove the sched from the Task in TLS right now. - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); // ... allowing us to give it away when performing a // scheduling operation. sched.terminate_current_task() diff --git a/src/libstd/rt/tube.rs b/src/libstd/rt/tube.rs index 247893f75de00..b8e535e4c7dfd 100644 --- a/src/libstd/rt/tube.rs +++ b/src/libstd/rt/tube.rs @@ -51,7 +51,7 @@ impl Tube { // There's a waiting task. Wake it up rtdebug!("waking blocked tube"); let task = (*state).blocked_task.take_unwrap(); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); sched.resume_blocked_task_immediately(task); } } @@ -67,7 +67,7 @@ impl Tube { rtdebug!("blocking on tube recv"); assert!(self.p.refcount() > 1); // There better be somebody to wake us up assert!((*state).blocked_task.is_none()); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |_, task| { (*state).blocked_task = Some(task); } @@ -102,7 +102,7 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone_cell = Cell::new(tube_clone); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { let mut tube_clone = tube_clone_cell.take(); tube_clone.send(1); @@ -119,7 +119,7 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone = Cell::new(tube_clone); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { let tube_clone = Cell::new(tube_clone.take()); do sched.event_loop.callback { @@ -143,7 +143,7 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone = Cell::new(tube_clone); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { callback_send(tube_clone.take(), 0); @@ -151,7 +151,7 @@ mod test { if i == 100 { return; } let tube = Cell::new(Cell::new(tube)); - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { let tube = tube.take(); do sched.event_loop.callback { let mut tube = tube.take(); diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs index a26b8a3ad594d..54542a34ff55a 100644 --- a/src/libstd/rt/uv/uvio.rs +++ b/src/libstd/rt/uv/uvio.rs @@ -214,7 +214,7 @@ mod test_remote { let mut tube = Tube::new(); let tube_clone = tube.clone(); let remote_cell = Cell::new_empty(); - do Local::borrow::() |sched| { + do Local::borrow |sched: &mut Scheduler| { let tube_clone = tube_clone.clone(); let tube_clone_cell = Cell::new(tube_clone); let remote = do sched.event_loop.remote_callback { @@ -250,7 +250,7 @@ impl IoFactory for UvIoFactory { let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); // Block this task and take ownership, switch to scheduler context do scheduler.deschedule_running_task_and_then |_, task| { @@ -272,7 +272,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(res); } // Context switch - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } else { rtdebug!("status is some"); @@ -280,7 +280,7 @@ impl IoFactory for UvIoFactory { do stream_watcher.close { let res = Err(uv_error_to_io_error(status.unwrap())); unsafe { (*result_cell_ptr).put_back(res); } - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } }; @@ -296,11 +296,11 @@ impl IoFactory for UvIoFactory { match watcher.bind(addr) { Ok(_) => Ok(~UvTcpListener::new(watcher)), Err(uverr) => { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do watcher.as_stream().close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -314,11 +314,11 @@ impl IoFactory for UvIoFactory { match watcher.bind(addr) { Ok(_) => Ok(~UvUdpSocket(watcher)), Err(uverr) => { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do watcher.close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -353,11 +353,11 @@ impl UvTcpListener { impl Drop for UvTcpListener { fn drop(&self) { let watcher = self.watcher(); - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do watcher.as_stream().close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -433,11 +433,11 @@ pub struct UvTcpStream(TcpWatcher); impl Drop for UvTcpStream { fn drop(&self) { rtdebug!("closing tcp stream"); - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do self.as_stream().close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -455,7 +455,7 @@ impl RtioTcpStream for UvTcpStream { let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); let buf_ptr: *&mut [u8] = &buf; do scheduler.deschedule_running_task_and_then |_sched, task| { rtdebug!("read: entered scheduler context"); @@ -483,7 +483,7 @@ impl RtioTcpStream for UvTcpStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -495,7 +495,7 @@ impl RtioTcpStream for UvTcpStream { fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); let buf_ptr: *&[u8] = &buf; do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); @@ -510,7 +510,7 @@ impl RtioTcpStream for UvTcpStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -574,11 +574,11 @@ pub struct UvUdpSocket(UdpWatcher); impl Drop for UvUdpSocket { fn drop(&self) { rtdebug!("closing udp socket"); - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do self.close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -596,7 +596,7 @@ impl RtioUdpSocket for UvUdpSocket { let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); let buf_ptr: *&mut [u8] = &buf; do scheduler.deschedule_running_task_and_then |_sched, task| { rtdebug!("recvfrom: entered scheduler context"); @@ -617,7 +617,7 @@ impl RtioUdpSocket for UvUdpSocket { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -629,7 +629,7 @@ impl RtioUdpSocket for UvUdpSocket { fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> Result<(), IoError> { let result_cell = Cell::new_empty(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); let buf_ptr: *&[u8] = &buf; do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); @@ -643,7 +643,7 @@ impl RtioUdpSocket for UvUdpSocket { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -758,11 +758,11 @@ impl UvTimer { impl Drop for UvTimer { fn drop(&self) { rtdebug!("closing UvTimer"); - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_, task| { let task_cell = Cell::new(task); do self.close { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -771,14 +771,14 @@ impl Drop for UvTimer { impl RtioTimer for UvTimer { fn sleep(&self, msecs: u64) { - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); do scheduler.deschedule_running_task_and_then |_sched, task| { rtdebug!("sleep: entered scheduler context"); let task_cell = Cell::new(task); let mut watcher = **self; do watcher.start(msecs, 0) |_, status| { assert!(status.is_none()); - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); scheduler.resume_blocked_task_immediately(task_cell.take()); } } @@ -791,7 +791,7 @@ impl RtioTimer for UvTimer { fn test_simple_io_no_connect() { do run_in_newsched_task { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let addr = next_test_ip4(); let maybe_chan = (*io).tcp_connect(addr); assert!(maybe_chan.is_err()); @@ -803,7 +803,7 @@ fn test_simple_io_no_connect() { fn test_simple_udp_io_bind_only() { do run_in_newsched_task { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let addr = next_test_ip4(); let maybe_socket = (*io).udp_bind(addr); assert!(maybe_socket.is_ok()); @@ -819,7 +819,7 @@ fn test_simple_tcp_server_and_client() { // Start the server first so it's listening when we connect do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -834,7 +834,7 @@ fn test_simple_tcp_server_and_client() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); } @@ -850,7 +850,7 @@ fn test_simple_udp_server_and_client() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut server_socket = (*io).udp_bind(server_addr).unwrap(); let mut buf = [0, .. 2048]; let (nread,src) = server_socket.recvfrom(buf).unwrap(); @@ -865,7 +865,7 @@ fn test_simple_udp_server_and_client() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut client_socket = (*io).udp_bind(client_addr).unwrap(); client_socket.sendto([0, 1, 2, 3, 4, 5, 6, 7], server_addr); } @@ -879,7 +879,7 @@ fn test_read_and_block() { let addr = next_test_ip4(); do spawntask { - let io = unsafe { Local::unsafe_borrow::() }; + let io: *mut IoFactoryObject = unsafe { Local::unsafe_borrow() }; let mut listener = unsafe { (*io).tcp_bind(addr).unwrap() }; let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -897,7 +897,7 @@ fn test_read_and_block() { } reads += 1; - let scheduler = Local::take::(); + let scheduler: ~Scheduler = Local::take(); // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it @@ -913,7 +913,7 @@ fn test_read_and_block() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -933,7 +933,7 @@ fn test_read_read_read() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let buf = [1, .. 2048]; @@ -947,7 +947,7 @@ fn test_read_read_read() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut stream = (*io).tcp_connect(addr).unwrap(); let mut buf = [0, .. 2048]; let mut total_bytes_read = 0; @@ -973,7 +973,7 @@ fn test_udp_twice() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut client = (*io).udp_bind(client_addr).unwrap(); assert!(client.sendto([1], server_addr).is_ok()); assert!(client.sendto([2], server_addr).is_ok()); @@ -982,7 +982,7 @@ fn test_udp_twice() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut server = (*io).udp_bind(server_addr).unwrap(); let mut buf1 = [0]; let mut buf2 = [0]; @@ -1010,7 +1010,7 @@ fn test_udp_many_read() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut server_out = (*io).udp_bind(server_out_addr).unwrap(); let mut server_in = (*io).udp_bind(server_in_addr).unwrap(); let msg = [1, .. 2048]; @@ -1033,7 +1033,7 @@ fn test_udp_many_read() { do spawntask { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let mut client_out = (*io).udp_bind(client_out_addr).unwrap(); let mut client_in = (*io).udp_bind(client_in_addr).unwrap(); let mut total_bytes_recv = 0; @@ -1060,7 +1060,7 @@ fn test_udp_many_read() { fn test_timer_sleep_simple_impl() { unsafe { - let io = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = Local::unsafe_borrow(); let timer = (*io).timer_init(); match timer { Ok(t) => t.sleep(1), diff --git a/src/libstd/select.rs b/src/libstd/select.rs index a92339e256244..579d19e6725d1 100644 --- a/src/libstd/select.rs +++ b/src/libstd/select.rs @@ -57,7 +57,7 @@ pub fn select(ports: &mut [A]) -> uint { let p = Cell::new(p); let c = Cell::new(c); - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { let task_handles = task.make_selectable(ports.len()); diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs index bfb9bee78028c..cb0753fb2e5de 100644 --- a/src/libstd/sys.rs +++ b/src/libstd/sys.rs @@ -143,7 +143,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { if in_green_task_context() { // XXX: Logging doesn't work here - the check to call the log // function never passes - so calling the log function directly. - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { let msg = match task.name { Some(ref name) => fmt!("task '%s' failed at '%s', %s:%i", @@ -160,7 +160,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { msg, file, line as int); } - let task = Local::unsafe_borrow::(); + let task: *mut Task = Local::unsafe_borrow(); if (*task).unwinder.unwinding { rtabort!("unwinding again"); } diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs index 3a11dee313816..ab59c70032523 100644 --- a/src/libstd/task/local_data_priv.rs +++ b/src/libstd/task/local_data_priv.rs @@ -28,7 +28,7 @@ impl Handle { pub fn new() -> Handle { use rt::local::Local; unsafe { - let task = Local::unsafe_borrow::(); + let task: *mut Task = Local::unsafe_borrow(); NewHandle(&mut (*task).storage) } } diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index c38e6f233130b..7d9208cfd93c3 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -526,7 +526,7 @@ pub fn with_task_name(blk: &fn(Option<&str>) -> U) -> U { use rt::task::Task; if in_green_task_context() { - do Local::borrow:: |task| { + do Local::borrow |task: &mut Task| { match task.name { Some(ref name) => blk(Some(name.as_slice())), None => blk(None) @@ -545,7 +545,7 @@ pub fn yield() { // XXX: What does yield really mean in newsched? // FIXME(#7544): Optimize this, since we know we won't block. - let sched = Local::take::(); + let sched: ~Scheduler = Local::take(); do sched.deschedule_running_task_and_then |sched, task| { sched.enqueue_blocked_task(task); } @@ -556,7 +556,7 @@ pub fn failing() -> bool { use rt::task::Task; - do Local::borrow:: |local| { + do Local::borrow |local: &mut Task| { local.unwinder.unwinding } } @@ -582,7 +582,7 @@ pub fn unkillable(f: &fn() -> U) -> U { unsafe { if in_green_task_context() { // The inhibits/allows might fail and need to borrow the task. - let t = Local::unsafe_borrow::(); + let t: *mut Task = Local::unsafe_borrow(); do (|| { (*t).death.inhibit_kill((*t).unwinder.unwinding); f() @@ -602,7 +602,7 @@ pub unsafe fn rekillable(f: &fn() -> U) -> U { use rt::task::Task; if in_green_task_context() { - let t = Local::unsafe_borrow::(); + let t: *mut Task = Local::unsafe_borrow(); do (|| { (*t).death.allow_kill((*t).unwinder.unwinding); f() @@ -989,7 +989,7 @@ fn test_try_fail() { #[cfg(test)] fn get_sched_id() -> int { - do Local::borrow::<::rt::sched::Scheduler, int> |sched| { + do Local::borrow |sched: &mut ::rt::sched::Scheduler| { sched.sched_id() as int } } diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs index e0efc14a8871f..216a9e9e4264d 100644 --- a/src/libstd/task/spawn.rs +++ b/src/libstd/task/spawn.rs @@ -450,7 +450,7 @@ impl RuntimeGlue { let mut handle = handle; do handle.kill().map_move |killed_task| { let killed_task = Cell::new(killed_task); - do Local::borrow:: |sched| { + do Local::borrow |sched: &mut Scheduler| { sched.enqueue_task(killed_task.take()); } }; @@ -461,7 +461,7 @@ impl RuntimeGlue { unsafe { // Can't use safe borrow, because the taskgroup destructor needs to // access the scheduler again to send kill signals to other tasks. - let me = Local::unsafe_borrow::(); + let me: *mut Task = Local::unsafe_borrow(); blk((*me).death.kill_handle.get_ref(), (*me).unwinder.unwinding) } } else { @@ -474,7 +474,7 @@ impl RuntimeGlue { unsafe { // Can't use safe borrow, because creating new hashmaps for the // tasksets requires an rng, which needs to borrow the sched. - let me = Local::unsafe_borrow::(); + let me: *mut Task = Local::unsafe_borrow(); blk(match (*me).taskgroup { None => { // First task in its (unlinked/unsupervised) taskgroup. @@ -587,7 +587,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { // If child data is 'None', the enlist is vacuously successful. let enlist_success = do child_data.take().map_move_default(true) |child_data| { let child_data = Cell::new(child_data); // :( - do Local::borrow:: |me| { + do Local::borrow |me: &mut Task| { let (child_tg, ancestors) = child_data.take(); let mut ancestors = ancestors; let handle = me.death.kill_handle.get_ref(); @@ -621,7 +621,7 @@ fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) { } else { unsafe { // Creating a 1:1 task:thread ... - let sched = Local::unsafe_borrow::(); + let sched: *mut Scheduler = Local::unsafe_borrow(); let sched_handle = (*sched).make_handle(); // Since this is a 1:1 scheduler we create a queue not in diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs index f871f4ef6d6ac..c5163a8cb9442 100644 --- a/src/libstd/to_bytes.rs +++ b/src/libstd/to_bytes.rs @@ -335,7 +335,14 @@ impl IterBytes for ~A { // NB: raw-pointer IterBytes does _not_ dereference // to the target; it just gives you the pointer-bytes. -impl IterBytes for *const A { +impl IterBytes for *A { + #[inline] + fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { + (*self as uint).iter_bytes(lsb0, f) + } +} + +impl IterBytes for *mut A { #[inline] fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool { (*self as uint).iter_bytes(lsb0, f) diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs index 12073a1f4f095..5d9ca6202e262 100644 --- a/src/libstd/tuple.rs +++ b/src/libstd/tuple.rs @@ -176,7 +176,7 @@ macro_rules! tuple_impls { impl<$($T:Zero),+> Zero for ($($T,)+) { #[inline] fn zero() -> ($($T,)+) { - ($(Zero::zero::<$T>(),)+) + ($({ let x: $T = Zero::zero(); x},)+) } #[inline] fn is_zero(&self) -> bool { diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs index 2cfe63d99266f..5744bf0fb0c86 100644 --- a/src/libstd/unstable/atomics.rs +++ b/src/libstd/unstable/atomics.rs @@ -538,7 +538,8 @@ mod test { #[test] fn option_empty() { - assert!(AtomicOption::empty::<()>().is_empty(SeqCst)); + let mut option: AtomicOption<()> = AtomicOption::empty(); + assert!(option.is_empty(SeqCst)); } #[test] diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs index 91b4283ba12dd..b32f66e48010f 100644 --- a/src/libstd/unstable/lang.rs +++ b/src/libstd/unstable/lang.rs @@ -13,7 +13,7 @@ use c_str::ToCStr; use cast::transmute; use libc::{c_char, c_void, size_t, uintptr_t}; -use option::{Some, None}; +use option::{Option, None, Some}; use sys; use rt::task::Task; use rt::local::Local; @@ -37,7 +37,8 @@ pub fn fail_bounds_check(file: *c_char, line: size_t, #[lang="malloc"] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { // XXX: Unsafe borrow for speed. Lame. - match Local::try_unsafe_borrow::() { + let task: Option<*mut Task> = Local::try_unsafe_borrow(); + match task { Some(task) => { (*task).heap.alloc(td as *c_void, size as uint) as *c_char } diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index adbf9fc757819..743083348f0f3 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -286,7 +286,7 @@ pub unsafe fn atomically(f: &fn() -> U) -> U { use rt::in_green_task_context; if in_green_task_context() { - let t = Local::unsafe_borrow::(); + let t: *mut Task = Local::unsafe_borrow(); do (|| { (*t).death.inhibit_yield(); f() diff --git a/src/libstd/util.rs b/src/libstd/util.rs index b46876ad3fe44..5085f337d4bba 100644 --- a/src/libstd/util.rs +++ b/src/libstd/util.rs @@ -54,8 +54,10 @@ pub fn swap(x: &mut T, y: &mut T) { let t: *mut T = &mut tmp; // Perform the swap, `&mut` pointers never alias - ptr::copy_nonoverlapping_memory(t, x, 1); - ptr::copy_nonoverlapping_memory(x, y, 1); + let x_raw: *mut T = x; + let y_raw: *mut T = y; + ptr::copy_nonoverlapping_memory(t, x_raw, 1); + ptr::copy_nonoverlapping_memory(x, y_raw, 1); ptr::copy_nonoverlapping_memory(y, t, 1); // y and t now point to the same thing, but we need to completely forget `tmp` diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs index 7748c040a1ddc..f35ca9ab40453 100644 --- a/src/libstd/vec.rs +++ b/src/libstd/vec.rs @@ -1062,14 +1062,7 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] { * foreign interop. */ #[inline] - fn as_imm_buf(&self, - /* NB---this CANNOT be const, see below */ - f: &fn(*T, uint) -> U) -> U { - // NB---Do not change the type of s to `&const [T]`. This is - // unsound. The reason is that we are going to create immutable pointers - // into `s` and pass them to `f()`, but in fact they are potentially - // pointing at *mutable memory*. Use `as_mut_buf` instead! - + fn as_imm_buf(&self, f: &fn(*T, uint) -> U) -> U { let s = self.repr(); f(s.data, s.len / sys::nonzero_size_of::()) } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 17247222c3ff9..1b39c64be7139 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -109,12 +109,21 @@ pub struct Path { /// A `::foo` path, is relative to the crate root rather than current /// module (like paths in an import). global: bool, - /// The segments in the path (the things separated by ::) - idents: ~[ident], - /// "Region parameter", currently only one lifetime is allowed in a path. - rp: Option, - /// These are the type parameters, ie, the `a, b` in `foo::bar::` - types: ~[Ty], + /// The segments in the path: the things separated by `::`. + segments: ~[PathSegment], +} + +/// A segment of a path: an identifier, an optional lifetime, and a set of +/// types. +#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] +pub struct PathSegment { + /// The identifier portion of this path segment. + identifier: ident, + /// The lifetime parameter for this path segment. Currently only one + /// lifetime parameter is allowed. + lifetime: Option, + /// The type parameters for this path segment, if present. + types: OptVec, } pub type CrateNum = int; @@ -165,12 +174,16 @@ impl Generics { } } +#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] +pub enum MethodProvenance { + FromTrait(def_id), + FromImpl(def_id), +} + #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum def { def_fn(def_id, purity), - def_static_method(/* method */ def_id, - /* trait */ Option, - purity), + def_static_method(/* method */ def_id, MethodProvenance, purity), def_self(NodeId, bool /* is_implicit */), def_self_ty(/* trait id */ NodeId), def_mod(def_id), @@ -298,7 +311,10 @@ pub enum pat_ { } #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] -pub enum mutability { m_mutbl, m_imm, m_const, } +pub enum mutability { + m_mutbl, + m_imm, +} #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub enum Sigil { @@ -704,7 +720,7 @@ impl ToStr for float_ty { } // NB Eq method appears below. -#[deriving(Clone, Eq, Encodable, Decodable,IterBytes)] +#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)] pub struct Ty { id: NodeId, node: ty_, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index cfbe61ca65e68..585db7171a2d0 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -28,8 +28,8 @@ pub fn path_name_i(idents: &[ident]) -> ~str { idents.map(|i| token::interner_get(i.name)).connect("::") } -pub fn path_to_ident(p: &Path) -> ident { - *p.idents.last() +pub fn path_to_ident(path: &Path) -> ident { + path.segments.last().identifier } pub fn local_def(id: NodeId) -> def_id { @@ -217,12 +217,18 @@ pub fn default_block( } } -pub fn ident_to_path(s: span, i: ident) -> Path { - ast::Path { span: s, - global: false, - idents: ~[i], - rp: None, - types: ~[] } +pub fn ident_to_path(s: span, identifier: ident) -> Path { + ast::Path { + span: s, + global: false, + segments: ~[ + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + ], + } } pub fn ident_to_pat(id: NodeId, s: span, i: ident) -> @pat { @@ -420,7 +426,7 @@ impl IdVisitor { impl Visitor<()> for IdVisitor { fn visit_mod(&mut self, module: &_mod, - _span: span, + _: span, node_id: NodeId, env: ()) { (self.visit_callback)(node_id); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index dfaffa0c2759d..d666cf68e1563 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -325,20 +325,6 @@ pub fn expr_to_str(cx: @ExtCtxt, expr: @ast::expr, err_msg: &str) -> @str { } } -pub fn expr_to_ident(cx: @ExtCtxt, - expr: @ast::expr, - err_msg: &str) -> ast::ident { - match expr.node { - ast::expr_path(ref p) => { - if p.types.len() > 0u || p.idents.len() != 1u { - cx.span_fatal(expr.span, err_msg); - } - return p.idents[0]; - } - _ => cx.span_fatal(expr.span, err_msg) - } -} - pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], name: &str) { if tts.len() != 0 { @@ -349,15 +335,15 @@ pub fn check_zero_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], pub fn get_single_str_from_tts(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree], - name: &str) -> @str { + name: &str) + -> @str { if tts.len() != 1 { cx.span_fatal(sp, fmt!("%s takes 1 argument.", name)); } match tts[0] { ast::tt_tok(_, token::LIT_STR(ident)) => cx.str_of(ident), - _ => - cx.span_fatal(sp, fmt!("%s requires a string.", name)) + _ => cx.span_fatal(sp, fmt!("%s requires a string.", name)), } } diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 65032642fda78..91f6b64076f6d 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -74,6 +74,13 @@ pub trait AstBuilder { // statements fn stmt_expr(&self, expr: @ast::expr) -> @ast::stmt; fn stmt_let(&self, sp: span, mutbl: bool, ident: ast::ident, ex: @ast::expr) -> @ast::stmt; + fn stmt_let_typed(&self, + sp: span, + mutbl: bool, + ident: ast::ident, + typ: ast::Ty, + ex: @ast::expr) + -> @ast::stmt; // blocks fn block(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@ast::expr>) -> ast::Block; @@ -233,18 +240,31 @@ impl AstBuilder for @ExtCtxt { fn path_global(&self, span: span, strs: ~[ast::ident]) -> ast::Path { self.path_all(span, true, strs, None, ~[]) } - fn path_all(&self, sp: span, + fn path_all(&self, + sp: span, global: bool, - idents: ~[ast::ident], + mut idents: ~[ast::ident], rp: Option, types: ~[ast::Ty]) - -> ast::Path { + -> ast::Path { + let last_identifier = idents.pop(); + let mut segments: ~[ast::PathSegment] = idents.move_iter() + .map(|ident| { + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + }).collect(); + segments.push(ast::PathSegment { + identifier: last_identifier, + lifetime: rp, + types: opt_vec::from(types), + }); ast::Path { span: sp, global: global, - idents: idents, - rp: rp, - types: types + segments: segments, } } @@ -387,6 +407,26 @@ impl AstBuilder for @ExtCtxt { @respan(sp, ast::stmt_decl(@decl, self.next_id())) } + fn stmt_let_typed(&self, + sp: span, + mutbl: bool, + ident: ast::ident, + typ: ast::Ty, + ex: @ast::expr) + -> @ast::stmt { + let pat = self.pat_ident(sp, ident); + let local = @ast::Local { + is_mutbl: mutbl, + ty: typ, + pat: pat, + init: Some(ex), + id: self.next_id(), + span: sp, + }; + let decl = respan(sp, ast::decl_local(local)); + @respan(sp, ast::stmt_decl(@decl, self.next_id())) + } + fn block(&self, span: span, stmts: ~[@ast::stmt], expr: Option<@expr>) -> ast::Block { self.block_all(span, ~[], stmts, expr) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index edb5c634d5698..477f3fde99c73 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -12,6 +12,7 @@ use ast; use codemap::span; use ext::base::*; use ext::base; +use opt_vec; use parse::token; use parse::token::{str_to_ident}; @@ -39,9 +40,13 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: span, tts: &[ast::token_tree]) ast::Path { span: sp, global: false, - idents: ~[res], - rp: None, - types: ~[], + segments: ~[ + ast::PathSegment { + identifier: res, + lifetime: None, + types: opt_vec::Empty, + } + ] } ), span: sp, diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index e55a96f77ff9b..9f86fe7d7f2c2 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -76,24 +76,34 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { let variant_count = cx.expr_uint(span, variants.len()); - // need to specify the uint-ness of the random number - let uint_ty = cx.ty_ident(span, cx.ident_of("uint")); let r_ty = cx.ty_ident(span, cx.ident_of("R")); let rand_name = cx.path_all(span, true, rand_ident.clone(), None, - ~[ uint_ty, r_ty ]); + ~[]); let rand_name = cx.expr_path(rand_name); - // ::std::rand::Rand::rand::(rng) + // ::std::rand::Rand::rand(rng) let rv_call = cx.expr_call(span, rand_name, ~[ rng[0].duplicate(cx) ]); + // need to specify the uint-ness of the random number + let uint_ty = cx.ty_ident(span, cx.ident_of("uint")); + let value_ident = cx.ident_of("__value"); + let let_statement = cx.stmt_let_typed(span, + false, + value_ident, + uint_ty, + rv_call); + // rand() % variants.len() - let rand_variant = cx.expr_binary(span, ast::rem, - rv_call, variant_count); + let value_ref = cx.expr_ident(span, value_ident); + let rand_variant = cx.expr_binary(span, + ast::rem, + value_ref, + variant_count); let mut arms = do variants.iter().enumerate().map |(i, id_sum)| { let i_expr = cx.expr_uint(span, i); @@ -111,7 +121,10 @@ fn rand_substructure(cx: @ExtCtxt, span: span, substr: &Substructure) -> @expr { // _ => {} at the end. Should never occur arms.push(cx.arm_unreachable(span)); - cx.expr_match(span, rand_variant, arms) + let match_expr = cx.expr_match(span, rand_variant, arms); + + let block = cx.block(span, ~[ let_statement ], Some(match_expr)); + cx.expr_block(block) } _ => cx.bug("Non-static method in `deriving(Rand)`") }; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index c188326a4f1b0..8e3c8d08f555c 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -19,6 +19,7 @@ use codemap; use codemap::{span, spanned, ExpnInfo, NameAndSpan}; use ext::base::*; use fold::*; +use opt_vec; use parse; use parse::{parse_item_from_source_str}; use parse::token; @@ -42,13 +43,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, match (*mac).node { // Token-tree macros: mac_invoc_tt(ref pth, ref tts) => { - if (pth.idents.len() > 1u) { + if (pth.segments.len() > 1u) { cx.span_fatal( pth.span, fmt!("expected macro name without module \ separators")); } - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); // leaving explicit deref here to highlight unbox op: match (*extsbox).find(&extname.name) { @@ -143,9 +144,13 @@ pub fn expand_expr(extsbox: @mut SyntaxEnv, ast::Path { span: span, global: false, - idents: ~[ident], - rp: None, - types: ~[] + segments: ~[ + ast::PathSegment { + identifier: ident, + lifetime: None, + types: opt_vec::Empty, + } + ], } } @@ -368,7 +373,7 @@ pub fn expand_item_mac(extsbox: @mut SyntaxEnv, _ => cx.span_bug(it.span, "invalid item macro invocation") }; - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); let expanded = match (*extsbox).find(&extname.name) { None => cx.span_fatal(pth.span, @@ -459,13 +464,13 @@ pub fn expand_stmt(extsbox: @mut SyntaxEnv, } _ => return orig(s, sp, fld) }; - if (pth.idents.len() > 1u) { + if (pth.segments.len() > 1u) { cx.span_fatal( pth.span, fmt!("expected macro name without module \ separators")); } - let extname = &pth.idents[0]; + let extname = &pth.segments[0].identifier; let extnamestr = ident_to_str(extname); let (fully_expanded, sp) = match (*extsbox).find(&extname.name) { None => @@ -534,10 +539,14 @@ impl Visitor<()> for NewNameFinderContext { // a path of length one: &ast::Path { global: false, - idents: [id], span: _, - rp: _, - types: _ + segments: [ + ast::PathSegment { + identifier: id, + lifetime: _, + types: _ + } + ] } => self.ident_accumulator.push(id), // I believe these must be enums... _ => () diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index c208a7f7e3e40..327ee331c3814 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -16,8 +16,8 @@ use codemap::{BytePos, mk_sp}; use codemap; use parse::lexer::*; //resolve bug? use parse::ParseSess; -use parse::parser::Parser; use parse::attr::parser_attr; +use parse::parser::{LifetimeAndTypesWithoutColons, Parser}; use parse::token::{Token, EOF, to_str, nonterminal, get_ident_interner, ident_to_str}; use parse::token; @@ -430,7 +430,9 @@ pub fn parse_nt(p: &Parser, name: &str) -> nonterminal { _ => p.fatal(~"expected ident, found " + token::to_str(get_ident_interner(), p.token)) }, - "path" => token::nt_path(~p.parse_path_with_tps(false)), + "path" => { + token::nt_path(~p.parse_path(LifetimeAndTypesWithoutColons).path) + } "attr" => token::nt_attr(@p.parse_attribute(false)), "tt" => { *p.quote_depth += 1u; //but in theory, non-quoted tts might be useful diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 65694f013f751..458737e2fbf0b 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -765,9 +765,11 @@ fn noop_fold_path(p: &Path, fld: @ast_fold) -> Path { ast::Path { span: fld.new_span(p.span), global: p.global, - idents: p.idents.map(|x| fld.fold_ident(*x)), - rp: p.rp, - types: p.types.map(|x| fld.fold_ty(x)), + segments: p.segments.map(|segment| ast::PathSegment { + identifier: fld.fold_ident(segment.identifier), + lifetime: segment.lifetime, + types: segment.types.map(|typ| fld.fold_ty(typ)), + }) } } diff --git a/src/libsyntax/oldvisit.rs b/src/libsyntax/oldvisit.rs index 295003c6ef538..56576ee359960 100644 --- a/src/libsyntax/oldvisit.rs +++ b/src/libsyntax/oldvisit.rs @@ -284,7 +284,11 @@ pub fn visit_ty(t: &Ty, (e, v): (E, vt)) { } pub fn visit_path(p: &Path, (e, v): (E, vt)) { - for tp in p.types.iter() { (v.visit_ty)(tp, (e.clone(), v)); } + for segment in p.segments.iter() { + for typ in segment.types.iter() { + (v.visit_ty)(typ, (e.clone(), v)) + } + } } pub fn visit_pat(p: &pat, (e, v): (E, vt)) { diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 23c6a8b97208b..1a7fc558dcd29 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -361,27 +361,47 @@ mod test { span{lo:BytePos(a),hi:BytePos(b),expn_info:None} } - #[test] fn path_exprs_1 () { + #[test] fn path_exprs_1() { assert_eq!(string_to_expr(@"a"), - @ast::expr{id:1, - node:ast::expr_path(ast::Path {span:sp(0,1), - global:false, - idents:~[str_to_ident("a")], - rp:None, - types:~[]}), - span:sp(0,1)}) + @ast::expr{ + id: 1, + node: ast::expr_path(ast::Path { + span: sp(0, 1), + global: false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("a"), + lifetime: None, + types: ~[], + } + ], + }), + span: sp(0, 1) + }) } #[test] fn path_exprs_2 () { assert_eq!(string_to_expr(@"::a::b"), - @ast::expr{id:1, - node:ast::expr_path( - ast::Path {span:sp(0,6), - global:true, - idents:strs_to_idents(~["a","b"]), - rp:None, - types:~[]}), - span:sp(0,6)}) + @ast::expr { + id:1, + node: ast::expr_path(ast::Path { + span: sp(0, 6), + global: true, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("a"), + lifetime: None, + types: ~[], + }, + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: ~[], + } + ] + }), + span: sp(0, 6) + }) } #[should_fail] @@ -420,32 +440,43 @@ mod test { #[test] fn ret_expr() { assert_eq!(string_to_expr(@"return d"), - @ast::expr{id:2, - node:ast::expr_ret( - Some(@ast::expr{id:1, - node:ast::expr_path( - ast::Path{span:sp(7,8), - global:false, - idents:~[str_to_ident("d")], - rp:None, - types:~[] - }), - span:sp(7,8)})), - span:sp(0,8)}) + @ast::expr{ + id:2, + node:ast::expr_ret(Some(@ast::expr{ + id:1, + node:ast::expr_path(ast::Path{ + span: sp(7, 8), + global: false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("d"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }), + span:sp(7,8) + })), + span:sp(0,8) + }) } #[test] fn parse_stmt_1 () { assert_eq!(string_to_stmt(@"b;"), @spanned{ - node: ast::stmt_expr(@ast::expr{ + node: ast::stmt_expr(@ast::expr { id: 1, - node: ast::expr_path( - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp:None, - types: ~[]}), + node: ast::expr_path(ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }), span: sp(0,1)}, 2), // fixme span: sp(0,1)}) @@ -460,15 +491,20 @@ mod test { let parser = string_to_parser(@"b"); assert_eq!(parser.parse_pat(), @ast::pat{id:1, // fixme - node: ast::pat_ident(ast::bind_infer, - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None /* no idea */), span: sp(0,1)}); parser_done(parser); } @@ -483,21 +519,33 @@ mod test { span:sp(4,4), // this is bizarre... // check this in the original parser? global:false, - idents:~[str_to_ident("int")], - rp: None, - types: ~[]}, - None, 2), + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("int"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, None, 2), span:sp(4,7)}, pat: @ast::pat{id:1, - node: ast::pat_ident(ast::bind_infer, - ast::Path{ - span:sp(0,1), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(0,1), + global:false, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None // no idea + ), span: sp(0,1)}, id: 4 // fixme }) @@ -519,23 +567,37 @@ mod test { node: ast::ty_path(ast::Path{ span:sp(10,13), global:false, - idents:~[str_to_ident("int")], - rp: None, - types: ~[]}, - None, 2), - span:sp(10,13)}, - pat: @ast::pat{id:1, // fixme - node: ast::pat_ident( - ast::bind_infer, - ast::Path{ - span:sp(6,7), - global:false, - idents:~[str_to_ident("b")], - rp: None, - types: ~[]}, - None // no idea - ), - span: sp(6,7)}, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("int"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, None, 2), + span:sp(10,13) + }, + pat: @ast::pat { + id:1, // fixme + node: ast::pat_ident( + ast::bind_infer, + ast::Path { + span:sp(6,7), + global:false, + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident("b"), + lifetime: None, + types: opt_vec::Empty, + } + ], + }, + None // no idea + ), + span: sp(6,7) + }, id: 4 // fixme }], output: ast::Ty{id:5, // fixme @@ -558,9 +620,18 @@ mod test { ast::Path{ span:sp(17,18), global:false, - idents:~[str_to_ident("b")], - rp:None, - types: ~[]}), + segments: ~[ + ast::PathSegment { + identifier: + str_to_ident( + "b"), + lifetime: + None, + types: + opt_vec::Empty + } + ], + }), span: sp(17,18)}, 7), // fixme span: sp(17,18)}], diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 01c1af7464db6..6e43e7ca8684a 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -54,7 +54,6 @@ pub enum ObsoleteSyntax { ObsoleteMode, ObsoleteImplicitSelf, ObsoleteLifetimeNotation, - ObsoleteConstManagedPointer, ObsoletePurity, ObsoleteStaticMethod, ObsoleteConstItem, @@ -66,6 +65,7 @@ pub enum ObsoleteSyntax { ObsoleteUnsafeExternFn, ObsoletePrivVisibility, ObsoleteTraitFuncVisibility, + ObsoleteConstPointer, } impl to_bytes::IterBytes for ObsoleteSyntax { @@ -209,10 +209,6 @@ impl ParserObsoleteMethods for Parser { "instead of `&foo/bar`, write `&'foo bar`; instead of \ `bar/&foo`, write `&bar<'foo>" ), - ObsoleteConstManagedPointer => ( - "const `@` pointer", - "instead of `@const Foo`, write `@Foo`" - ), ObsoletePurity => ( "pure function", "remove `pure`" @@ -263,6 +259,11 @@ impl ParserObsoleteMethods for Parser { "visibility not necessary", "trait functions inherit the visibility of the trait itself" ), + ObsoleteConstPointer => ( + "const pointer", + "instead of `&const Foo` or `@const Foo`, write `&Foo` or \ + `@Foo`" + ), }; self.report(sp, kind, kind_str, desc); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2664dcf890ad..9aca142838dc6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -38,7 +38,7 @@ use ast::{ident, impure_fn, inherited, item, item_, item_static}; use ast::{item_enum, item_fn, item_foreign_mod, item_impl}; use ast::{item_mac, item_mod, item_struct, item_trait, item_ty, lit, lit_}; use ast::{lit_bool, lit_float, lit_float_unsuffixed, lit_int}; -use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local, m_const}; +use ast::{lit_int_unsuffixed, lit_nil, lit_str, lit_uint, Local}; use ast::{m_imm, m_mutbl, mac_, mac_invoc_tt, matcher, match_nonterminal}; use ast::{match_seq, match_tok, method, mt, mul, mutability}; use ast::{named_field, neg, NodeId, noreturn, not, pat, pat_box, pat_enum}; @@ -97,6 +97,37 @@ enum restriction { type arg_or_capture_item = Either; type item_info = (ident, item_, Option<~[Attribute]>); +/// How to parse a path. There are four different kinds of paths, all of which +/// are parsed somewhat differently. +#[deriving(Eq)] +pub enum PathParsingMode { + /// A path with no type parameters; e.g. `foo::bar::Baz` + NoTypesAllowed, + /// A path with a lifetime and type parameters, with no double colons + /// before the type parameters; e.g. `foo::bar<'self>::Baz` + LifetimeAndTypesWithoutColons, + /// A path with a lifetime and type parameters with double colons before + /// the type parameters; e.g. `foo::bar::<'self>::Baz::` + LifetimeAndTypesWithColons, + /// A path with a lifetime and type parameters with bounds before the last + /// set of type parameters only; e.g. `foo::bar<'self>::Baz:X+Y` This + /// form does not use extra double colons. + LifetimeAndTypesAndBounds, +} + +/// A pair of a path segment and group of type parameter bounds. (See `ast.rs` +/// for the definition of a path segment.) +struct PathSegmentAndBoundSet { + segment: ast::PathSegment, + bound_set: Option>, +} + +/// A path paired with optional type bounds. +struct PathAndBounds { + path: ast::Path, + bounds: Option>, +} + pub enum item_or_view_item { // Indicates a failure to parse any kind of item. The attributes are // returned. @@ -1108,7 +1139,10 @@ impl Parser { } else if *self.token == token::MOD_SEP || is_ident_or_path(self.token) { // NAMED TYPE - let (path, bounds) = self.parse_type_path(); + let PathAndBounds { + path, + bounds + } = self.parse_path(LifetimeAndTypesAndBounds); ty_path(path, bounds, self.get_id()) } else { self.fatal(fmt!("expected type, found token %?", @@ -1154,9 +1188,6 @@ impl Parser { if mt.mutbl != m_imm && sigil == OwnedSigil { self.obsolete(*self.last_span, ObsoleteMutOwnedPointer); } - if mt.mutbl == m_const && sigil == ManagedSigil { - self.obsolete(*self.last_span, ObsoleteConstManagedPointer); - } ctor(mt) } @@ -1333,139 +1364,155 @@ impl Parser { } } - // parse a path into a vector of idents, whether the path starts - // with ::, and a span. - pub fn parse_path(&self) -> (~[ast::ident],bool,span) { + /// Parses a path and optional type parameter bounds, depending on the + /// mode. The `mode` parameter determines whether lifetimes, types, and/or + /// bounds are permitted and whether `::` must precede type parameter + /// groups. + pub fn parse_path(&self, mode: PathParsingMode) -> PathAndBounds { + // Check for a whole path... + let found = match *self.token { + INTERPOLATED(token::nt_path(_)) => Some(self.bump_and_get()), + _ => None, + }; + match found { + Some(INTERPOLATED(token::nt_path(~path))) => { + return PathAndBounds { + path: path, + bounds: None, + } + } + _ => {} + } + let lo = self.span.lo; let is_global = self.eat(&token::MOD_SEP); - let (ids,span{lo:_,hi,expn_info}) = self.parse_path_non_global(); - (ids,is_global,span{lo:lo,hi:hi,expn_info:expn_info}) - } - // parse a path beginning with an identifier into a vector of idents and a span - pub fn parse_path_non_global(&self) -> (~[ast::ident],span) { - let lo = self.span.lo; - let mut ids = ~[]; - // must be at least one to begin: - ids.push(self.parse_ident()); + // Parse any number of segments and bound sets. A segment is an + // identifier followed by an optional lifetime and a set of types. + // A bound set is a set of type parameter bounds. + let mut segments = ~[]; loop { + // First, parse an identifier. match *self.token { - token::MOD_SEP => { - let is_ident = do self.look_ahead(1) |t| { - match *t { - token::IDENT(*) => true, - _ => false, - } - }; - if is_ident { - self.bump(); - ids.push(self.parse_ident()); - } else { - break - } - } - _ => break + token::IDENT(*) => {} + _ => break, } - } - (ids, mk_sp(lo, self.last_span.hi)) - } + let identifier = self.parse_ident(); - // parse a path that doesn't have type parameters attached - pub fn parse_path_without_tps(&self) -> ast::Path { - maybe_whole!(deref self, nt_path); - let (ids,is_global,sp) = self.parse_path(); - ast::Path { span: sp, - global: is_global, - idents: ids, - rp: None, - types: ~[] } - } + // Next, parse a colon and bounded type parameters, if applicable. + let bound_set = if mode == LifetimeAndTypesAndBounds { + self.parse_optional_ty_param_bounds() + } else { + None + }; - pub fn parse_bounded_path_with_tps(&self, colons: bool, - before_tps: Option<&fn()>) -> ast::Path { - debug!("parse_path_with_tps(colons=%b)", colons); + // Parse the '::' before type parameters if it's required. If + // it is required and wasn't present, then we're done. + if mode == LifetimeAndTypesWithColons && + !self.eat(&token::MOD_SEP) { + segments.push(PathSegmentAndBoundSet { + segment: ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + }, + bound_set: bound_set + }); + break + } - maybe_whole!(deref self, nt_path); - let lo = self.span.lo; - let path = self.parse_path_without_tps(); - if colons && !self.eat(&token::MOD_SEP) { - return path; - } - - // If the path might have bounds on it, they should be parsed before - // the parameters, e.g. module::TraitName:B1+B2 - before_tps.map_move(|callback| callback()); - - // Parse the (obsolete) trailing region parameter, if any, which will - // be written "foo/&x" - let rp_slash = { - if *self.token == token::BINOP(token::SLASH) - && self.look_ahead(1, |t| *t == token::BINOP(token::AND)) - { - self.bump(); self.bump(); - self.obsolete(*self.last_span, ObsoleteLifetimeNotation); - match *self.token { - token::IDENT(sid, _) => { - let span = self.span; - self.bump(); - Some(ast::Lifetime { - id: self.get_id(), - span: *span, - ident: sid - }) + // Parse the `<` before the lifetime and types, if applicable. + let (any_lifetime_or_types, optional_lifetime, types) = + if mode != NoTypesAllowed && self.eat(&token::LT) { + // Parse an optional lifetime. + let optional_lifetime = match *self.token { + token::LIFETIME(*) => Some(self.parse_lifetime()), + _ => None, + }; + + // Parse type parameters. + let mut types = opt_vec::Empty; + let mut need_comma = optional_lifetime.is_some(); + loop { + // We're done if we see a `>`. + match *self.token { + token::GT | token::BINOP(token::SHR) => { + self.expect_gt(); + break + } + _ => {} // Go on. } - _ => { - self.fatal(fmt!("Expected a lifetime name")); + + if need_comma { + self.expect(&token::COMMA) + } else { + need_comma = true } + + types.push(self.parse_ty(false)) } + + (true, optional_lifetime, types) } else { - None - } - }; + (false, None, opt_vec::Empty) + }; - // Parse any lifetime or type parameters which may appear: - let (lifetimes, tps) = self.parse_generic_values(); - let hi = self.span.lo; + // Assemble and push the result. + segments.push(PathSegmentAndBoundSet { + segment: ast::PathSegment { + identifier: identifier, + lifetime: optional_lifetime, + types: types, + }, + bound_set: bound_set + }); - let rp = match (&rp_slash, &lifetimes) { - (&Some(_), _) => rp_slash, - (&None, v) => { - if v.len() == 0 { - None - } else if v.len() == 1 { - Some(*v.get(0)) - } else { - self.fatal(fmt!("Expected at most one \ - lifetime name (for now)")); + // We're done if we don't see a '::', unless the mode required + // a double colon to get here in the first place. + if !(mode == LifetimeAndTypesWithColons && + !any_lifetime_or_types) { + if !self.eat(&token::MOD_SEP) { + break } } - }; - - ast::Path { - span: mk_sp(lo, hi), - rp: rp, - types: tps, - .. path.clone() } - } - // parse a path optionally with type parameters. If 'colons' - // is true, then type parameters must be preceded by colons, - // as in a::t:: - pub fn parse_path_with_tps(&self, colons: bool) -> ast::Path { - self.parse_bounded_path_with_tps(colons, None) - } + // Assemble the span. + let span = mk_sp(lo, self.last_span.hi); - // Like the above, but can also parse kind bounds in the case of a - // path to be used as a type that might be a trait. - pub fn parse_type_path(&self) -> (ast::Path, Option>) { + // Assemble the path segments. + let mut path_segments = ~[]; let mut bounds = None; - let path = self.parse_bounded_path_with_tps(false, Some(|| { - // Note: this closure might not even get called in the case of a - // macro-generated path. But that's the macro parser's job. - bounds = self.parse_optional_ty_param_bounds(); - })); - (path, bounds) + let last_segment_index = segments.len() - 1; + for (i, segment_and_bounds) in segments.move_iter().enumerate() { + let PathSegmentAndBoundSet { + segment: segment, + bound_set: bound_set + } = segment_and_bounds; + path_segments.push(segment); + + if bound_set.is_some() { + if i != last_segment_index { + self.span_err(span, + "type parameter bounds are allowed only \ + before the last segment in a path") + } + + bounds = bound_set + } + } + + // Assemble the result. + let path_and_bounds = PathAndBounds { + path: ast::Path { + span: span, + global: is_global, + segments: path_segments, + }, + bounds: bounds, + }; + + path_and_bounds } /// parses 0 or 1 lifetime @@ -1569,7 +1616,8 @@ impl Parser { if self.eat_keyword(keywords::Mut) { m_mutbl } else if self.eat_keyword(keywords::Const) { - m_const + self.obsolete(*self.last_span, ObsoleteConstPointer); + m_imm } else { m_imm } @@ -1728,7 +1776,7 @@ impl Parser { } else if *self.token == token::LBRACKET { self.bump(); let mutbl = self.parse_mutability(); - if mutbl == m_mutbl || mutbl == m_const { + if mutbl == m_mutbl { self.obsolete(*self.last_span, ObsoleteMutVector); } @@ -1792,7 +1840,7 @@ impl Parser { } else if *self.token == token::MOD_SEP || is_ident(&*self.token) && !self.is_keyword(keywords::True) && !self.is_keyword(keywords::False) { - let pth = self.parse_path_with_tps(true); + let pth = self.parse_path(LifetimeAndTypesWithColons).path; // `!`, as an operator, is prefix, so we know this isn't that if *self.token == token::NOT { @@ -2183,10 +2231,6 @@ impl Parser { token::AT => { self.bump(); let m = self.parse_mutability(); - if m == m_const { - self.obsolete(*self.last_span, ObsoleteConstManagedPointer); - } - let e = self.parse_prefix_expr(); hi = e.span.hi; // HACK: turn @[...] into a @-evec @@ -2887,7 +2931,8 @@ impl Parser { let val = self.parse_literal_maybe_minus(); if self.eat(&token::DOTDOT) { let end = if is_ident_or_path(tok) { - let path = self.parse_path_with_tps(true); + let path = self.parse_path(LifetimeAndTypesWithColons) + .path; let hi = self.span.hi; self.mk_expr(lo, hi, expr_path(path)) } else { @@ -2916,7 +2961,7 @@ impl Parser { let end = self.parse_expr_res(RESTRICT_NO_BAR_OP); pat = pat_range(start, end); } else if is_plain_ident(&*self.token) && !can_be_enum_or_struct { - let name = self.parse_path_without_tps(); + let name = self.parse_path(NoTypesAllowed).path; let sub; if self.eat(&token::AT) { // parse foo @ pat @@ -2928,7 +2973,8 @@ impl Parser { pat = pat_ident(bind_infer, name, sub); } else { // parse an enum pat - let enum_path = self.parse_path_with_tps(true); + let enum_path = self.parse_path(LifetimeAndTypesWithColons) + .path; match *self.token { token::LBRACE => { self.bump(); @@ -2964,7 +3010,7 @@ impl Parser { } }, _ => { - if enum_path.idents.len()==1u { + if enum_path.segments.len() == 1 { // it could still be either an enum // or an identifier pattern, resolve // will sort it out: @@ -2999,7 +3045,7 @@ impl Parser { "expected identifier, found path"); } // why a path here, and not just an identifier? - let name = self.parse_path_without_tps(); + let name = self.parse_path(NoTypesAllowed).path; let sub = if self.eat(&token::AT) { Some(self.parse_pat()) } else { @@ -3116,7 +3162,7 @@ impl Parser { // Potential trouble: if we allow macros with paths instead of // idents, we'd need to look ahead past the whole path here... - let pth = self.parse_path_without_tps(); + let pth = self.parse_path(NoTypesAllowed).path; self.bump(); let id = if *self.token == token::LPAREN { @@ -3792,7 +3838,7 @@ impl Parser { // parse a::B<~str,int> fn parse_trait_ref(&self) -> trait_ref { ast::trait_ref { - path: self.parse_path_with_tps(false), + path: self.parse_path(LifetimeAndTypesWithoutColons).path, ref_id: self.get_id(), } } @@ -4712,7 +4758,7 @@ impl Parser { } // item macro. - let pth = self.parse_path_without_tps(); + let pth = self.parse_path(NoTypesAllowed).path; self.expect(&token::NOT); // a 'special' identifier (like what `macro_rules!` uses) @@ -4796,11 +4842,17 @@ impl Parser { let id = self.parse_ident(); path.push(id); } - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.move_iter().map(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_simple(first_ident, path, @@ -4826,11 +4878,17 @@ impl Parser { seq_sep_trailing_allowed(token::COMMA), |p| p.parse_path_list_ident() ); - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.move_iter().map(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_list(path, idents, self.get_id())); } @@ -4838,11 +4896,17 @@ impl Parser { // foo::bar::* token::BINOP(token::STAR) => { self.bump(); - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.move_iter().map(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.span.hi, view_path_glob(path, self.get_id())); } @@ -4854,11 +4918,17 @@ impl Parser { _ => () } let last = path[path.len() - 1u]; - let path = ast::Path { span: mk_sp(lo, self.span.hi), - global: false, - idents: path, - rp: None, - types: ~[] }; + let path = ast::Path { + span: mk_sp(lo, self.span.hi), + global: false, + segments: path.move_iter().map(|identifier| { + ast::PathSegment { + identifier: identifier, + lifetime: None, + types: opt_vec::Empty, + } + }).collect() + }; return @spanned(lo, self.last_span.hi, view_path_simple(last, path, self.get_id())); diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 6a3d829aca0b0..f7f2f27ab0ed6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -387,7 +387,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) { word(s.s, "["); match mt.mutbl { ast::m_mutbl => word_space(s, "mut"), - ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); @@ -430,7 +429,6 @@ pub fn print_type(s: @ps, ty: &ast::Ty) { word(s.s, "["); match mt.mutbl { ast::m_mutbl => word_space(s, "mut"), - ast::m_const => word_space(s, "const"), ast::m_imm => () } print_type(s, mt.ty); @@ -1504,34 +1502,52 @@ pub fn print_for_decl(s: @ps, loc: &ast::Local, coll: &ast::expr) { print_expr(s, coll); } -fn print_path_(s: @ps, path: &ast::Path, colons_before_params: bool, +fn print_path_(s: @ps, + path: &ast::Path, + colons_before_params: bool, opt_bounds: &Option>) { maybe_print_comment(s, path.span.lo); - if path.global { word(s.s, "::"); } - let mut first = true; - for id in path.idents.iter() { - if first { first = false; } else { word(s.s, "::"); } - print_ident(s, *id); + if path.global { + word(s.s, "::"); } - do opt_bounds.map |bounds| { - print_bounds(s, bounds, true); - }; - if path.rp.is_some() || !path.types.is_empty() { - if colons_before_params { word(s.s, "::"); } - if path.rp.is_some() || !path.types.is_empty() { + let mut first = true; + for (i, segment) in path.segments.iter().enumerate() { + if first { + first = false + } else { + word(s.s, "::") + } + + print_ident(s, segment.identifier); + + if segment.lifetime.is_some() || !segment.types.is_empty() { + // If this is the last segment, print the bounds. + if i == path.segments.len() - 1 { + match *opt_bounds { + None => {} + Some(ref bounds) => print_bounds(s, bounds, true), + } + } + + if colons_before_params { + word(s.s, "::") + } word(s.s, "<"); - for r in path.rp.iter() { - print_lifetime(s, r); - if !path.types.is_empty() { - word_space(s, ","); + for lifetime in segment.lifetime.iter() { + print_lifetime(s, lifetime); + if !segment.types.is_empty() { + word_space(s, ",") } } - commasep(s, inconsistent, path.types, print_type); + commasep(s, + inconsistent, + segment.types.map_to_vec(|t| (*t).clone()), + print_type); - word(s.s, ">"); + word(s.s, ">") } } } @@ -1822,7 +1838,7 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) { pub fn print_view_path(s: @ps, vp: &ast::view_path) { match vp.node { ast::view_path_simple(ident, ref path, _) => { - if path.idents[path.idents.len()-1u] != ident { + if path.segments.last().identifier != ident { print_ident(s, ident); space(s.s); word_space(s, "="); @@ -1883,7 +1899,6 @@ pub fn print_view_item(s: @ps, item: &ast::view_item) { pub fn print_mutability(s: @ps, mutbl: ast::mutability) { match mutbl { ast::m_mutbl => word_nbsp(s, "mut"), - ast::m_const => word_nbsp(s, "const"), ast::m_imm => {/* nothing */ } } } @@ -1903,8 +1918,9 @@ pub fn print_arg(s: @ps, input: &ast::arg) { _ => { match input.pat.node { ast::pat_ident(_, ref path, _) if - path.idents.len() == 1 && - path.idents[0] == parse::token::special_idents::invalid => { + path.segments.len() == 1 && + path.segments[0].identifier == + parse::token::special_idents::invalid => { // Do nothing. } _ => { diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 8178e7f3760b7..2a0630d332ca7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -319,8 +319,10 @@ pub fn walk_ty>(visitor: &mut V, typ: &Ty, env: E) { } pub fn walk_path>(visitor: &mut V, path: &Path, env: E) { - for typ in path.types.iter() { - visitor.visit_ty(typ, env.clone()) + for segment in path.segments.iter() { + for typ in segment.types.iter() { + visitor.visit_ty(typ, env.clone()) + } } } @@ -671,26 +673,35 @@ pub fn walk_arm>(visitor: &mut V, arm: &arm, env: E) { // calls the given functions on the nodes. pub trait SimpleVisitor { - fn visit_mod(&mut self, &_mod, span, NodeId); - fn visit_view_item(&mut self, &view_item); - fn visit_foreign_item(&mut self, @foreign_item); - fn visit_item(&mut self, @item); - fn visit_local(&mut self, @Local); - fn visit_block(&mut self, &Block); - fn visit_stmt(&mut self, @stmt); - fn visit_arm(&mut self, &arm); - fn visit_pat(&mut self, @pat); - fn visit_decl(&mut self, @decl); - fn visit_expr(&mut self, @expr); - fn visit_expr_post(&mut self, @expr); - fn visit_ty(&mut self, &Ty); - fn visit_generics(&mut self, &Generics); - fn visit_fn(&mut self, &fn_kind, &fn_decl, &Block, span, NodeId); - fn visit_ty_method(&mut self, &TypeMethod); - fn visit_trait_method(&mut self, &trait_method); - fn visit_struct_def(&mut self, @struct_def, ident, &Generics, NodeId); - fn visit_struct_field(&mut self, @struct_field); - fn visit_struct_method(&mut self, @method); + fn visit_mod(&mut self, _m: &_mod, _s: span, _n: NodeId) {} + fn visit_view_item(&mut self, _vi: &view_item) {} + fn visit_foreign_item(&mut self, _fi: @foreign_item) {} + fn visit_item(&mut self, _i: @item) {} + fn visit_local(&mut self, _l: @Local) {} + fn visit_block(&mut self, _b: &Block) {} + fn visit_stmt(&mut self, _s: @stmt) {} + fn visit_arm(&mut self, _a: &arm) {} + fn visit_pat(&mut self, _p: @pat) {} + fn visit_decl(&mut self, _d: @decl) {} + fn visit_expr(&mut self, _e: @expr) {} + fn visit_expr_post(&mut self, _e: @expr) {} + fn visit_ty(&mut self, _t: &Ty) {} + fn visit_generics(&mut self, _g: &Generics) {} + fn visit_fn(&mut self, + _fk: &fn_kind, + _fd: &fn_decl, + _b: &Block, + _s: span, + _n: NodeId) {} + fn visit_ty_method(&mut self, _t: &TypeMethod) {} + fn visit_trait_method(&mut self, _t: &trait_method) {} + fn visit_struct_def(&mut self, + _s: @struct_def, + _i: ident, + _g: &Generics, + _n: NodeId) {} + fn visit_struct_field(&mut self, _s: @struct_field) {} + fn visit_struct_method(&mut self, _m: @method) {} } pub struct SimpleVisitorVisitor { diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs new file mode 100644 index 0000000000000..e4833345d311c --- /dev/null +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -0,0 +1,37 @@ +#[no_std]; + +struct S { + contents: T, +} + +impl S { + fn new(x: T, _: U) -> S { + S { + contents: x, + } + } +} + +trait Trait { + fn new(x: T, y: U) -> Self; +} + +struct S2 { + contents: int, +} + +impl Trait for S2 { + fn new(x: int, _: U) -> S2 { + S2 { + contents: x, + } + } +} + +fn main() { + let _ = S::new::(1, 1.0); //~ ERROR the impl referenced by this path has 1 type parameter, but 0 type parameters were supplied + let _ = S::<'self,int>::new::(1, 1.0); //~ ERROR this impl has no lifetime parameter + let _: S2 = Trait::new::(1, 1.0); //~ ERROR the trait referenced by this path has 1 type parameter, but 0 type parameters were supplied + let _: S2 = Trait::<'self,int>::new::(1, 1.0); //~ ERROR this trait has no lifetime parameter +} + diff --git a/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs b/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs deleted file mode 100644 index c51cf5b9538d9..0000000000000 --- a/src/test/compile-fail/borrowck-alias-mut-base-ptr.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Test that attempt to alias `&mut` pointer while pointee is borrowed -// yields an error. -// -// Example from src/middle/borrowck/doc.rs - -use std::util::swap; - -fn foo(t0: &mut int) { - let p: &int = &*t0; // Freezes `*t0` - let q: &const &mut int = &const t0; //~ ERROR cannot borrow `t0` - **q = 22; //~ ERROR cannot assign to an `&mut` in a `&const` pointer -} - -fn main() { -} \ No newline at end of file diff --git a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs index 7e9c298ba4732..843b5436d842c 100644 --- a/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs +++ b/src/test/compile-fail/borrowck-borrow-mut-base-ptr-in-aliasable-loc.rs @@ -11,16 +11,6 @@ fn foo(t0: & &mut int) { **t1 = 22; //~ ERROR cannot assign } -fn foo2(t0: &const &mut int) { - // Note: reborrowing from an &const actually yields two errors, since it - // is unsafe in two ways: we can't control the aliasing, and we can't - // control the mutation. - let t1 = t0; - let p: &int = &**t0; //~ ERROR cannot borrow an `&mut` in a `&const` pointer - //~^ ERROR unsafe borrow of aliasable, const value - **t1 = 22; //~ ERROR cannot assign -} - fn foo3(t0: &mut &mut int) { let t1 = &mut *t0; let p: &int = &**t0; //~ ERROR cannot borrow @@ -28,4 +18,4 @@ fn foo3(t0: &mut &mut int) { } fn main() { -} \ No newline at end of file +} diff --git a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs index 0aa7cbf50b7a3..537e52120d9f1 100644 --- a/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs +++ b/src/test/compile-fail/borrowck-call-method-from-mut-aliasable.rs @@ -14,29 +14,18 @@ struct Foo { impl Foo { pub fn f(&self) {} - pub fn g(&const self) {} pub fn h(&mut self) {} } fn a(x: &mut Foo) { x.f(); - x.g(); x.h(); } fn b(x: &Foo) { x.f(); - x.g(); x.h(); //~ ERROR cannot borrow } -fn c(x: &const Foo) { - x.f(); //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - x.g(); - x.h(); //~ ERROR cannot borrow - //~^ ERROR unsafe borrow -} - fn main() { } diff --git a/src/test/compile-fail/borrowck-lend-flow.rs b/src/test/compile-fail/borrowck-lend-flow.rs index 59cac0c5d953a..ea840a28b4e6a 100644 --- a/src/test/compile-fail/borrowck-lend-flow.rs +++ b/src/test/compile-fail/borrowck-lend-flow.rs @@ -32,14 +32,6 @@ fn pre_freeze() { borrow_mut(v); //~ ERROR cannot borrow } -fn pre_const() { - // In this instance, the freeze starts before the mut borrow. - - let mut v = ~3; - let _w = &const v; - borrow_mut(v); -} - fn post_freeze() { // In this instance, the const alias starts after the borrow. diff --git a/src/test/compile-fail/borrowck-loan-vec-content.rs b/src/test/compile-fail/borrowck-loan-vec-content.rs index 6a8e64377aab2..8a4a2cdedb230 100644 --- a/src/test/compile-fail/borrowck-loan-vec-content.rs +++ b/src/test/compile-fail/borrowck-loan-vec-content.rs @@ -29,16 +29,5 @@ fn has_mut_vec_but_tries_to_change_it() { } } -fn takes_const_elt(_v: &const int, f: &fn()) { - f(); -} - -fn has_mut_vec_and_tries_to_change_it() { - let mut v = ~[1, 2, 3]; - do takes_const_elt(&const v[0]) { - v[1] = 4; - } -} - fn main() { } diff --git a/src/test/compile-fail/borrowck-pat-by-value-binding.rs b/src/test/compile-fail/borrowck-pat-by-value-binding.rs deleted file mode 100644 index e77f5245d7d8b..0000000000000 --- a/src/test/compile-fail/borrowck-pat-by-value-binding.rs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2012 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. - -fn process(_t: T) {} - -fn match_const_opt_by_mut_ref(v: &const Option) { - match *v { - Some(ref mut i) => process(i), //~ ERROR cannot borrow - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_const_ref(v: &const Option) { - match *v { - Some(ref const i) => process(i), - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_imm_ref(v: &const Option) { - match *v { - Some(ref i) => process(i), //~ ERROR cannot borrow - //~^ ERROR unsafe borrow of aliasable, const value - None => () - } -} - -fn match_const_opt_by_value(v: &const Option) { - match *v { - Some(i) => process(i), - None => () - } -} - -fn main() { -} diff --git a/src/test/compile-fail/borrowck-uniq-via-lend.rs b/src/test/compile-fail/borrowck-uniq-via-lend.rs index 43459acaaf185..c87428cd300a7 100644 --- a/src/test/compile-fail/borrowck-uniq-via-lend.rs +++ b/src/test/compile-fail/borrowck-uniq-via-lend.rs @@ -35,12 +35,6 @@ fn aliased_imm() { borrow(v); } -fn aliased_const() { - let mut v = ~3; - let _w = &const v; - borrow(v); -} - fn aliased_mut() { let mut v = ~3; let _w = &mut v; diff --git a/src/test/compile-fail/fn-variance-3.rs b/src/test/compile-fail/fn-variance-3.rs index 630eb4b538d58..e42c6b658e4f7 100644 --- a/src/test/compile-fail/fn-variance-3.rs +++ b/src/test/compile-fail/fn-variance-3.rs @@ -23,13 +23,10 @@ fn main() { // @int <: X // - // This constraint forces X to be - // @const int. - r(@3); + // Here the type check fails because @const is gone and there is no + // supertype. + r(@3); //~ ERROR mismatched types - // Here the type check succeeds but the - // mutability check will fail, because the - // type of r has been inferred to be - // fn(@const int) -> @const int - *r(@mut 3) = 4; //~ ERROR cannot assign to const dereference of @ pointer + // Here the type check succeeds. + *r(@mut 3) = 4; } diff --git a/src/test/compile-fail/issue-3969.rs b/src/test/compile-fail/issue-3969.rs deleted file mode 100644 index b60a54a44bbfd..0000000000000 --- a/src/test/compile-fail/issue-3969.rs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 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. - -struct Bike { - name: ~str, -} - -trait BikeMethods { - fn woops(&const self) -> ~str; -} - -impl BikeMethods for Bike { - fn woops() -> ~str { ~"foo" } - //~^ ERROR has a `&const self` declaration in the trait, but not in the impl -} - -pub fn main() { -} diff --git a/src/test/compile-fail/issue-4096.rs b/src/test/compile-fail/issue-4096.rs deleted file mode 100644 index 3f1172b6de8f6..0000000000000 --- a/src/test/compile-fail/issue-4096.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 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. - -pub trait Nummy { - fn from_inty() -> Self; -} - -impl Nummy for float { - fn from_inty() -> float { 0.0 } -} - -fn main() { - let _1:float = Nummy::from_inty::(); //~ ERROR not enough type - //~^ NOTE Static methods have an extra implicit type parameter -} diff --git a/src/test/compile-fail/mutable-huh-ptr-assign.rs b/src/test/compile-fail/mutable-huh-ptr-assign.rs deleted file mode 100644 index 4460da72e2059..0000000000000 --- a/src/test/compile-fail/mutable-huh-ptr-assign.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2012 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. - -extern mod extra; - -fn main() { - unsafe fn f(v: *const int) { - *v = 1 //~ ERROR cannot assign - } - - unsafe { - let mut a = 0; - let v = &mut a; - f(v); - } -} diff --git a/src/test/compile-fail/prim-with-args.rs b/src/test/compile-fail/prim-with-args.rs index 40d5a44124177..e60fbf4fc49a8 100644 --- a/src/test/compile-fail/prim-with-args.rs +++ b/src/test/compile-fail/prim-with-args.rs @@ -23,17 +23,17 @@ let x: u64; //~ ERROR type parameters are not allowed on this type let x: float; //~ ERROR type parameters are not allowed on this type let x: char; //~ ERROR type parameters are not allowed on this type -let x: int<'static>; //~ ERROR region parameters are not allowed on this type -let x: i8<'static>; //~ ERROR region parameters are not allowed on this type -let x: i16<'static>; //~ ERROR region parameters are not allowed on this type -let x: i32<'static>; //~ ERROR region parameters are not allowed on this type -let x: i64<'static>; //~ ERROR region parameters are not allowed on this type -let x: uint<'static>; //~ ERROR region parameters are not allowed on this type -let x: u8<'static>; //~ ERROR region parameters are not allowed on this type -let x: u16<'static>; //~ ERROR region parameters are not allowed on this type -let x: u32<'static>; //~ ERROR region parameters are not allowed on this type -let x: u64<'static>; //~ ERROR region parameters are not allowed on this type -let x: float<'static>; //~ ERROR region parameters are not allowed on this type -let x: char<'static>; //~ ERROR region parameters are not allowed on this type +let x: int<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: i8<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: i16<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: i32<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: i64<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: uint<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: u8<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: u16<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: u32<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: u64<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: float<'static>; //~ ERROR lifetime parameters are not allowed on this type +let x: char<'static>; //~ ERROR lifetime parameters are not allowed on this type } diff --git a/src/test/compile-fail/regions-bounds.rs b/src/test/compile-fail/regions-bounds.rs index ab2ac6cc0e5b9..ab365c1bf6fb3 100644 --- a/src/test/compile-fail/regions-bounds.rs +++ b/src/test/compile-fail/regions-bounds.rs @@ -25,8 +25,4 @@ fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> { //~^ ERROR cannot infer an appropriate lifetime } -fn a_fn4<'a,'b>() { - let _: int<'a> = 1; //~ ERROR region parameters are not allowed on this type -} - fn main() { } diff --git a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs index 65fbbfc6e1985..351daf461d2fe 100644 --- a/src/test/compile-fail/resolve-inconsistent-binding-mode.rs +++ b/src/test/compile-fail/resolve-inconsistent-binding-mode.rs @@ -26,13 +26,6 @@ fn matcher2(x: opts) { } } -fn matcher3(x: opts) { - match x { - a(ref mut i) | b(ref const i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 - c(_) => {} - } -} - fn matcher4(x: opts) { match x { a(ref mut i) | b(ref i) => {} //~ ERROR variable `i` is bound with different mode in pattern #2 than in pattern #1 diff --git a/src/test/compile-fail/static-method-privacy.rs b/src/test/compile-fail/static-method-privacy.rs index 0fd82b5ace3a7..b637037f60e8f 100644 --- a/src/test/compile-fail/static-method-privacy.rs +++ b/src/test/compile-fail/static-method-privacy.rs @@ -6,5 +6,5 @@ mod a { } fn main() { - let _ = a::S::new(); //~ ERROR function `new` is private + let _ = a::S::new(); //~ ERROR method `new` is private } diff --git a/src/test/run-pass/auto-ref-slice-plus-ref.rs b/src/test/run-pass/auto-ref-slice-plus-ref.rs index 58a477900c324..d35341516f2a7 100644 --- a/src/test/run-pass/auto-ref-slice-plus-ref.rs +++ b/src/test/run-pass/auto-ref-slice-plus-ref.rs @@ -13,17 +13,14 @@ trait MyIter { fn test_imm(&self); - fn test_const(&const self); } impl<'self> MyIter for &'self [int] { fn test_imm(&self) { assert_eq!(self[0], 1) } - fn test_const(&const self) { assert_eq!(self[0], 1) } } impl<'self> MyIter for &'self str { fn test_imm(&self) { assert_eq!(*self, "test") } - fn test_const(&const self) { assert_eq!(self[0], 't' as u8) } } pub fn main() { @@ -40,15 +37,6 @@ pub fn main() { // XXX: Other types of mutable vecs don't currently exist - ([1]).test_const(); - (~[1]).test_const(); - (@[1]).test_const(); - (&[1]).test_const(); - ("test").test_const(); - (~"test").test_const(); - (@"test").test_const(); - (&"test").test_const(); - // NB: We don't do this double autoreffing for &mut self because that would // allow creating a mutable pointer to a temporary, which would be a source // of confusion diff --git a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs index b00d8980c69fe..fc643ec594089 100644 --- a/src/test/run-pass/autoderef-and-borrow-method-receiver.rs +++ b/src/test/run-pass/autoderef-and-borrow-method-receiver.rs @@ -13,7 +13,7 @@ struct Foo { } impl Foo { - pub fn f(&const self) {} + pub fn f(&self) {} } fn g(x: &mut Foo) { diff --git a/src/test/compile-fail/borrowck-pat-enum.rs b/src/test/run-pass/borrowck-pat-enum.rs similarity index 65% rename from src/test/compile-fail/borrowck-pat-enum.rs rename to src/test/run-pass/borrowck-pat-enum.rs index f1cca89b227d6..f320de39c8c3b 100644 --- a/src/test/compile-fail/borrowck-pat-enum.rs +++ b/src/test/run-pass/borrowck-pat-enum.rs @@ -1,3 +1,5 @@ +// xfail-pretty + // Copyright 2012 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. @@ -24,32 +26,9 @@ fn match_ref_unused(v: Option) { } } -fn match_const_reg(v: &const Option) -> int { - match *v { - Some(ref i) => {*i} //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - None => {0} - } -} - fn impure(_i: int) { } -fn match_const_reg_unused(v: &const Option) { - match *v { - Some(_) => {impure(0)} // OK because nothing is captured - None => {} - } -} - -fn match_const_reg_impure(v: &const Option) { - match *v { - Some(ref i) => {impure(*i)} //~ ERROR cannot borrow - //~^ ERROR unsafe borrow - None => {} - } -} - fn match_imm_reg(v: &Option) { match *v { Some(ref i) => {impure(*i)} // OK because immutable diff --git a/src/test/compile-fail/borrowck-uniq-via-ref.rs b/src/test/run-pass/borrowck-uniq-via-ref.rs similarity index 77% rename from src/test/compile-fail/borrowck-uniq-via-ref.rs rename to src/test/run-pass/borrowck-uniq-via-ref.rs index 8bf627d991911..44f3a8f518a15 100644 --- a/src/test/compile-fail/borrowck-uniq-via-ref.rs +++ b/src/test/run-pass/borrowck-uniq-via-ref.rs @@ -25,7 +25,6 @@ struct Innermost { } fn borrow(_v: &int) {} -fn borrow_const(_v: &const int) {} fn box_mut(v: &mut ~int) { borrow(*v); // OK: &mut -> &imm @@ -51,17 +50,5 @@ fn box_imm_recs(v: &Outer) { borrow(v.f.g.h); // OK } -fn box_const(v: &const ~int) { - borrow_const(*v); //~ ERROR unsafe borrow -} - -fn box_const_rec(v: &const Rec) { - borrow_const(v.f); //~ ERROR unsafe borrow -} - -fn box_const_recs(v: &const Outer) { - borrow_const(v.f.g.h); //~ ERROR unsafe borrow -} - fn main() { } diff --git a/src/test/run-pass/class-impl-very-parameterized-trait.rs b/src/test/run-pass/class-impl-very-parameterized-trait.rs index d42c57c3b81a0..725019fd9f516 100644 --- a/src/test/run-pass/class-impl-very-parameterized-trait.rs +++ b/src/test/run-pass/class-impl-very-parameterized-trait.rs @@ -51,8 +51,8 @@ impl cat { } impl Container for cat { - fn len(&const self) -> uint { self.meows as uint } - fn is_empty(&const self) -> bool { self.meows == 0 } + fn len(&self) -> uint { self.meows as uint } + fn is_empty(&self) -> bool { self.meows == 0 } } impl Mutable for cat { diff --git a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs index 438c70c6583f4..69e5d692d0d3d 100644 --- a/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs +++ b/src/test/run-pass/coerce-reborrow-imm-ptr-rcvr.rs @@ -3,14 +3,14 @@ struct SpeechMaker { } impl SpeechMaker { - pub fn how_many(&const self) -> uint { self.speeches } + pub fn how_many(&self) -> uint { self.speeches } } -fn foo(speaker: &const SpeechMaker) -> uint { +fn foo(speaker: &SpeechMaker) -> uint { speaker.how_many() + 33 } pub fn main() { let mut lincoln = SpeechMaker {speeches: 22}; - assert_eq!(foo(&const lincoln), 55); + assert_eq!(foo(&lincoln), 55); } diff --git a/src/test/run-pass/const-vec-syntax.rs b/src/test/run-pass/const-vec-syntax.rs index 625f6ec30cc13..84ee54cfdde6d 100644 --- a/src/test/run-pass/const-vec-syntax.rs +++ b/src/test/run-pass/const-vec-syntax.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -fn f(_: &const [int]) {} +fn f(_: &[int]) {} pub fn main() { let v = [ 1, 2, 3 ]; diff --git a/src/test/run-pass/deriving-zero.rs b/src/test/run-pass/deriving-zero.rs index 54895d1796f40..1dfb03f3c783b 100644 --- a/src/test/run-pass/deriving-zero.rs +++ b/src/test/run-pass/deriving-zero.rs @@ -38,5 +38,6 @@ struct Lots { } fn main() { - assert!(Zero::zero::().is_zero()); + let lots: Lots = Zero::zero(); + assert!(lots.is_zero()); } diff --git a/src/test/run-pass/float-nan.rs b/src/test/run-pass/float-nan.rs index 29a180db1855d..d59b8c77d0067 100644 --- a/src/test/run-pass/float-nan.rs +++ b/src/test/run-pass/float-nan.rs @@ -13,11 +13,12 @@ extern mod extra; use std::num::Float; pub fn main() { - let nan = Float::NaN::(); + let nan: float = Float::NaN(); assert!((nan).is_NaN()); - let inf = Float::infinity::(); - assert_eq!(-inf, Float::neg_infinity::()); + let inf: float = Float::infinity(); + let neg_inf: float = Float::neg_infinity(); + assert_eq!(-inf, neg_inf); assert!( nan != nan); assert!( nan != -nan); diff --git a/src/test/run-pass/issue-6898.rs b/src/test/run-pass/issue-6898.rs index 2d612bb742eb3..8e9502d6d49e6 100644 --- a/src/test/run-pass/issue-6898.rs +++ b/src/test/run-pass/issue-6898.rs @@ -1,3 +1,5 @@ +// xfail-test + // Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. diff --git a/src/test/run-pass/mid-path-type-params.rs b/src/test/run-pass/mid-path-type-params.rs new file mode 100644 index 0000000000000..1bc37a035e046 --- /dev/null +++ b/src/test/run-pass/mid-path-type-params.rs @@ -0,0 +1,33 @@ +struct S { + contents: T, +} + +impl S { + fn new(x: T, _: U) -> S { + S { + contents: x, + } + } +} + +trait Trait { + fn new(x: T, y: U) -> Self; +} + +struct S2 { + contents: int, +} + +impl Trait for S2 { + fn new(x: int, _: U) -> S2 { + S2 { + contents: x, + } + } +} + +fn main() { + let _ = S::::new::(1, 1.0); + let _: S2 = Trait::::new::(1, 1.0); +} + diff --git a/src/test/run-pass/trait-default-method-xc.rs b/src/test/run-pass/trait-default-method-xc.rs index 38b386838a1b4..9b7ff287e3c03 100644 --- a/src/test/run-pass/trait-default-method-xc.rs +++ b/src/test/run-pass/trait-default-method-xc.rs @@ -59,7 +59,7 @@ fn main () { assert_eq!(0i.thing(3.14, 1), (3.14, 1)); assert_eq!(B::staticthing(&0i, 3.14, 1), (3.14, 1)); - assert_eq!(B::staticthing::(&0i, 3.14, 1), (3.14, 1)); + assert_eq!(B::::staticthing::(&0i, 3.14, 1), (3.14, 1)); assert_eq!(g(0i, 3.14, 1), (3.14, 1)); assert_eq!(g(false, 3.14, 1), (3.14, 1)); diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index 1f5c33e2bc097..b79c97c6fbbb8 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -14,7 +14,7 @@ mod base { use std::io; pub trait HasNew { - fn new() -> T; + fn new() -> Self; } pub struct Foo { @@ -41,6 +41,6 @@ mod base { } pub fn main() { - let f: base::Foo = base::HasNew::new::(); - let b: base::Bar = base::HasNew::new::(); + let f: base::Foo = base::HasNew::::new(); + let b: base::Bar = base::HasNew::::new(); }