diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 701f8899fa4ef..c64bb180d4120 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -298,10 +298,11 @@ pub fn make_tests(config: &Config) -> Vec { let file = file.clone(); debug!("inspecting file {}", file.display()); if is_test(config, &file) { - let t = make_test(config, &file, || { + let file_ptr = &file; + let t = make_test(config, file_ptr, || { match config.mode { - Codegen => make_metrics_test_closure(config, &file), - _ => make_test_closure(config, &file) + Codegen => make_metrics_test_closure(config, file_ptr), + _ => make_test_closure(config, file_ptr) } }); tests.push(t) diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index 531f51f982f6b..105a9e391d16f 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -51,57 +51,71 @@ pub fn load_props(testfile: &Path) -> TestProps { let mut check_stdout = false; let mut no_prefer_dynamic = false; let mut no_pretty_expanded = false; - iter_header(testfile, |ln| { - match parse_error_pattern(ln) { - Some(ep) => error_patterns.push(ep), - None => () - }; - - if compile_flags.is_none() { - compile_flags = parse_compile_flags(ln); - } - if run_flags.is_none() { - run_flags = parse_run_flags(ln); - } + { + let error_patterns_ptr = &mut error_patterns; + let aux_builds_ptr = &mut aux_builds; + let exec_env_ptr = &mut exec_env; + let compile_flags_ptr = &mut compile_flags; + let run_flags_ptr = &mut run_flags; + let pp_exact_ptr = &mut pp_exact; + let check_lines_ptr = &mut check_lines; + let force_host_ptr = &mut force_host; + let check_stdout_ptr = &mut check_stdout; + let no_prefer_dynamic_ptr = &mut no_prefer_dynamic; + let no_pretty_expanded_ptr = &mut no_pretty_expanded; + iter_header(testfile, |ln| { + match parse_error_pattern(ln) { + Some(ep) => error_patterns_ptr.push(ep), + None => () + }; + + if compile_flags_ptr.is_none() { + *compile_flags_ptr = parse_compile_flags(ln); + } - if pp_exact.is_none() { - pp_exact = parse_pp_exact(ln, testfile); - } + if run_flags_ptr.is_none() { + *run_flags_ptr = parse_run_flags(ln); + } - if !force_host { - force_host = parse_force_host(ln); - } + if pp_exact_ptr.is_none() { + *pp_exact_ptr = parse_pp_exact(ln, testfile); + } - if !check_stdout { - check_stdout = parse_check_stdout(ln); - } + if !*force_host_ptr { + *force_host_ptr = parse_force_host(ln); + } - if !no_prefer_dynamic { - no_prefer_dynamic = parse_no_prefer_dynamic(ln); - } + if !*check_stdout_ptr { + *check_stdout_ptr = parse_check_stdout(ln); + } - if !no_pretty_expanded { - no_pretty_expanded = parse_no_pretty_expanded(ln); - } + if !*no_prefer_dynamic_ptr { + *no_prefer_dynamic_ptr = parse_no_prefer_dynamic(ln); + } - match parse_aux_build(ln) { - Some(ab) => { aux_builds.push(ab); } - None => {} - } + if !*no_pretty_expanded_ptr { + *no_pretty_expanded_ptr = parse_no_pretty_expanded(ln); + } - match parse_exec_env(ln) { - Some(ee) => { exec_env.push(ee); } - None => {} - } + match parse_aux_build(ln) { + Some(ab) => { aux_builds_ptr.push(ab); } + None => {} + } - match parse_check_line(ln) { - Some(cl) => check_lines.push(cl), - None => () - }; + match parse_exec_env(ln) { + Some(ee) => { exec_env_ptr.push(ee); } + None => {} + } - true - }); + match parse_check_line(ln) { + Some(cl) => check_lines_ptr.push(cl), + None => () + }; + + true + }); + } TestProps { error_patterns: error_patterns, diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 7ad302646b36c..ccd08591b6aaa 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -627,32 +627,38 @@ fn parse_debugger_commands(file_path: &Path, debugger_prefix: &str) let mut check_lines = vec!(); let mut counter = 1; let mut reader = BufferedReader::new(File::open(file_path).unwrap()); - for line in reader.lines() { - match line { - Ok(line) => { - if line.as_slice().contains("#break") { - breakpoint_lines.push(counter); - } - header::parse_name_value_directive( - line.as_slice(), - command_directive.to_string()).map(|cmd| { - commands.push(cmd) - }); + { + let breakpoint_lines_ptr = &mut breakpoint_lines; + let commands_ptr = &mut commands; + let check_lines_ptr = &mut check_lines; + for line in reader.lines() { + match line { + Ok(line) => { + if line.as_slice().contains("#break") { + breakpoint_lines_ptr.push(counter); + } - header::parse_name_value_directive( - line.as_slice(), - check_directive.to_string()).map(|cmd| { - check_lines.push(cmd) - }); - } - Err(e) => { - fatal(format_strbuf!("Error while parsing debugger commands: \ - {}", - e)) + header::parse_name_value_directive( + line.as_slice(), + command_directive.to_string()).map(|cmd| { + commands_ptr.push(cmd) + }); + + header::parse_name_value_directive( + line.as_slice(), + check_directive.to_string()).map(|cmd| { + check_lines_ptr.push(cmd) + }); + } + Err(e) => { + fatal(format_strbuf!("Error while parsing debugger commands: \ + {}", + e)) + } } + counter += 1; } - counter += 1; } DebuggerCommands { diff --git a/src/doc/guide-container.md b/src/doc/guide-container.md index 30bfd28d57ee0..9acb38ad5e6bd 100644 --- a/src/doc/guide-container.md +++ b/src/doc/guide-container.md @@ -184,8 +184,9 @@ let xs = [1,2,3,4,5]; let mut calls = 0; { + let calls_ref = &mut calls; let it = xs.iter().scan((), |_, x| { - calls += 1; + *calls_ref += 1; if *x < 3 { Some(x) } else { None }}); // the iterator will only yield 1 and 2 before returning None diff --git a/src/doc/tutorial.md b/src/doc/tutorial.md index 011d1b2b5db8f..79b05d37037f5 100644 --- a/src/doc/tutorial.md +++ b/src/doc/tutorial.md @@ -1838,7 +1838,8 @@ access local variables in the enclosing scope. ~~~~ let mut max = 0; -let f = |x: int| if x > max { max = x }; +let max_ref = &mut max; +let f = |x: int| if x > *max_ref { *max_ref = x }; for x in [1, 2, 3].iter() { f(*x); } diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 58d8bf289e173..c5de0d5690535 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -503,8 +503,9 @@ mod tests { #[bench] pub fn bench_copy(b: &mut Bencher) { let arena = TypedArena::new(); + let arena_ptr = &arena; b.iter(|| { - arena.alloc(Point { + arena_ptr.alloc(Point { x: 1, y: 2, z: 3, @@ -526,8 +527,9 @@ mod tests { #[bench] pub fn bench_copy_old_arena(b: &mut Bencher) { let arena = Arena::new(); + let arena_ptr = &arena; b.iter(|| { - arena.alloc(|| { + arena_ptr.alloc(|| { Point { x: 1, y: 2, @@ -545,8 +547,9 @@ mod tests { #[test] pub fn test_noncopy() { let arena = TypedArena::new(); + let arena_ptr = &arena; for _ in range(0, 100000) { - arena.alloc(Noncopy { + arena_ptr.alloc(Noncopy { string: "hello world".to_string(), array: vec!( 1, 2, 3, 4, 5 ), }); @@ -556,8 +559,9 @@ mod tests { #[bench] pub fn bench_noncopy(b: &mut Bencher) { let arena = TypedArena::new(); + let arena_ptr = &arena; b.iter(|| { - arena.alloc(Noncopy { + arena_ptr.alloc(Noncopy { string: "hello world".to_string(), array: vec!( 1, 2, 3, 4, 5 ), }) @@ -577,8 +581,9 @@ mod tests { #[bench] pub fn bench_noncopy_old_arena(b: &mut Bencher) { let arena = Arena::new(); + let arena_ptr = &arena; b.iter(|| { - arena.alloc(|| Noncopy { + arena_ptr.alloc(|| Noncopy { string: "hello world".to_string(), array: vec!( 1, 2, 3, 4, 5 ), }) diff --git a/src/libcollections/bitv.rs b/src/libcollections/bitv.rs index 0b5d499c533bc..4df9d96186ee0 100644 --- a/src/libcollections/bitv.rs +++ b/src/libcollections/bitv.rs @@ -699,10 +699,13 @@ impl BitvSet { /// Creates a new bit vector set from the given bit vector pub fn from_bitv(bitv: Bitv) -> BitvSet { let mut size = 0; - bitv.ones(|_| { - size += 1; - true - }); + { + let size_ptr = &mut size; + bitv.ones(|_| { + *size_ptr += 1; + true + }); + } let Bitv{rep, ..} = bitv; match rep { Big(b) => BitvSet{ size: size, bitv: b }, @@ -770,39 +773,51 @@ impl BitvSet { BitPositions {set: self, next_idx: 0} } - pub fn difference(&self, other: &BitvSet, f: |&uint| -> bool) -> bool { + pub fn difference(&self, + other: &BitvSet, + mut f: |&uint| -> bool) -> bool { + let f_ptr = &mut f; for (i, w1, w2) in self.commons(other) { - if !iterate_bits(i, w1 & !w2, |b| f(&b)) { + if !iterate_bits(i, w1 & !w2, |b| (*f_ptr)(&b)) { return false } }; /* everything we have that they don't also shows up */ self.outliers(other).advance(|(mine, i, w)| - !mine || iterate_bits(i, w, |b| f(&b)) + !mine || iterate_bits(i, w, |b| (*f_ptr)(&b)) ) } - pub fn symmetric_difference(&self, other: &BitvSet, f: |&uint| -> bool) + pub fn symmetric_difference(&self, + other: &BitvSet, + mut f: |&uint| -> bool) -> bool { + let f_ptr = &mut f; for (i, w1, w2) in self.commons(other) { - if !iterate_bits(i, w1 ^ w2, |b| f(&b)) { + if !iterate_bits(i, w1 ^ w2, |b| (*f_ptr)(&b)) { return false } }; - self.outliers(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b))) + self.outliers(other) + .advance(|(_, i, w)| iterate_bits(i, w, |b| (*f_ptr)(&b))) } - pub fn intersection(&self, other: &BitvSet, f: |&uint| -> bool) -> bool { - self.commons(other).advance(|(i, w1, w2)| iterate_bits(i, w1 & w2, |b| f(&b))) + pub fn intersection(&self, other: &BitvSet, mut f: |&uint| -> bool) + -> bool { + let f_ptr = &mut f; + self.commons(other) + .advance(|(i, w1, w2)| iterate_bits(i, w1 & w2, |b| (*f_ptr)(&b))) } - pub fn union(&self, other: &BitvSet, f: |&uint| -> bool) -> bool { + pub fn union(&self, other: &BitvSet, mut f: |&uint| -> bool) -> bool { + let f_ptr = &mut f; for (i, w1, w2) in self.commons(other) { - if !iterate_bits(i, w1 | w2, |b| f(&b)) { + if !iterate_bits(i, w1 | w2, |b| (*f_ptr)(&b)) { return false } }; - self.outliers(other).advance(|(_, i, w)| iterate_bits(i, w, |b| f(&b))) + self.outliers(other) + .advance(|(_, i, w)| iterate_bits(i, w, |b| (*f_ptr)(&b))) } } @@ -1462,13 +1477,14 @@ mod tests { assert!(b.insert(3)); let mut i = 0; + let i_ptr = &mut i; let expected = [3, 5, 11, 77]; a.intersection(&b, |x| { - assert_eq!(*x, expected[i]); - i += 1; + assert_eq!(*x, expected[*i_ptr]); + *i_ptr += 1; true }); - assert_eq!(i, expected.len()); + assert_eq!(*i_ptr, expected.len()); } #[test] @@ -1487,12 +1503,13 @@ mod tests { let mut i = 0; let expected = [1, 5, 500]; + let i_ptr = &mut i; a.difference(&b, |x| { - assert_eq!(*x, expected[i]); - i += 1; + assert_eq!(*x, expected[*i_ptr]); + *i_ptr += 1; true }); - assert_eq!(i, expected.len()); + assert_eq!(*i_ptr, expected.len()); } #[test] @@ -1512,13 +1529,14 @@ mod tests { assert!(b.insert(220)); let mut i = 0; + let i_ptr = &mut i; let expected = [1, 5, 11, 14, 220]; a.symmetric_difference(&b, |x| { - assert_eq!(*x, expected[i]); - i += 1; + assert_eq!(*x, expected[*i_ptr]); + *i_ptr += 1; true }); - assert_eq!(i, expected.len()); + assert_eq!(*i_ptr, expected.len()); } #[test] @@ -1542,12 +1560,13 @@ mod tests { let mut i = 0; let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160]; + let i_ptr = &mut i; a.union(&b, |x| { - assert_eq!(*x, expected[i]); - i += 1; + assert_eq!(*x, expected[*i_ptr]); + *i_ptr += 1; true }); - assert_eq!(i, expected.len()); + assert_eq!(*i_ptr, expected.len()); } #[test] @@ -1638,9 +1657,10 @@ mod tests { fn bench_uint_small(b: &mut Bencher) { let mut r = rng(); let mut bitv = 0 as uint; + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv |= 1 << ((r.next_u32() as uint) % uint::BITS); - &bitv + *bitv_ptr |= 1 << ((r_ptr.next_u32() as uint) % uint::BITS); }) } @@ -1648,9 +1668,10 @@ mod tests { fn bench_small_bitv_small(b: &mut Bencher) { let mut r = rng(); let mut bitv = SmallBitv::new(uint::BITS); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.set((r.next_u32() as uint) % uint::BITS, true); - &bitv + bitv_ptr.set((r_ptr.next_u32() as uint) % uint::BITS, true); }) } @@ -1658,9 +1679,10 @@ mod tests { fn bench_big_bitv_small(b: &mut Bencher) { let mut r = rng(); let mut bitv = BigBitv::new(vec!(0)); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.set((r.next_u32() as uint) % uint::BITS, true); - &bitv + bitv_ptr.set((r_ptr.next_u32() as uint) % uint::BITS, true); }) } @@ -1670,9 +1692,10 @@ mod tests { let mut storage = vec!(); storage.grow(BENCH_BITS / uint::BITS, &0u); let mut bitv = BigBitv::new(storage); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.set((r.next_u32() as uint) % BENCH_BITS, true); - &bitv + bitv_ptr.set((r_ptr.next_u32() as uint) % BENCH_BITS, true); }) } @@ -1680,9 +1703,10 @@ mod tests { fn bench_bitv_big(b: &mut Bencher) { let mut r = rng(); let mut bitv = Bitv::new(BENCH_BITS, false); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.set((r.next_u32() as uint) % BENCH_BITS, true); - &bitv + bitv_ptr.set((r_ptr.next_u32() as uint) % BENCH_BITS, true); }) } @@ -1690,9 +1714,10 @@ mod tests { fn bench_bitv_small(b: &mut Bencher) { let mut r = rng(); let mut bitv = Bitv::new(uint::BITS, false); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.set((r.next_u32() as uint) % uint::BITS, true); - &bitv + bitv_ptr.set((r_ptr.next_u32() as uint) % uint::BITS, true); }) } @@ -1700,9 +1725,10 @@ mod tests { fn bench_bitv_set_small(b: &mut Bencher) { let mut r = rng(); let mut bitv = BitvSet::new(); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.insert((r.next_u32() as uint) % uint::BITS); - &bitv + bitv_ptr.insert((r_ptr.next_u32() as uint) % uint::BITS); }) } @@ -1710,9 +1736,10 @@ mod tests { fn bench_bitv_set_big(b: &mut Bencher) { let mut r = rng(); let mut bitv = BitvSet::new(); + let bitv_ptr = &mut bitv; + let r_ptr = &mut r; b.iter(|| { - bitv.insert((r.next_u32() as uint) % BENCH_BITS); - &bitv + bitv_ptr.insert((r_ptr.next_u32() as uint) % BENCH_BITS); }) } @@ -1720,8 +1747,9 @@ mod tests { fn bench_bitv_big_union(b: &mut Bencher) { let mut b1 = Bitv::new(BENCH_BITS, false); let b2 = Bitv::new(BENCH_BITS, false); + let b1_ptr = &mut b1; b.iter(|| { - b1.union(&b2); + b1_ptr.union(&b2); }) } diff --git a/src/libcollections/btree.rs b/src/libcollections/btree.rs index 184a59303f3a4..a334da43b83b5 100644 --- a/src/libcollections/btree.rs +++ b/src/libcollections/btree.rs @@ -373,9 +373,11 @@ impl Leaf { if self.elts.len() > ub { let midpoint_opt = self.elts.remove(ub / 2); let midpoint = midpoint_opt.unwrap(); - let (left_leaf, right_leaf) = self.elts.partition(|le| - le.key.cmp(&midpoint.key.clone()) - == Less); + let (left_leaf, right_leaf) = { + let midpoint_ptr = &midpoint; + self.elts.partition(|le| le.key.cmp(&midpoint_ptr.key.clone()) + == Less) + }; let branch_return = Node::new_branch(vec!(BranchElt::new(midpoint.key.clone(), midpoint.value.clone(), box Node::new_leaf(left_leaf))), @@ -600,9 +602,12 @@ impl Branch { //and two children. if self.elts.len() > ub { let midpoint = self.elts.remove(ub / 2).unwrap(); - let (new_left, new_right) = self.clone().elts.partition(|le| - midpoint.key.cmp(&le.key) - == Greater); + let (new_left, new_right) = { + let midpoint_ptr = &midpoint; + self.clone().elts.partition(|le| { + midpoint_ptr.key.cmp(&le.key) == Greater + }) + }; new_branch = Node::new_branch( vec!(BranchElt::new(midpoint.clone().key, midpoint.clone().value, diff --git a/src/libcollections/deque.rs b/src/libcollections/deque.rs index e031b07f87296..0458f3d84f4c3 100644 --- a/src/libcollections/deque.rs +++ b/src/libcollections/deque.rs @@ -59,8 +59,9 @@ pub mod bench { } // measure + let rng_ptr = &mut rng; b.iter(|| { - let k = rng.gen::() % n; + let k = rng_ptr.gen::() % n; map.insert(k, 1); map.remove(&k); }) @@ -77,10 +78,11 @@ pub mod bench { // measure let mut i = 1; + let i_ptr = &mut i; b.iter(|| { - map.insert(i, 1); - map.remove(&i); - i = (i + 2) % n; + map.insert(*i_ptr, 1); + map.remove(i_ptr); + *i_ptr = (*i_ptr + 2) % n; }) } @@ -89,19 +91,21 @@ pub mod bench { b: &mut Bencher) { // setup let mut rng = rand::weak_rng(); - let mut keys = Vec::from_fn(n, |_| rng.gen::() % n); + let rng_ptr = &mut rng; + let mut keys = Vec::from_fn(n, |_| rng_ptr.gen::() % n); for k in keys.iter() { map.insert(*k, 1); } - rng.shuffle(keys.as_mut_slice()); + rng_ptr.shuffle(keys.as_mut_slice()); // measure let mut i = 0; + let i_ptr = &mut i; b.iter(|| { - map.find(keys.get(i)); - i = (i + 1) % n; + map.find(keys.get(*i_ptr)); + *i_ptr = (*i_ptr + 1) % n; }) } @@ -115,9 +119,10 @@ pub mod bench { // measure let mut i = 0; + let i_ptr = &mut i; b.iter(|| { - let x = map.find(&i); - i = (i + 1) % n; + let x = map.find(i_ptr); + *i_ptr = (*i_ptr + 1) % n; x }) } diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs index 8072ee02bc012..6cdf03f30e641 100644 --- a/src/libcollections/dlist.rs +++ b/src/libcollections/dlist.rs @@ -1069,54 +1069,60 @@ mod tests { #[bench] fn bench_push_front(b: &mut test::Bencher) { let mut m: DList = DList::new(); + let m_ptr = &mut m; b.iter(|| { - m.push_front(0); + m_ptr.push_front(0); }) } #[bench] fn bench_push_back(b: &mut test::Bencher) { let mut m: DList = DList::new(); + let m_ptr = &mut m; b.iter(|| { - m.push_back(0); + m_ptr.push_back(0); }) } #[bench] fn bench_push_back_pop_back(b: &mut test::Bencher) { let mut m: DList = DList::new(); + let m_ptr = &mut m; b.iter(|| { - m.push_back(0); - m.pop_back(); + m_ptr.push_back(0); + m_ptr.pop_back(); }) } #[bench] fn bench_push_front_pop_front(b: &mut test::Bencher) { let mut m: DList = DList::new(); + let m_ptr = &mut m; b.iter(|| { - m.push_front(0); - m.pop_front(); + m_ptr.push_front(0); + m_ptr.pop_front(); }) } #[bench] fn bench_rotate_forward(b: &mut test::Bencher) { let mut m: DList = DList::new(); - m.push_front(0); - m.push_front(1); + let m_ptr = &mut m; + m_ptr.push_front(0); + m_ptr.push_front(1); b.iter(|| { - m.rotate_forward(); + m_ptr.rotate_forward(); }) } #[bench] fn bench_rotate_backward(b: &mut test::Bencher) { let mut m: DList = DList::new(); - m.push_front(0); - m.push_front(1); + let m_ptr = &mut m; + m_ptr.push_front(0); + m_ptr.push_front(1); b.iter(|| { - m.rotate_backward(); + m_ptr.rotate_backward(); }) } @@ -1124,32 +1130,36 @@ mod tests { fn bench_iter(b: &mut test::Bencher) { let v = &[0, ..128]; let m: DList = v.iter().map(|&x|x).collect(); + let m_ptr = &m; b.iter(|| { - assert!(m.iter().len() == 128); + assert!(m_ptr.iter().len() == 128); }) } #[bench] fn bench_iter_mut(b: &mut test::Bencher) { let v = &[0, ..128]; let mut m: DList = v.iter().map(|&x|x).collect(); + let m_ptr = &mut m; b.iter(|| { - assert!(m.mut_iter().len() == 128); + assert!(m_ptr.mut_iter().len() == 128); }) } #[bench] fn bench_iter_rev(b: &mut test::Bencher) { let v = &[0, ..128]; let m: DList = v.iter().map(|&x|x).collect(); + let m_ptr = &m; b.iter(|| { - assert!(m.iter().rev().len() == 128); + assert!(m_ptr.iter().rev().len() == 128); }) } #[bench] fn bench_iter_mut_rev(b: &mut test::Bencher) { let v = &[0, ..128]; let mut m: DList = v.iter().map(|&x|x).collect(); + let m_ptr = &mut m; b.iter(|| { - assert!(m.mut_iter().rev().len() == 128); + assert!(m_ptr.mut_iter().rev().len() == 128); }) } } diff --git a/src/libcollections/hashmap.rs b/src/libcollections/hashmap.rs index 42b57a1ea4063..27aeda013398a 100644 --- a/src/libcollections/hashmap.rs +++ b/src/libcollections/hashmap.rs @@ -2370,10 +2370,12 @@ mod bench { } let mut k = 1001; + let k_ptr = &mut k; + let m_ptr = &mut m; b.iter(|| { - m.insert(k, k); - k += 1; + m_ptr.insert(*k_ptr, *k_ptr); + *k_ptr += 1; }); } @@ -2387,9 +2389,10 @@ mod bench { m.insert(i, i); } + let m_ptr = &mut m; b.iter(|| { for i in range_inclusive(1, 1000) { - m.contains_key(&i); + m_ptr.contains_key(&i); } }); } @@ -2404,9 +2407,10 @@ mod bench { m.insert(i, i); } + let m_ptr = &mut m; b.iter(|| { for i in range_inclusive(1001, 2000) { - m.contains_key(&i); + m_ptr.contains_key(&i); } }); } @@ -2422,11 +2426,13 @@ mod bench { } let mut k = 1; + let k_ptr = &mut k; + let m_ptr = &mut m; b.iter(|| { - m.pop(&k); - m.insert(k + 1000, k + 1000); - k += 1; + m_ptr.pop(k_ptr); + m_ptr.insert(*k_ptr + 1000, *k_ptr + 1000); + *k_ptr += 1; }); } @@ -2441,13 +2447,15 @@ mod bench { } let mut k = 1; + let k_ptr = &mut k; + let m_ptr = &mut m; b.iter(|| { - m.find(&(k + 400)); - m.find(&(k + 2000)); - m.pop(&k); - m.insert(k + 1000, k + 1000); - k += 1; + m_ptr.find(&(*k_ptr + 400)); + m_ptr.find(&(*k_ptr + 2000)); + m_ptr.pop(k_ptr); + m_ptr.insert(*k_ptr + 1000, *k_ptr + 1000); + *k_ptr += 1; }) } } diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index f45c9685be58b..86ef15ff72f41 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -545,25 +545,28 @@ mod tests { #[bench] fn bench_push_back(b: &mut test::Bencher) { let mut deq = RingBuf::new(); + let deq_ptr = &mut deq; b.iter(|| { - deq.push_back(0); + deq_ptr.push_back(0); }) } #[bench] fn bench_push_front(b: &mut test::Bencher) { let mut deq = RingBuf::new(); + let deq_ptr = &mut deq; b.iter(|| { - deq.push_front(0); + deq_ptr.push_front(0); }) } #[bench] fn bench_grow(b: &mut test::Bencher) { let mut deq = RingBuf::new(); + let deq_ptr = &mut deq; b.iter(|| { for _ in range(0, 65) { - deq.push_front(1); + deq_ptr.push_front(1); } }) } diff --git a/src/libcollections/treemap.rs b/src/libcollections/treemap.rs index fb663d91131af..1dfcfb24e311d 100644 --- a/src/libcollections/treemap.rs +++ b/src/libcollections/treemap.rs @@ -813,7 +813,8 @@ impl TreeNode { // Remove left horizontal link by rotating right fn skew(node: &mut Box>) { - if node.left.as_ref().map_or(false, |x| x.level == node.level) { + let node_level = node.level; + if node.left.as_ref().map_or(false, |x| x.level == node_level) { let mut save = node.left.take_unwrap(); swap(&mut node.left, &mut save.right); // save.right now None swap(node, &mut save); @@ -824,8 +825,9 @@ fn skew(node: &mut Box>) { // Remove dual horizontal link by rotating left and increasing level of // the parent fn split(node: &mut Box>) { + let node_level = node.level; if node.right.as_ref().map_or(false, - |x| x.right.as_ref().map_or(false, |y| y.level == node.level)) { + |x| x.right.as_ref().map_or(false, |y| y.level == node_level)) { let mut save = node.right.take_unwrap(); swap(&mut node.right, &mut save.left); // save.left now None save.level += 1; @@ -1134,7 +1136,7 @@ mod test_treemap { #[test] fn test_rand_int() { let mut map: TreeMap = TreeMap::new(); - let mut ctrl = vec![]; + let mut ctrl: Vec<(int,int)> = vec![]; check_equal(ctrl.as_slice(), &map); assert!(map.find(&5).is_none()); @@ -1143,8 +1145,8 @@ mod test_treemap { for _ in range(0, 3) { for _ in range(0, 90) { - let k = rng.gen(); - let v = rng.gen(); + let k: int = rng.gen(); + let v: int = rng.gen(); if !ctrl.iter().any(|x| x == &(k, v)) { assert!(map.insert(k, v)); ctrl.push((k, v)); @@ -1642,12 +1644,13 @@ mod test_set { for y in b.iter() { assert!(set_b.insert(*y)) } let mut i = 0; + let i_ptr = &mut i; f(&set_a, &set_b, |x| { - assert_eq!(*x, expected[i]); - i += 1; + assert_eq!(*x, expected[*i_ptr]); + *i_ptr += 1; true }); - assert_eq!(i, expected.len()); + assert_eq!(*i_ptr, expected.len()); } #[test] diff --git a/src/libcollections/trie.rs b/src/libcollections/trie.rs index 9d64b3c2394b0..7457acfc428bc 100644 --- a/src/libcollections/trie.rs +++ b/src/libcollections/trie.rs @@ -394,11 +394,16 @@ impl TrieNode { } impl TrieNode { - fn each_reverse<'a>(&'a self, f: |&uint, &'a T| -> bool) -> bool { + fn each_reverse<'a>(&'a self, mut f: |&uint, &'a T| -> bool) -> bool { + let f_ptr = &mut f; for elt in self.children.iter().rev() { match *elt { - Internal(ref x) => if !x.each_reverse(|i,t| f(i,t)) { return false }, - External(k, ref v) => if !f(&k, v) { return false }, + Internal(ref x) => { + if !x.each_reverse(|i,t| (*f_ptr)(i,t)) { + return false + } + } + External(k, ref v) => if !(*f_ptr)(&k, v) { return false }, Nothing => () } } @@ -730,10 +735,11 @@ mod test_map { assert!(m.insert(1, 2)); let mut n = 4; + let n_ptr = &mut n; m.each_reverse(|k, v| { - assert_eq!(*k, n); - assert_eq!(*v, n * 2); - n -= 1; + assert_eq!(*k, *n_ptr); + assert_eq!(*v, *n_ptr * 2); + *n_ptr -= 1; true }); } @@ -747,13 +753,14 @@ mod test_map { } let mut n = uint::MAX - 1; + let n_ptr = &mut n; m.each_reverse(|k, v| { - if n == uint::MAX - 5000 { false } else { - assert!(n > uint::MAX - 5000); + if *n_ptr == uint::MAX - 5000 { false } else { + assert!(*n_ptr > uint::MAX - 5000); - assert_eq!(*k, n); - assert_eq!(*v, n / 2); - n -= 1; + assert_eq!(*k, *n_ptr); + assert_eq!(*v, *n_ptr / 2); + *n_ptr -= 1; true } }); @@ -948,9 +955,11 @@ mod bench_map { m.insert(rng.gen(), rng.gen()); } + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 10) { - m.lower_bound(rng.gen()); + m_ptr.lower_bound(rng_ptr.gen()); } }); } @@ -963,9 +972,11 @@ mod bench_map { m.insert(rng.gen(), rng.gen()); } + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 10) { - m.upper_bound(rng.gen()); + m_ptr.upper_bound(rng_ptr.gen()); } }); } @@ -975,9 +986,11 @@ mod bench_map { let mut m = TrieMap::<[uint, .. 10]>::new(); let mut rng = weak_rng(); + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 1000) { - m.insert(rng.gen(), [1, .. 10]); + m_ptr.insert(rng_ptr.gen(), [1, .. 10]); } }) } @@ -986,10 +999,12 @@ mod bench_map { let mut m = TrieMap::<[uint, .. 10]>::new(); let mut rng = weak_rng(); + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 1000) { // only have the last few bits set. - m.insert(rng.gen::() & 0xff_ff, [1, .. 10]); + m_ptr.insert(rng_ptr.gen::() & 0xff_ff, [1, .. 10]); } }) } @@ -999,9 +1014,11 @@ mod bench_map { let mut m = TrieMap::<()>::new(); let mut rng = weak_rng(); + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 1000) { - m.insert(rng.gen(), ()); + m_ptr.insert(rng_ptr.gen(), ()); } }) } @@ -1010,10 +1027,12 @@ mod bench_map { let mut m = TrieMap::<()>::new(); let mut rng = weak_rng(); + let m_ptr = &mut m; + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, 1000) { // only have the last few bits set. - m.insert(rng.gen::() & 0xff_ff, ()); + m_ptr.insert(rng_ptr.gen::() & 0xff_ff, ()); } }) } diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 0c5d3151af0f5..3ce80d97f3eff 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -714,7 +714,10 @@ mod test { fn test_escape_default() { fn string(c: char) -> String { let mut result = String::new(); - escape_default(c, |c| { result.push_char(c); }); + { + let result_ptr = &mut result; + escape_default(c, |c| { result_ptr.push_char(c); }); + } return result; } let s = string('\n'); @@ -749,7 +752,10 @@ mod test { fn test_escape_unicode() { fn string(c: char) -> String { let mut result = String::new(); - escape_unicode(c, |c| { result.push_char(c); }); + { + let result_ptr = &mut result; + escape_unicode(c, |c| { result_ptr.push_char(c); }); + } return result; } let s = string('\x00'); diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index e5fb148aded34..f8a0a4e6fc690 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -351,15 +351,16 @@ pub fn float_to_str_bytes_common( } let mut filler = Filler { buf: buf, end: &mut end }; + let filler = &mut filler; match sign { SignNeg => { let _ = format_args!(|args| { - fmt::write(&mut filler, args) + fmt::write(&mut *filler, args) }, "{:-}", exp); } SignNone | SignAll => { let _ = format_args!(|args| { - fmt::write(&mut filler, args) + fmt::write(&mut *filler, args) }, "{}", exp); } } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 731911185ff7e..701648b288bcd 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -404,31 +404,36 @@ mod bench { #[bench] fn format_bin(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:t}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:t}", rng_ptr.gen::()); }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:o}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:o}", rng_ptr.gen::()); }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:u}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:u}", rng_ptr.gen::()); }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:x}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:x}", rng_ptr.gen::()); }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{}", radix(rng_ptr.gen::(), 36)); }) } } @@ -440,31 +445,36 @@ mod bench { #[bench] fn format_bin(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:t}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:t}", rng_ptr.gen::()); }) } #[bench] fn format_oct(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:o}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:o}", rng_ptr.gen::()); }) } #[bench] fn format_dec(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:d}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:d}", rng_ptr.gen::()); }) } #[bench] fn format_hex(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{:x}", rng.gen::()); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{:x}", rng_ptr.gen::()); }) } #[bench] fn format_base_36(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { format!("{}", radix(rng.gen::(), 36)); }) + let rng_ptr = &mut rng; + b.iter(|| { format!("{}", radix(rng_ptr.gen::(), 36)); }) } } } diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index e58ef49c17fa6..9481bfe70da4f 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -2530,13 +2530,14 @@ mod tests { fn test_inspect() { let xs = [1u, 2, 3, 4]; let mut n = 0; + let n_ptr = &mut n; let ys = xs.iter() .map(|&x| x) - .inspect(|_| n += 1) + .inspect(|_| *n_ptr += 1) .collect::>(); - assert_eq!(n, xs.len()); + assert_eq!(*n_ptr, xs.len()); assert_eq!(xs.as_slice(), ys.as_slice()); } @@ -2838,11 +2839,12 @@ mod tests { fn test_rposition_fail() { let v = [(box 0, @0), (box 0, @0), (box 0, @0), (box 0, @0)]; let mut i = 0; + let i_ptr = &mut i; v.iter().rposition(|_elt| { - if i == 2 { + if *i_ptr == 2 { fail!() } - i += 1; + *i_ptr += 1; false }); } @@ -2854,9 +2856,10 @@ mod tests { let mut b = a.clone(); assert_eq!(len, b.indexable()); let mut n = 0; + let n_ptr = &mut n; for (i, elt) in a.enumerate() { assert!(Some(elt) == b.idx(i)); - n += 1; + *n_ptr += 1; } assert_eq!(n, len); assert!(None == b.idx(n)); @@ -2872,7 +2875,11 @@ mod tests { fn test_double_ended_flat_map() { let u = [0u,1]; let v = [5,6,7,8]; - let mut it = u.iter().flat_map(|x| v.slice(*x, v.len()).iter()); + let v_ptr = &v; + let mut it = u.iter() + .flat_map(|x| { + v_ptr.slice(*x, v_ptr.len()).iter() + }); assert_eq!(it.next_back().unwrap(), &8); assert_eq!(it.next().unwrap(), &5); assert_eq!(it.next_back().unwrap(), &7); diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 975736cb40cef..3f1d6fdb042c6 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -732,15 +732,16 @@ mod tests { #[test] fn test_option_while_some() { let mut i = 0; + let i_ptr = &mut i; Some(10).while_some(|j| { - i += 1; + *i_ptr += 1; if j > 0 { Some(j-1) } else { None } }); - assert_eq!(i, 11); + assert_eq!(*i_ptr, 11); } #[test] diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 34596480273c3..0bbc5140941de 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -651,16 +651,18 @@ pub mod ptr_tests { let mut ctr = 0; let mut iteration_count = 0; + let ctr_ptr = &mut ctr; + let iteration_count_ptr = &mut iteration_count; array_each_with_len(arr.as_ptr(), arr.len(), |e| { let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { + let expected = expected_arr[*ctr_ptr].with_ref(|buf| { str::raw::from_c_str(buf) }); assert_eq!(actual.as_slice(), expected.as_slice()); - ctr += 1; - iteration_count += 1; + *ctr_ptr += 1; + *iteration_count_ptr += 1; }); - assert_eq!(iteration_count, 3u); + assert_eq!(*iteration_count_ptr, 3u); } } @@ -684,16 +686,18 @@ pub mod ptr_tests { let arr_ptr = arr.as_ptr(); let mut ctr = 0; let mut iteration_count = 0; + let ctr_ptr = &mut ctr; + let iteration_count_ptr = &mut iteration_count; array_each(arr_ptr, |e| { let actual = str::raw::from_c_str(e); - let expected = expected_arr[ctr].with_ref(|buf| { + let expected = expected_arr[*ctr_ptr].with_ref(|buf| { str::raw::from_c_str(buf) }); assert_eq!(actual.as_slice(), expected.as_slice()); - ctr += 1; - iteration_count += 1; + *ctr_ptr += 1; + *iteration_count_ptr += 1; }); - assert_eq!(iteration_count, 3); + assert_eq!(*iteration_count_ptr, 3); } } diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 8b8ddbe847c01..08dcce8ffc03c 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -1779,11 +1779,12 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn trim_chars(&self, mut to_trim: C) -> &'a str { - let cur = match self.find(|c: char| !to_trim.matches(c)) { + let to_trim = &mut to_trim; + let cur = match self.find(|c: char| !(*to_trim).matches(c)) { None => "", Some(i) => unsafe { raw::slice_bytes(*self, i, self.len()) } }; - match cur.rfind(|c: char| !to_trim.matches(c)) { + match cur.rfind(|c: char| !(*to_trim).matches(c)) { None => "", Some(i) => { let right = cur.char_range_at(i).next; @@ -1794,7 +1795,8 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn trim_left_chars(&self, mut to_trim: C) -> &'a str { - match self.find(|c: char| !to_trim.matches(c)) { + let to_trim = &mut to_trim; + match self.find(|c: char| !(*to_trim).matches(c)) { None => "", Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) } } @@ -1802,7 +1804,8 @@ impl<'a> StrSlice<'a> for &'a str { #[inline] fn trim_right_chars(&self, mut to_trim: C) -> &'a str { - match self.rfind(|c: char| !to_trim.matches(c)) { + let to_trim = &mut to_trim; + match self.rfind(|c: char| !(*to_trim).matches(c)) { None => "", Some(last) => { let next = self.char_range_at(last).next; @@ -1887,22 +1890,28 @@ impl<'a> StrSlice<'a> for &'a str { } fn find(&self, mut search: C) -> Option { + let search = &mut search; if search.only_ascii() { - self.bytes().position(|b| search.matches(b as char)) + self.bytes().position(|b| (*search).matches(b as char)) } else { for (index, c) in self.char_indices() { - if search.matches(c) { return Some(index); } + if (*search).matches(c) { + return Some(index); + } } None } } fn rfind(&self, mut search: C) -> Option { + let search = &mut search; if search.only_ascii() { - self.bytes().rposition(|b| search.matches(b as char)) + self.bytes().rposition(|b| (*search).matches(b as char)) } else { for (index, c) in self.char_indices().rev() { - if search.matches(c) { return Some(index); } + if (*search).matches(c) { + return Some(index); + } } None } diff --git a/src/libcore/unicode.rs b/src/libcore/unicode.rs index 242672de2967a..127b3b5624eb0 100644 --- a/src/libcore/unicode.rs +++ b/src/libcore/unicode.rs @@ -2126,7 +2126,7 @@ pub mod normalization { pub fn decompose_compatible(c: char, i: |char|) { d(c, i, true); } - fn d(c: char, i: |char|, k: bool) { + fn d(c: char, mut i: |char|, k: bool) { use iter::Iterator; // 7-bit ASCII never decomposes @@ -2142,7 +2142,8 @@ pub mod normalization { match bsearch_table(c, canonical_table) { Some(canon) => { for x in canon.iter() { - d(*x, |b| i(b), k); + let i = &mut i; + d(*x, |b| (*i)(b), k); } return; } @@ -2156,7 +2157,8 @@ pub mod normalization { match bsearch_table(c, compatibility_table) { Some(compat) => { for x in compat.iter() { - d(*x, |b| i(b), k); + let f = &mut i; + d(*x, |b| (*f)(b), k); } return; } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index c88b825811f51..d112b5ea8d381 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -374,15 +374,20 @@ fn is_arg(arg: &str) -> bool { } fn find_opt(opts: &[Opt], nm: Name) -> Option { + let nm_ptr = &nm; + // Search main options. - let pos = opts.iter().position(|opt| opt.name == nm); + let pos = opts.iter().position(|opt| opt.name == *nm_ptr); if pos.is_some() { return pos } // Search in aliases. for candidate in opts.iter() { - if candidate.aliases.iter().position(|opt| opt.name == nm).is_some() { + if candidate.aliases + .iter() + .position(|opt| opt.name == *nm_ptr) + .is_some() { return opts.iter().position(|opt| opt.name == candidate.name); } } @@ -726,16 +731,17 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // FIXME: #5516 should be graphemes not codepoints let mut desc_rows = Vec::new(); + let desc_rows_ptr = &mut desc_rows; each_split_within(desc_normalized_whitespace.as_slice(), 54, |substr| { - desc_rows.push(substr.to_string()); + desc_rows_ptr.push(substr.to_string()); true }); // FIXME: #5516 should be graphemes not codepoints // wrapped description - row.push_str(desc_rows.connect(desc_sep.as_slice()).as_slice()); + row.push_str(desc_rows_ptr.connect(desc_sep.as_slice()).as_slice()); row }); @@ -830,6 +836,11 @@ fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) let mut fake_i = ss.len(); let mut lim = lim; + let slice_start_ptr = &mut slice_start; + let last_start_ptr = &mut last_start; + let last_end_ptr = &mut last_end; + let state_ptr = &mut state; + let mut cont = true; // if the limit is larger than the string, lower it to save cycles @@ -837,46 +848,46 @@ fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) lim = fake_i; } - let machine: |&mut bool, (uint, char)| -> bool = |cont, (i, c)| { + let mut machine: |&mut bool, (uint, char)| -> bool = |cont, (i, c)| { let whitespace = if ::std::char::is_whitespace(c) { Ws } else { Cr }; - let limit = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim }; + let limit = if (i - *slice_start_ptr + 1) <= lim { UnderLim } else { OverLim }; - state = match (state, whitespace, limit) { - (A, Ws, _) => { A } - (A, Cr, _) => { slice_start = i; last_start = i; B } + *state_ptr = match (*state_ptr, whitespace, limit) { + (A, Ws, _) => { A } + (A, Cr, _) => { *slice_start_ptr = i; *last_start_ptr = i; B } (B, Cr, UnderLim) => { B } - (B, Cr, OverLim) if (i - last_start + 1) > lim + (B, Cr, OverLim) if (i - *last_start_ptr + 1) > lim => fail!("word starting with {} longer than limit!", - ss.slice(last_start, i + 1)), + ss.slice(*last_start_ptr, i + 1)), (B, Cr, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); - slice_start = last_start; + *cont = it(ss.slice(*slice_start_ptr, *last_end_ptr)); + *slice_start_ptr = *last_start_ptr; B } (B, Ws, UnderLim) => { - last_end = i; + *last_end_ptr = i; C } (B, Ws, OverLim) => { - last_end = i; - *cont = it(ss.slice(slice_start, last_end)); + *last_end_ptr = i; + *cont = it(ss.slice(*slice_start_ptr, *last_end_ptr)); A } (C, Cr, UnderLim) => { - last_start = i; + *last_start_ptr = i; B } (C, Cr, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); - slice_start = i; - last_start = i; - last_end = i; + *cont = it(ss.slice(*slice_start_ptr, *last_end_ptr)); + *slice_start_ptr = i; + *last_start_ptr = i; + *last_end_ptr = i; B } (C, Ws, OverLim) => { - *cont = it(ss.slice(slice_start, last_end)); + *cont = it(ss.slice(*slice_start_ptr, *last_end_ptr)); A } (C, Ws, UnderLim) => { @@ -887,21 +898,26 @@ fn each_split_within<'a>(ss: &'a str, lim: uint, it: |&'a str| -> bool) *cont }; - ss.char_indices().advance(|x| machine(&mut cont, x)); + let machine_ptr = &mut machine; + let cont_ptr = &mut cont; + ss.char_indices().advance(|x| (*machine_ptr)(cont_ptr, x)); // Let the automaton 'run out' by supplying trailing whitespace - while cont && match state { B | C => true, A => false } { - machine(&mut cont, (fake_i, ' ')); + while *cont_ptr && match *state_ptr { B | C => true, A => false } { + (*machine_ptr)(cont_ptr, (fake_i, ' ')); fake_i += 1; } - return cont; + return *cont_ptr; } #[test] fn test_split_within() { fn t(s: &str, i: uint, u: &[String]) { let mut v = Vec::new(); - each_split_within(s, i, |s| { v.push(s.to_string()); true }); + { + let v_ptr = &mut v; + each_split_within(s, i, |s| { v_ptr.push(s.to_string()); true }); + } assert!(v.iter().zip(u.iter()).all(|(a,b)| a == b)); } t("", 0, []); diff --git a/src/libglob/lib.rs b/src/libglob/lib.rs index 1affeadbff1f2..72c91c9921cb0 100644 --- a/src/libglob/lib.rs +++ b/src/libglob/lib.rs @@ -382,18 +382,22 @@ impl Pattern { options: MatchOptions) -> MatchResult { let prev_char = Cell::new(prev_char); + let prev_char_ptr = &prev_char; let require_literal = |c| { (options.require_literal_separator && is_sep(c)) || (options.require_literal_leading_dot && c == '.' - && is_sep(prev_char.get().unwrap_or('/'))) + && is_sep(prev_char_ptr.get().unwrap_or('/'))) }; for (ti, token) in self.tokens.slice_from(i).iter().enumerate() { match *token { AnySequence => { loop { - match self.matches_from(prev_char.get(), file, i + ti + 1, options) { + match self.matches_from(prev_char_ptr.get(), + file, + i + ti + 1, + options) { SubPatternDoesntMatch => (), // keep trying m => return m, } @@ -406,7 +410,7 @@ impl Pattern { if require_literal(some_c.unwrap()) { return SubPatternDoesntMatch; } - prev_char.set(some_c); + prev_char_ptr.set(some_c); file = next; } } @@ -443,7 +447,7 @@ impl Pattern { if !matches { return SubPatternDoesntMatch; } - prev_char.set(some_c); + prev_char_ptr.set(some_c); file = next; } } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index e5fb200a1c417..c3800402e5c85 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -426,8 +426,11 @@ impl<'a> LabelText<'a> { } fn escape_str(s: &str) -> String { let mut out = String::with_capacity(s.len()); - for c in s.chars() { - LabelText::escape_char(c, |c| out.push_char(c)); + { + let out_ref = &mut out; + for c in s.chars() { + LabelText::escape_char(c, |c| out_ref.push_char(c)); + } } out } diff --git a/src/libgreen/basic.rs b/src/libgreen/basic.rs index 1ebebbe555e8b..dee25e0c6248d 100644 --- a/src/libgreen/basic.rs +++ b/src/libgreen/basic.rs @@ -127,11 +127,10 @@ impl EventLoop for BasicLoop { unsafe { // We block here if we have no messages to process and we may // receive a message at a later date - self.messages.hold_and_wait(|messages| { - self.remotes.len() > 0 && - messages.len() == 0 && - self.work.len() == 0 - }) + self.messages.hold_and_wait(|messages, (remotes, work)| { + remotes.len() > 0 && messages.len() == 0 && + work.len() == 0 + }, (&self.remotes, &self.work)) } } } @@ -178,8 +177,9 @@ impl BasicRemote { impl RemoteCallback for BasicRemote { fn fire(&mut self) { unsafe { + let id = self.id; self.queue.hold_and_signal(|queue| { - queue.push(RunRemote(self.id)); + queue.push(RunRemote(id)); }) } } @@ -188,8 +188,9 @@ impl RemoteCallback for BasicRemote { impl Drop for BasicRemote { fn drop(&mut self) { unsafe { + let id = self.id; self.queue.hold_and_signal(|queue| { - queue.push(RemoveRemote(self.id)); + queue.push(RemoveRemote(id)); }) } } diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs index 4584c08cbd898..ad1ce8e09ec4a 100644 --- a/src/libgreen/lib.rs +++ b/src/libgreen/lib.rs @@ -294,9 +294,13 @@ pub fn start(argc: int, argv: **u8, rt::init(argc, argv); let mut main = Some(main); let mut ret = None; - simple::task().run(|| { - ret = Some(run(event_loop_factory, main.take_unwrap())); - }); + { + let main_ptr = &mut main; + let ret_ptr = &mut ret; + simple::task().run(|| { + *ret_ptr = Some(run(event_loop_factory, main_ptr.take_unwrap())); + }); + } // unsafe is ok b/c we're sure that the runtime is gone unsafe { rt::cleanup() } ret.unwrap() diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs index f50f65af6f9eb..ddcb93333e1d7 100644 --- a/src/libgreen/task.rs +++ b/src/libgreen/task.rs @@ -111,7 +111,10 @@ extern fn bootstrap_green_task(task: uint, code: *(), env: *()) -> ! { // requested. This is the "try/catch" block for this green task and // is the wrapper for *all* code run in the task. let mut start = Some(start); - let task = task.swap().run(|| start.take_unwrap()()); + let task = { + let start_ptr = &mut start; + task.swap().run(|| start_ptr.take_unwrap()()) + }; // Once the function has exited, it's time to run the termination // routine. This means we need to context switch one more time but diff --git a/src/libnative/io/file_unix.rs b/src/libnative/io/file_unix.rs index b10284a3b6c3f..18d430899053b 100644 --- a/src/libnative/io/file_unix.rs +++ b/src/libnative/io/file_unix.rs @@ -52,10 +52,12 @@ impl FileDesc { // native::io wanting to use them is forced to have all the // rtio traits in scope pub fn inner_read(&mut self, buf: &mut [u8]) -> Result { + let buf_ptr = buf.as_mut_ptr(); + let buf_len = buf.len(); let ret = retry(|| unsafe { libc::read(self.fd(), - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as libc::size_t) as libc::c_int + buf_ptr as *mut libc::c_void, + buf_len as libc::size_t) as libc::c_int }); if ret == 0 { Err(io::standard_error(io::EndOfFile)) @@ -102,9 +104,11 @@ impl rtio::RtioFileStream for FileDesc { self.inner_write(buf) } fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result { + let buf_ptr = buf.as_ptr(); + let buf_len = buf.len(); match retry(|| unsafe { - libc::pread(self.fd(), buf.as_ptr() as *libc::c_void, - buf.len() as libc::size_t, + libc::pread(self.fd(), buf_ptr as *libc::c_void, + buf_len as libc::size_t, offset as libc::off_t) as libc::c_int }) { -1 => Err(super::last_error()), @@ -165,8 +169,9 @@ impl rtio::RtioFileStream for FileDesc { fn fstat(&mut self) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - match retry(|| unsafe { libc::fstat(self.fd(), &mut stat) }) { - 0 => Ok(mkstat(&stat)), + let stat_ptr = &mut stat; + match retry(|| unsafe { libc::fstat(self.fd(), stat_ptr) }) { + 0 => Ok(mkstat(stat_ptr)), _ => Err(super::last_error()), } } @@ -285,8 +290,10 @@ impl rtio::RtioFileStream for CFile { } } - fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result { - self.flush().and_then(|()| self.fd.pread(buf, offset)) + fn pread(&mut self, mut buf: &mut [u8], offset: u64) + -> Result { + let buf_ptr = &mut buf; + self.flush().and_then(|()| self.fd.pread(*buf_ptr, offset)) } fn pwrite(&mut self, buf: &[u8], offset: u64) -> Result<(), IoError> { self.flush().and_then(|()| self.fd.pwrite(buf, offset)) @@ -438,8 +445,10 @@ pub fn readlink(p: &CString) -> IoResult { len = 1024; // FIXME: read PATH_MAX from C ffi? } let mut buf: Vec = Vec::with_capacity(len as uint); + let buf_ptr = buf.as_ptr(); match retry(|| unsafe { - libc::readlink(p, buf.as_ptr() as *mut libc::c_char, + libc::readlink(p, + buf_ptr as *mut libc::c_char, len as libc::size_t) as libc::c_int }) { -1 => Err(super::last_error()), @@ -510,16 +519,18 @@ fn mkstat(stat: &libc::stat) -> io::FileStat { pub fn stat(p: &CString) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - match retry(|| unsafe { libc::stat(p.with_ref(|p| p), &mut stat) }) { - 0 => Ok(mkstat(&stat)), + let stat_ptr = &mut stat; + match retry(|| unsafe { libc::stat(p.with_ref(|p| p), stat_ptr) }) { + 0 => Ok(mkstat(stat_ptr)), _ => Err(super::last_error()), } } pub fn lstat(p: &CString) -> IoResult { let mut stat: libc::stat = unsafe { mem::zeroed() }; - match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), &mut stat) }) { - 0 => Ok(mkstat(&stat)), + let stat_ptr = &mut stat; + match retry(|| unsafe { libc::lstat(p.with_ref(|p| p), stat_ptr) }) { + 0 => Ok(mkstat(stat_ptr)), _ => Err(super::last_error()), } } diff --git a/src/libnative/io/mod.rs b/src/libnative/io/mod.rs index 0c103bc4695fd..ba532d79fd9ba 100644 --- a/src/libnative/io/mod.rs +++ b/src/libnative/io/mod.rs @@ -131,12 +131,13 @@ fn retry(f: || -> libc::c_int) -> libc::c_int { } } -fn keep_going(data: &[u8], f: |*u8, uint| -> i64) -> i64 { +fn keep_going(data: &[u8], mut f: |*u8, uint| -> i64) -> i64 { + let f_ptr = &mut f; let origamt = data.len(); let mut data = data.as_ptr(); let mut amt = origamt; while amt > 0 { - let ret = retry(|| f(data, amt) as libc::c_int); + let ret = retry(|| (*f_ptr)(data, amt) as libc::c_int); if ret == 0 { break } else if ret != -1 { diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs index 26307feae91f0..ec7c94d6b538f 100644 --- a/src/libnative/io/net.rs +++ b/src/libnative/io/net.rs @@ -341,12 +341,11 @@ impl rtio::RtioTcpStream for TcpStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { let fd = self.fd(); let dolock = || self.lock_nonblocking(); + let buf_ptr = buf.as_mut_ptr() as *mut libc::c_void; + let buf_len = buf.len(); let doread = |nb| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; - libc::recv(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as wrlen, - flags) as libc::c_int + libc::recv(fd, buf_ptr, buf_len as u64, flags) as libc::c_int }; read(fd, self.read_deadline, dolock, doread) } @@ -499,10 +498,11 @@ impl TcpAcceptor { let storagep = &mut storage as *mut libc::sockaddr_storage; let size = mem::size_of::(); let mut size = size as libc::socklen_t; + let size_ptr = &mut size; match retry(|| { libc::accept(self.fd(), storagep as *mut libc::sockaddr, - &mut size as *mut libc::socklen_t) as libc::c_int + size_ptr as *mut libc::socklen_t) as libc::c_int }) as sock_t { -1 => Err(last_error()), fd => Ok(TcpStream::new(Inner::new(fd))), @@ -623,14 +623,17 @@ impl rtio::RtioUdpSocket for UdpSocket { mem::size_of::() as libc::socklen_t; let dolock = || self.lock_nonblocking(); + let buf_ptr = buf.as_mut_ptr(); + let buf_len = buf.len(); + let addrlen_ptr = &mut addrlen; let doread = |nb| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::recvfrom(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as msglen_t, + buf_ptr as *mut libc::c_void, + buf_len as msglen_t, flags, storagep, - &mut addrlen) as libc::c_int + addrlen_ptr) as libc::c_int }; let n = try!(read(fd, self.read_deadline, dolock, doread)); sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| { @@ -788,10 +791,11 @@ impl rtio::RtioUdpSocket for UdpSocket { pub fn read(fd: sock_t, deadline: u64, lock: || -> T, - read: |bool| -> libc::c_int) -> IoResult { + mut read: |bool| -> libc::c_int) -> IoResult { + let read_ptr = &mut read; let mut ret = -1; if deadline == 0 { - ret = retry(|| read(false)); + ret = retry(|| (*read_ptr)(false)); } if deadline != 0 || (ret == -1 && util::wouldblock()) { @@ -812,7 +816,7 @@ pub fn read(fd: sock_t, // fail to read some data, we retry (hence the outer loop) and // wait for the socket to become readable again. let _guard = lock(); - match retry(|| read(deadline.is_some())) { + match retry(|| (*read_ptr)(deadline.is_some())) { -1 if util::wouldblock() => { assert!(deadline.is_some()); } -1 => return Err(last_error()), n => { ret = n; break } @@ -832,20 +836,24 @@ pub fn write(fd: sock_t, buf: &[u8], write_everything: bool, lock: || -> T, - write: |bool, *u8, uint| -> i64) -> IoResult { + mut write: |bool, *u8, uint| -> i64) -> IoResult { let mut ret = -1; let mut written = 0; + let write_ptr = &mut write; + let written_ptr = &mut written; if deadline == 0 { if write_everything { ret = keep_going(buf, |inner, len| { - written = buf.len() - len; - write(false, inner, len) + *written_ptr = buf.len() - len; + (*write_ptr)(false, inner, len) }); } else { ret = retry(|| { - write(false, buf.as_ptr(), buf.len()) as libc::c_int + (*write_ptr)(false, buf.as_ptr(), buf.len()) as libc::c_int }) as i64; - if ret > 0 { written = ret as uint; } + if ret > 0 { + *written_ptr = ret as uint; + } } } @@ -875,10 +883,12 @@ pub fn write(fd: sock_t, let _guard = lock(); let ptr = buf.slice_from(written).as_ptr(); let len = buf.len() - written; - match retry(|| write(deadline.is_some(), ptr, len) as libc::c_int) { + match retry(|| (*write_ptr)(deadline.is_some(), + ptr, + len) as libc::c_int) { -1 if util::wouldblock() => {} -1 => return Err(last_error()), - n => { written += n as uint; } + n => { *written_ptr += n as uint; } } } ret = 0; diff --git a/src/libnative/io/pipe_unix.rs b/src/libnative/io/pipe_unix.rs index a53a58b6cec43..d830cae793228 100644 --- a/src/libnative/io/pipe_unix.rs +++ b/src/libnative/io/pipe_unix.rs @@ -76,10 +76,11 @@ fn connect(addr: &CString, ty: libc::c_int, let inner = Inner::new(try!(unix_socket(ty))); let addrp = &addr as *_ as *libc::sockaddr; let len = len as libc::socklen_t; + let inner_fd = inner.fd; match timeout { None => { - match retry(|| unsafe { libc::connect(inner.fd, addrp, len) }) { + match retry(|| unsafe { libc::connect(inner_fd, addrp, len) }) { -1 => Err(super::last_error()), _ => Ok(inner) } @@ -149,11 +150,13 @@ impl rtio::RtioPipe for UnixStream { fn read(&mut self, buf: &mut [u8]) -> IoResult { let fd = self.fd(); let dolock = || self.lock_nonblocking(); + let buf_ptr = buf.as_mut_ptr(); + let buf_len = buf.len(); let doread = |nb| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::recv(fd, - buf.as_mut_ptr() as *mut libc::c_void, - buf.len() as libc::size_t, + buf_ptr as *mut libc::c_void, + buf_len as libc::size_t, flags) as libc::c_int }; net::read(fd, self.read_deadline, dolock, doread) @@ -248,10 +251,11 @@ impl UnixAcceptor { let storagep = &mut storage as *mut libc::sockaddr_storage; let size = mem::size_of::(); let mut size = size as libc::socklen_t; + let size_ptr = &mut size; match retry(|| unsafe { libc::accept(self.fd(), storagep as *mut libc::sockaddr, - &mut size as *mut libc::socklen_t) as libc::c_int + size_ptr as *mut libc::socklen_t) as libc::c_int }) { -1 => Err(super::last_error()), fd => Ok(UnixStream::new(Arc::new(Inner::new(fd)))) diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs index 177b90f2e1acd..89b7f8988b275 100644 --- a/src/libnative/io/process.rs +++ b/src/libnative/io/process.rs @@ -833,10 +833,11 @@ fn waitpid(pid: pid_t, deadline: u64) -> IoResult { static mut WRITE_FD: libc::c_int = 0; let mut status = 0 as c_int; + let status_ptr = &mut status; if deadline == 0 { - return match retry(|| unsafe { c::waitpid(pid, &mut status, 0) }) { + return match retry(|| unsafe { c::waitpid(pid, status_ptr, 0) }) { -1 => fail!("unknown waitpid error: {}", super::last_error()), - _ => Ok(translate_status(status)), + _ => Ok(translate_status(*status_ptr)), } } @@ -1074,8 +1075,9 @@ fn waitpid_nowait(pid: pid_t) -> Option { #[cfg(unix)] fn waitpid_os(pid: pid_t) -> Option { let mut status = 0 as c_int; + let status_ptr = &mut status; match retry(|| unsafe { - c::waitpid(pid, &mut status, c::WNOHANG) + c::waitpid(pid, status_ptr, c::WNOHANG) }) { n if n == pid => Some(translate_status(status)), 0 => None, diff --git a/src/libnative/io/timer_unix.rs b/src/libnative/io/timer_unix.rs index 8aa8b12b26d27..7caa926681657 100644 --- a/src/libnative/io/timer_unix.rs +++ b/src/libnative/io/timer_unix.rs @@ -107,7 +107,8 @@ fn helper(input: libc::c_int, messages: Receiver, _: ()) { // inserts a timer into an array of timers (sorted by firing time) fn insert(t: Box, active: &mut Vec>) { - match active.iter().position(|tm| tm.target > t.target) { + let t_target = t.target; + match active.iter().position(|tm| tm.target > t_target) { Some(pos) => { active.insert(pos, t); } None => { active.push(t); } } diff --git a/src/libnative/io/util.rs b/src/libnative/io/util.rs index fe7a58a5e6868..a49bf5dcedb74 100644 --- a/src/libnative/io/util.rs +++ b/src/libnative/io/util.rs @@ -144,6 +144,7 @@ pub fn await(fd: net::sock_t, deadline: Option, Writable => (ptr::null(), &set as *_), }; let mut tv: libc::timeval = unsafe { mem::zeroed() }; + let tv_ptr = &mut tv; match retry(|| { let now = ::io::timer::now(); @@ -153,8 +154,8 @@ pub fn await(fd: net::sock_t, deadline: Option, // If we're past the deadline, then pass a 0 timeout to // select() so we can poll the status let ms = if deadline < now {0} else {deadline - now}; - tv = ms_to_timeval(ms); - &tv as *_ + *tv_ptr = ms_to_timeval(ms); + tv_ptr as *mut _ as *_ } }; let n = if cfg!(windows) {1} else {fd as libc::c_int + 1}; diff --git a/src/libnative/lib.rs b/src/libnative/lib.rs index f04dfac80ccfe..a5ef44108e336 100644 --- a/src/libnative/lib.rs +++ b/src/libnative/lib.rs @@ -126,12 +126,16 @@ pub fn start(argc: int, argv: **u8, main: proc()) -> int { let mut main = Some(main); let mut task = task::new((my_stack_bottom, my_stack_top)); task.name = Some(str::Slice("
")); - let t = task.run(|| { - unsafe { - rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top); - } - exit_code = Some(run(main.take_unwrap())); - }); + let t = { + let main_ptr = &mut main; + let exit_code_ptr = &mut exit_code; + task.run(|| { + unsafe { + rt::stack::record_stack_bounds(my_stack_bottom, my_stack_top); + } + *exit_code_ptr = Some(run((*main_ptr).take_unwrap())); + }) + }; drop(t); unsafe { rt::cleanup(); } // If the exit code wasn't set, then the task block must have failed. diff --git a/src/libnative/task.rs b/src/libnative/task.rs index 4183dec19d02d..06e08ee38183a 100644 --- a/src/libnative/task.rs +++ b/src/libnative/task.rs @@ -99,7 +99,10 @@ pub fn spawn_opts(opts: TaskOpts, f: proc():Send) { let mut f = Some(f); let mut task = task; task.put_runtime(ops); - let t = task.run(|| { f.take_unwrap()() }); + let t = { + let f_ptr = &mut f; + task.run(|| { (*f_ptr).take_unwrap()() }) + }; drop(t); bookkeeping::decrement(); }) diff --git a/src/libnum/bigint.rs b/src/libnum/bigint.rs index e8d0434c39285..a3876dee88664 100644 --- a/src/libnum/bigint.rs +++ b/src/libnum/bigint.rs @@ -200,13 +200,17 @@ impl Add for BigUint { let (a, b) = if self.data.len() > other.data.len() { (self, other) } else { (other, self) }; let mut carry = 0; + let carry_ref = &mut carry; let mut sum: Vec = a.data.iter().zip(b.data.iter().chain(zeros)).map(|(ai, bi)| { let (hi, lo) = BigDigit::from_doublebigdigit( - (*ai as DoubleBigDigit) + (*bi as DoubleBigDigit) + (carry as DoubleBigDigit)); - carry = hi; + (*ai as DoubleBigDigit) + (*bi as DoubleBigDigit) + + (*carry_ref as DoubleBigDigit)); + *carry_ref = hi; lo }).collect(); - if carry != 0 { sum.push(carry); } + if carry != 0 { + sum.push(*carry_ref); + } return BigUint::new(sum); } } @@ -218,22 +222,23 @@ impl Sub for BigUint { let (a, b) = (self.data.iter().chain(zeros.clone()), other.data.iter().chain(zeros)); let mut borrow = 0; + let borrow_ref = &mut borrow; let diff: Vec = a.take(new_len).zip(b).map(|(ai, bi)| { let (hi, lo) = BigDigit::from_doublebigdigit( BigDigit::base + (*ai as DoubleBigDigit) - (*bi as DoubleBigDigit) - - (borrow as DoubleBigDigit) + - (*borrow_ref as DoubleBigDigit) ); /* hi * (base) + lo == 1*(base) + ai - bi - borrow => ai - bi - borrow < 0 <=> hi == 0 */ - borrow = if hi == 0 { 1 } else { 0 }; + *borrow_ref = if hi == 0 { 1 } else { 0 }; lo }).collect(); - assert!(borrow == 0, + assert!(*borrow_ref == 0, "Cannot subtract other from self because other is larger than self."); return BigUint::new(diff); } @@ -276,14 +281,18 @@ impl Mul for BigUint { if n == 1 { return (*a).clone(); } let mut carry = 0; + let carry_ref = &mut carry; let mut prod: Vec = a.data.iter().map(|ai| { let (hi, lo) = BigDigit::from_doublebigdigit( - (*ai as DoubleBigDigit) * (n as DoubleBigDigit) + (carry as DoubleBigDigit) + (*ai as DoubleBigDigit) * (n as DoubleBigDigit) + + (*carry_ref as DoubleBigDigit) ); - carry = hi; + *carry_ref = hi; lo }).collect(); - if carry != 0 { prod.push(carry); } + if *carry_ref != 0 { + prod.push(*carry_ref); + } return BigUint::new(prod); } @@ -719,14 +728,18 @@ impl BigUint { if n_bits == 0 || self.is_zero() { return (*self).clone(); } let mut carry = 0; + let carry_ref = &mut carry; let mut shifted: Vec = self.data.iter().map(|elem| { let (hi, lo) = BigDigit::from_doublebigdigit( - (*elem as DoubleBigDigit) << n_bits | (carry as DoubleBigDigit) + (*elem as DoubleBigDigit) << n_bits | + (*carry_ref as DoubleBigDigit) ); - carry = hi; + *carry_ref = hi; lo }).collect(); - if carry != 0 { shifted.push(carry); } + if *carry_ref != 0 { + shifted.push(*carry_ref); + } return BigUint::new(shifted); } diff --git a/src/librand/distributions/exponential.rs b/src/librand/distributions/exponential.rs index 03c87eb931d60..f475351298e92 100644 --- a/src/librand/distributions/exponential.rs +++ b/src/librand/distributions/exponential.rs @@ -128,10 +128,12 @@ mod bench { fn rand_exp(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); let mut exp = Exp::new(2.71828 * 3.14159); + let rng_ptr = &mut rng; + let exp_ptr = &mut exp; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - exp.sample(&mut rng); + exp_ptr.sample(rng_ptr); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; diff --git a/src/librand/distributions/gamma.rs b/src/librand/distributions/gamma.rs index 1bb2c35bce206..7e129a809b771 100644 --- a/src/librand/distributions/gamma.rs +++ b/src/librand/distributions/gamma.rs @@ -387,10 +387,11 @@ mod bench { fn bench_gamma_large_shape(b: &mut Bencher) { let gamma = Gamma::new(10., 1.0); let mut rng = XorShiftRng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - gamma.ind_sample(&mut rng); + gamma.ind_sample(rng_ptr); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; @@ -400,10 +401,11 @@ mod bench { fn bench_gamma_small_shape(b: &mut Bencher) { let gamma = Gamma::new(0.1, 1.0); let mut rng = XorShiftRng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - gamma.ind_sample(&mut rng); + gamma.ind_sample(rng_ptr); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; diff --git a/src/librand/distributions/normal.rs b/src/librand/distributions/normal.rs index dea73945b4384..55490bf1d55c2 100644 --- a/src/librand/distributions/normal.rs +++ b/src/librand/distributions/normal.rs @@ -195,10 +195,12 @@ mod bench { fn rand_normal(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); let mut normal = Normal::new(-2.71828, 3.14159); + let rng_ptr = &mut rng; + let normal_ptr = &mut normal; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - normal.sample(&mut rng); + normal_ptr.sample(rng_ptr); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index 1d9da40f18b6e..f13d1bcac6aea 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -52,11 +52,12 @@ impl IsaacRng { pub fn new() -> IoResult { let mut rng = EMPTY; let mut os_rng = try!(OSRng::new()); + let os_rng_ptr = &mut os_rng; unsafe { let ptr = rng.rsl.as_mut_ptr(); raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| { - os_rng.fill_bytes(slice); + os_rng_ptr.fill_bytes(slice); }) } @@ -261,12 +262,13 @@ impl Isaac64Rng { pub fn new() -> IoResult { let mut rng = EMPTY_64; let mut os_rng = try!(OSRng::new()); + let os_rng_ptr = &mut os_rng; unsafe { let ptr = rng.rsl.as_mut_ptr(); raw::mut_buf_as_slice(ptr as *mut u8, mem::size_of_val(&rng.rsl), |slice| { - os_rng.fill_bytes(slice); + os_rng_ptr.fill_bytes(slice); }) } @@ -500,7 +502,8 @@ mod test { let seed = &[1, 23, 456, 7890, 12345]; let mut ra: IsaacRng = SeedableRng::from_seed(seed); // Regression test that isaac is actually using the above vector - let v = Vec::from_fn(10, |_| ra.next_u32()); + let ra_ptr = &mut ra; + let v = Vec::from_fn(10, |_| ra_ptr.next_u32()); assert_eq!(v, vec!(2558573138, 873787463, 263499565, 2103644246, 3595684709, 4203127393, 264982119, 2765226902, 2737944514, 3900253796)); @@ -508,9 +511,10 @@ mod test { let seed = &[12345, 67890, 54321, 9876]; let mut rb: IsaacRng = SeedableRng::from_seed(seed); // skip forward to the 10000th number - for _ in range(0, 10000) { rb.next_u32(); } + let rb_ptr = &mut rb; + for _ in range(0, 10000) { rb_ptr.next_u32(); } - let v = Vec::from_fn(10, |_| rb.next_u32()); + let v = Vec::from_fn(10, |_| rb_ptr.next_u32()); assert_eq!(v, vec!(3676831399, 3183332890, 2834741178, 3854698763, 2717568474, 1576568959, 3507990155, 179069555, 141456972, 2478885421)); @@ -520,7 +524,8 @@ mod test { let seed = &[1, 23, 456, 7890, 12345]; let mut ra: Isaac64Rng = SeedableRng::from_seed(seed); // Regression test that isaac is actually using the above vector - let v = Vec::from_fn(10, |_| ra.next_u64()); + let ra_ptr = &mut ra; + let v = Vec::from_fn(10, |_| ra_ptr.next_u64()); assert_eq!(v, vec!(547121783600835980, 14377643087320773276, 17351601304698403469, 1238879483818134882, 11952566807690396487, 13970131091560099343, @@ -530,9 +535,10 @@ mod test { let seed = &[12345, 67890, 54321, 9876]; let mut rb: Isaac64Rng = SeedableRng::from_seed(seed); // skip forward to the 10000th number - for _ in range(0, 10000) { rb.next_u64(); } + let rb_ptr = &mut rb; + for _ in range(0, 10000) { rb_ptr.next_u64(); } - let v = Vec::from_fn(10, |_| rb.next_u64()); + let v = Vec::from_fn(10, |_| rb_ptr.next_u64()); assert_eq!(v, vec!(18143823860592706164, 8491801882678285927, 2699425367717515619, 17196852593171130876, 2606123525235546165, 15790932315217671084, diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 4a11b69207600..18d0b15734f4b 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -872,9 +872,10 @@ mod bench { #[bench] fn rand_xorshift(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - rng.gen::(); + rng_ptr.gen::(); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; @@ -883,9 +884,10 @@ mod bench { #[bench] fn rand_isaac(b: &mut Bencher) { let mut rng = IsaacRng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - rng.gen::(); + rng_ptr.gen::(); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; @@ -894,9 +896,10 @@ mod bench { #[bench] fn rand_isaac64(b: &mut Bencher) { let mut rng = Isaac64Rng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - rng.gen::(); + rng_ptr.gen::(); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; @@ -905,9 +908,10 @@ mod bench { #[bench] fn rand_std(b: &mut Bencher) { let mut rng = StdRng::new().unwrap(); + let rng_ptr = &mut rng; b.iter(|| { for _ in range(0, RAND_BENCH_N) { - rng.gen::(); + rng_ptr.gen::(); } }); b.bytes = size_of::() as u64 * RAND_BENCH_N; @@ -916,9 +920,11 @@ mod bench { #[bench] fn rand_shuffle_100(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - let x : &mut[uint] = [1,..100]; + let mut x: &mut[uint] = [1,..100]; + let rng_ptr = &mut rng; + let x_ptr = &mut x; b.iter(|| { - rng.shuffle(x); + rng_ptr.shuffle(*x_ptr); }) } } diff --git a/src/libregex_macros/lib.rs b/src/libregex_macros/lib.rs index 71e3d06cf967c..912782ac861fd 100644 --- a/src/libregex_macros/lib.rs +++ b/src/libregex_macros/lib.rs @@ -116,13 +116,14 @@ impl<'a> NfaGen<'a> { // expression returned. let num_cap_locs = 2 * self.prog.num_captures(); let num_insts = self.prog.insts.len(); + let span = self.sp; let cap_names = self.vec_expr(self.names.as_slice().iter(), |cx, name| match *name { Some(ref name) => { let name = name.as_slice(); quote_expr!(cx, Some($name)) } - None => cx.expr_none(self.sp), + None => cx.expr_none(span), } ); let prefix_anchor = @@ -131,7 +132,7 @@ impl<'a> NfaGen<'a> { _ => false, }; let init_groups = self.vec_expr(range(0, num_cap_locs), - |cx, _| cx.expr_none(self.sp)); + |cx, _| cx.expr_none(span)); let prefix_lit = Rc::new(Vec::from_slice(self.prog.prefix.as_slice().as_bytes())); let prefix_bytes = self.cx.expr_lit(self.sp, ast::LitBinary(prefix_lit)); diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 82cda6f13f108..e9ebffe9a2ddc 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -230,9 +230,10 @@ impl ArchiveRO { pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> { unsafe { let mut size = 0 as libc::size_t; - let ptr = file.with_c_str(|file| { - llvm::LLVMRustArchiveReadSection(self.ptr, file, &mut size) - }); + let file_c = file.to_c_str(); + let ptr = llvm::LLVMRustArchiveReadSection(self.ptr, + file_c.with_ref(|x| x), + &mut size); if ptr.is_null() { None } else { diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 2baf8c2469728..911ce77e4f92f 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -23,7 +23,7 @@ use metadata::{encoder, cstore, filesearch, csearch, loader}; use middle::trans::context::CrateContext; use middle::trans::common::gensym_name; use middle::ty; -use util::common::time; +use util::common::Timer; use util::ppaux; use util::sha2::{Digest, Sha256}; @@ -101,7 +101,7 @@ pub mod write { use lib::llvm::llvm; use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef}; use lib; - use util::common::time; + use util::common::Timer; use syntax::abi; use std::c_str::ToCStr; @@ -230,10 +230,16 @@ pub mod write { } // Finally, run the actual optimization passes - time(sess.time_passes(), "llvm function passes", (), |()| - llvm::LLVMRustRunFunctionPassManager(fpm, llmod)); - time(sess.time_passes(), "llvm module passes", (), |()| - llvm::LLVMRunPassManager(mpm, llmod)); + { + let _timer = Timer::new(sess.time_passes(), + "LLVM function passes"); + llvm::LLVMRustRunFunctionPassManager(fpm, llmod); + } + { + let _timer = Timer::new(sess.time_passes(), + "LLVM module passes"); + llvm::LLVMRunPassManager(mpm, llmod); + } // Deallocate managers that we're now done with llvm::LLVMDisposePassManager(fpm); @@ -251,8 +257,11 @@ pub mod write { } if sess.lto() { - time(sess.time_passes(), "all lto passes", (), |()| - lto::run(sess, llmod, tm, trans.reachable.as_slice())); + { + let _timer = Timer::new(sess.time_passes(), + "all LTO passes"); + lto::run(sess, llmod, tm, trans.reachable.as_slice()); + } if sess.opts.cg.save_temps { output.with_extension("lto.bc").with_c_str(|buf| { @@ -324,7 +333,9 @@ pub mod write { } } - time(sess.time_passes(), "codegen passes", (), |()| { + { + let _timer = Timer::new(sess.time_passes(), + "code generation passes"); match object_file { Some(ref path) => { with_codegen(tm, llmod, trans.no_builtins, |cpm| { @@ -344,7 +355,7 @@ pub mod write { lib::llvm::ObjectFile); }) } - }); + } llvm::LLVMRustDisposeTargetMachine(tm); llvm::LLVMDisposeModule(trans.metadata_module); @@ -400,10 +411,12 @@ pub mod write { let mut llvm_c_strs = Vec::new(); let mut llvm_args = Vec::new(); { + let llvm_args_ptr = &mut llvm_args; + let llvm_c_strs_ptr = &mut llvm_c_strs; let add = |arg: &str| { let s = arg.to_c_str(); - llvm_args.push(s.with_ref(|p| p)); - llvm_c_strs.push(s); + llvm_args_ptr.push(s.with_ref(|p| p)); + llvm_c_strs_ptr.push(s); }; add("rustc"); // fake program name if vectorize_loop { add("-vectorize-loops"); } @@ -416,6 +429,8 @@ pub mod write { } } + let llvm_args_len = llvm_args.len(); + let llvm_args_ptr = llvm_args.as_ptr(); INIT.doit(|| { llvm::LLVMInitializePasses(); @@ -441,8 +456,8 @@ pub mod write { llvm::LLVMInitializeMipsAsmPrinter(); llvm::LLVMInitializeMipsAsmParser(); - llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, - llvm_args.as_ptr()); + llvm::LLVMRustSetLLVMOptions(llvm_args_len as c_int, + llvm_args_ptr); }); } @@ -638,7 +653,10 @@ pub fn sanitize(s: &str) -> String { _ => { let mut tstr = String::new(); - char::escape_unicode(c, |c| tstr.push_char(c)); + { + let tstr_ptr = &mut tstr; + char::escape_unicode(c, |c| tstr_ptr.push_char(c)); + } result.push_char('$'); result.push_str(tstr.as_slice().slice_from(1)); } @@ -965,8 +983,9 @@ fn link_rlib<'a>(sess: &'a Session, // into the archive. let bc = obj_filename.with_extension("bc"); let bc_deflated = obj_filename.with_extension("bc.deflate"); + let bc_deflated_ptr = &bc_deflated; match fs::File::open(&bc).read_to_end().and_then(|data| { - fs::File::create(&bc_deflated) + fs::File::create(bc_deflated_ptr) .write(match flate::deflate_bytes(data.as_slice()) { Some(compressed) => compressed, None => sess.fatal("failed to compress bytecode") @@ -980,8 +999,8 @@ fn link_rlib<'a>(sess: &'a Session, sess.abort_if_errors() } } - a.add_file(&bc_deflated, false); - remove(sess, &bc_deflated); + a.add_file(bc_deflated_ptr, false); + remove(sess, bc_deflated_ptr); if !sess.opts.cg.save_temps && !sess.opts.output_types.contains(&OutputTypeBitcode) { remove(sess, &bc); @@ -1068,7 +1087,10 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, // Invoke the system linker debug!("{}", &cmd); - let prog = time(sess.time_passes(), "running linker", (), |()| cmd.output()); + let prog = { + let _timer = Timer::new(sess.time_passes(), "running linker"); + cmd.output() + }; match prog { Ok(prog) => { if !prog.status.success() { @@ -1437,27 +1459,25 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session, // against the archive. if sess.lto() { let name = sess.cstore.get_crate_data(cnum).name.clone(); - time(sess.time_passes(), - format!("altering {}.rlib", name).as_slice(), - (), |()| { - let dst = tmpdir.join(cratepath.filename().unwrap()); - match fs::copy(&cratepath, &dst) { - Ok(..) => {} - Err(e) => { - sess.err(format!("failed to copy {} to {}: {}", - cratepath.display(), - dst.display(), - e).as_slice()); - sess.abort_if_errors(); - } - } - let mut archive = Archive::open(sess, dst.clone()); - archive.remove_file(format!("{}.o", name).as_slice()); - let files = archive.files(); - if files.iter().any(|s| s.as_slice().ends_with(".o")) { - cmd.arg(dst); + let _timer = Timer::new(sess.time_passes(), + "altering external rlib crate"); + let dst = tmpdir.join(cratepath.filename().unwrap()); + match fs::copy(&cratepath, &dst) { + Ok(..) => {} + Err(e) => { + sess.err(format!("failed to copy {} to {}: {}", + cratepath.display(), + dst.display(), + e).as_slice()); + sess.abort_if_errors(); } - }); + } + let mut archive = Archive::open(sess, dst.clone()); + archive.remove_file(format!("{}.o", name).as_slice()); + let files = archive.files(); + if files.iter().any(|s| s.as_slice().ends_with(".o")) { + cmd.arg(dst); + } } else { cmd.arg(cratepath); } diff --git a/src/librustc/back/lto.rs b/src/librustc/back/lto.rs index 372d66003f2da..a0139ed892bdf 100644 --- a/src/librustc/back/lto.rs +++ b/src/librustc/back/lto.rs @@ -14,7 +14,7 @@ use driver::session; use driver::config; use lib::llvm::{ModuleRef, TargetMachineRef, llvm, True, False}; use metadata::cstore; -use util::common::time; +use util::common::Timer; use libc; use flate; @@ -42,6 +42,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // load the bitcode from the archive. Then merge it into the current LLVM // module that we've got. let crates = sess.cstore.get_used_crates(cstore::RequireStatic); + let _timer = Timer::new(sess.time_passes(), "reading external crates"); for (cnum, path) in crates.move_iter() { let name = sess.cstore.get_crate_data(cnum).name.clone(); let path = match path { @@ -54,33 +55,18 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, let archive = ArchiveRO::open(&path).expect("wanted an rlib"); debug!("reading {}", name); - let bc = time(sess.time_passes(), - format!("read {}.bc.deflate", name).as_slice(), - (), - |_| { - archive.read(format!("{}.bc.deflate", - name).as_slice()) - }); + let bc = archive.read(format!("{}.bc.deflate", name).as_slice()); let bc = bc.expect("missing compressed bytecode in archive!"); - let bc = time(sess.time_passes(), - format!("inflate {}.bc", name).as_slice(), - (), - |_| { - match flate::inflate_bytes(bc) { - Some(bc) => bc, - None => { - sess.fatal(format!("failed to decompress \ - bc of `{}`", - name).as_slice()) - } - } - }); + let bc = match flate::inflate_bytes(bc) { + Some(bc) => bc, + None => { + sess.fatal(format!("failed to decompress bc of `{}`", + name).as_slice()) + } + }; let ptr = bc.as_slice().as_ptr(); debug!("linking {}", name); - time(sess.time_passes(), - format!("ll link {}", name).as_slice(), - (), - |()| unsafe { + unsafe { if !llvm::LLVMRustLinkInExternalBitcode(llmod, ptr as *libc::c_char, bc.len() as libc::size_t) { @@ -88,7 +74,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, format_strbuf!("failed to load bc of `{}`", name.as_slice())); } - }); + } } // Internalize everything but the reachable symbols of the current module @@ -126,8 +112,10 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, "verify".with_c_str(|s| llvm::LLVMRustAddPass(pm, s)); - time(sess.time_passes(), "LTO pases", (), |()| - llvm::LLVMRunPassManager(pm, llmod)); + { + let _timer = Timer::new(sess.time_passes(), "LTO passes"); + llvm::LLVMRunPassManager(pm, llmod); + } llvm::LLVMDisposePassManager(pm); } diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 16965bfa67fa8..eaff3f9053c1a 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -403,9 +403,13 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { pub fn append_configuration(cfg: &mut ast::CrateConfig, name: InternedString) { - if !cfg.iter().any(|mi| mi.name() == name) { - cfg.push(attr::mk_word_item(name)) + { + let name_ptr = &name; + if cfg.iter().any(|mi| mi.name() == *name_ptr) { + return + } } + cfg.push(attr::mk_word_item(name)) } pub fn build_configuration(sess: &Session) -> ast::CrateConfig { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index bc0d8e2f75c15..17c484a031df5 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -24,7 +24,7 @@ use middle::cfg::graphviz::LabelledCFG; use middle::{trans, freevars, kind, ty, typeck, lint, reachable}; use middle::dependency_format; use middle; -use util::common::time; +use util::common::Timer; use util::ppaux; use util::nodemap::{NodeSet}; @@ -136,19 +136,20 @@ impl Input { pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input) -> ast::Crate { - let krate = time(sess.time_passes(), "parsing", (), |_| { - match *input { - FileInput(ref file) => { - parse::parse_crate_from_file(&(*file), cfg.clone(), &sess.parse_sess) - } - StrInput(ref src) => { - parse::parse_crate_from_source_str(anon_src().to_string(), - src.to_string(), - cfg.clone(), - &sess.parse_sess) - } + let _timer = Timer::new(sess.time_passes(), "parsing"); + let krate = match *input { + FileInput(ref file) => { + parse::parse_crate_from_file(&(*file), + cfg.clone(), + &sess.parse_sess) } - }); + StrInput(ref src) => { + parse::parse_crate_from_source_str(anon_src().to_string(), + src.to_string(), + cfg.clone(), + &sess.parse_sess) + } + }; if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 { let mut stdout = io::BufferedWriter::new(io::stdout()); @@ -180,11 +181,15 @@ pub fn phase_2_configure_and_expand(sess: &Session, *sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice()); - time(time_passes, "gated feature checking", (), |_| - front::feature_gate::check_crate(sess, &krate)); + { + let _timer = Timer::new(time_passes, "gated feature checking"); + front::feature_gate::check_crate(sess, &krate) + } - krate = time(time_passes, "crate injection", krate, |krate| - front::std_inject::maybe_inject_crates_ref(sess, krate)); + { + let _timer = Timer::new(time_passes, "crate injection"); + krate = front::std_inject::maybe_inject_crates_ref(sess, krate) + } // strip before expansion to allow macros to depend on // configuration variables e.g/ in @@ -194,40 +199,54 @@ pub fn phase_2_configure_and_expand(sess: &Session, // // baz! should not use this definition unless foo is enabled. - krate = time(time_passes, "configuration 1", krate, |krate| - front::config::strip_unconfigured_items(krate)); + { + let _timer = Timer::new(time_passes, "early configuration"); + krate = front::config::strip_unconfigured_items(krate) + } - krate = time(time_passes, "expansion", krate, |krate| { - // Windows dlls do not have rpaths, so they don't know how to find their - // dependencies. It's up to us to tell the system where to find all the - // dependent dlls. Note that this uses cfg!(windows) as opposed to - // targ_cfg because syntax extensions are always loaded for the host - // compiler, not for the target. + { + let _timer = Timer::new(time_passes, "macro expansion"); + // Windows dlls do not have rpaths, so they don't know how to find + // their dependencies. It's up to us to tell the system where to find + // all the dependent dlls. Note that this uses cfg!(windows) as + // opposed to targ_cfg because syntax extensions are always loaded for + // the host compiler, not for the target. if cfg!(windows) { sess.host_filesearch().add_dylib_search_paths(); } let cfg = syntax::ext::expand::ExpansionConfig { loader: loader, - deriving_hash_type_parameter: sess.features.default_type_params.get(), + deriving_hash_type_parameter: sess.features + .default_type_params + .get(), crate_id: crate_id.clone(), }; - syntax::ext::expand::expand_crate(&sess.parse_sess, - cfg, - krate) - }); + krate = syntax::ext::expand::expand_crate(&sess.parse_sess, + cfg, + krate) + } // strip again, in case expansion added anything with a #[cfg]. - krate = time(time_passes, "configuration 2", krate, |krate| - front::config::strip_unconfigured_items(krate)); + { + let _timer = Timer::new(time_passes, "late configuration"); + krate = front::config::strip_unconfigured_items(krate) + } - krate = time(time_passes, "maybe building test harness", krate, |krate| - front::test::modify_for_testing(sess, krate)); + { + let _timer = Timer::new(time_passes, "building test harness"); + krate = front::test::modify_for_testing(sess, krate) + } - krate = time(time_passes, "prelude injection", krate, |krate| - front::std_inject::maybe_inject_prelude(sess, krate)); + { + let _timer = Timer::new(time_passes, "prelude injection"); + krate = front::std_inject::maybe_inject_prelude(sess, krate) + } - let (krate, map) = time(time_passes, "assigning node ids and indexing ast", krate, |krate| - front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate)); + let (krate, map) = { + let _timer = Timer::new(time_passes, + "node ID assignment and AST indexing"); + front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate) + }; if sess.opts.debugging_opts & config::AST_JSON != 0 { let mut stdout = io::BufferedWriter::new(io::stdout()); @@ -253,14 +272,17 @@ pub struct CrateAnalysis { pub fn phase_3_run_analysis_passes(sess: Session, krate: &ast::Crate, ast_map: syntax::ast_map::Map) -> CrateAnalysis { - let time_passes = sess.time_passes(); - time(time_passes, "external crate/lib resolution", (), |_| - creader::read_crates(&sess, krate)); + { + let _timer = Timer::new(time_passes, "external crate/lib resolution"); + creader::read_crates(&sess, krate) + } - let lang_items = time(time_passes, "language item collection", (), |_| - middle::lang_items::collect_language_items(krate, &sess)); + let lang_items = { + let _timer = Timer::new(time_passes, "language item collection"); + middle::lang_items::collect_language_items(krate, &sess) + }; let middle::resolve::CrateMap { def_map: def_map, @@ -268,32 +290,44 @@ pub fn phase_3_run_analysis_passes(sess: Session, trait_map: trait_map, external_exports: external_exports, last_private_map: last_private_map - } = - time(time_passes, "resolution", (), |_| - middle::resolve::resolve_crate(&sess, &lang_items, krate)); + } = { + let _timer = Timer::new(time_passes, "name resolution"); + middle::resolve::resolve_crate(&sess, &lang_items, krate) + }; // Discard MTWT tables that aren't required past resolution. syntax::ext::mtwt::clear_tables(); - let named_region_map = time(time_passes, "lifetime resolution", (), - |_| middle::resolve_lifetime::krate(&sess, krate)); + let named_region_map = { + let _timer = Timer::new(time_passes, "lifetime resolution"); + middle::resolve_lifetime::krate(&sess, krate) + }; - time(time_passes, "looking for entry point", (), - |_| middle::entry::find_entry_point(&sess, krate, &ast_map)); + { + let _timer = Timer::new(time_passes, "looking for entry point"); + middle::entry::find_entry_point(&sess, krate, &ast_map) + } - sess.macro_registrar_fn.set( - time(time_passes, "looking for macro registrar", (), |_| - syntax::ext::registrar::find_macro_registrar( - sess.diagnostic(), krate))); + sess.macro_registrar_fn.set({ + let _timer = Timer::new(time_passes, "looking for macro registrar"); + syntax::ext::registrar::find_macro_registrar(sess.diagnostic(), + krate) + }); - let freevars = time(time_passes, "freevar finding", (), |_| - freevars::annotate_freevars(&def_map, krate)); + let freevars = { + let _timer = Timer::new(time_passes, "freevar finding"); + freevars::annotate_freevars(&def_map, krate) + }; - let region_map = time(time_passes, "region resolution", (), |_| - middle::region::resolve_crate(&sess, krate)); + let region_map = { + let _timer = Timer::new(time_passes, "region resolution"); + middle::region::resolve_crate(&sess, krate) + }; - time(time_passes, "loop checking", (), |_| - middle::check_loop::check_crate(&sess, krate)); + { + let _timer = Timer::new(time_passes, "loop checking"); + middle::check_loop::check_crate(&sess, krate) + } let ty_cx = ty::mk_ctxt(sess, def_map, named_region_map, ast_map, freevars, region_map, lang_items); @@ -301,49 +335,73 @@ pub fn phase_3_run_analysis_passes(sess: Session, // passes are timed inside typeck typeck::check_crate(&ty_cx, trait_map, krate); - time(time_passes, "check static items", (), |_| - middle::check_static::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "static item checking"); + middle::check_static::check_crate(&ty_cx, krate) + } // These next two const passes can probably be merged - time(time_passes, "const marking", (), |_| - middle::const_eval::process_crate(krate, &ty_cx)); + { + let _timer = Timer::new(time_passes, "constant evaluation"); + middle::const_eval::process_crate(krate, &ty_cx) + } - time(time_passes, "const checking", (), |_| - middle::check_const::check_crate(krate, &ty_cx)); + { + let _timer = Timer::new(time_passes, "constant checking"); + middle::check_const::check_crate(krate, &ty_cx) + } - let maps = (external_exports, last_private_map); - let (exported_items, public_items) = - time(time_passes, "privacy checking", maps, |(a, b)| - middle::privacy::check_crate(&ty_cx, &exp_map2, a, b, krate)); + let (exported_items, public_items) = { + let _timer = Timer::new(time_passes, "privacy checking"); + middle::privacy::check_crate(&ty_cx, + &exp_map2, + external_exports, + last_private_map, + krate) + }; - time(time_passes, "effect checking", (), |_| - middle::effect::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "effect checking"); + middle::effect::check_crate(&ty_cx, krate) + } - time(time_passes, "match checking", (), |_| - middle::check_match::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "pattern checking"); + middle::check_match::check_crate(&ty_cx, krate) + } - time(time_passes, "liveness checking", (), |_| - middle::liveness::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "liveness checking"); + middle::liveness::check_crate(&ty_cx, krate) + } - time(time_passes, "borrow checking", (), |_| - middle::borrowck::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "borrow checking"); + middle::borrowck::check_crate(&ty_cx, krate) + } - time(time_passes, "kind checking", (), |_| - kind::check_crate(&ty_cx, krate)); + { + let _timer = Timer::new(time_passes, "kind checking"); + kind::check_crate(&ty_cx, krate) + } - let reachable_map = - time(time_passes, "reachability checking", (), |_| - reachable::find_reachable(&ty_cx, &exported_items)); + let reachable_map = { + let _timer = Timer::new(time_passes, "reachability checking"); + reachable::find_reachable(&ty_cx, &exported_items) + }; - time(time_passes, "death checking", (), |_| { + { + let _timer = Timer::new(time_passes, "death checking"); middle::dead::check_crate(&ty_cx, &exported_items, &reachable_map, krate) - }); + } - time(time_passes, "lint checking", (), |_| - lint::check_crate(&ty_cx, &exported_items, krate)); + { + let _timer = Timer::new(time_passes, "lint checking"); + lint::check_crate(&ty_cx, &exported_items, krate) + } CrateAnalysis { exp_map2: exp_map2, @@ -369,15 +427,19 @@ pub struct CrateTranslation { /// be discarded. pub fn phase_4_translate_to_llvm(krate: ast::Crate, analysis: CrateAnalysis, - outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) { + outputs: &OutputFilenames) + -> (ty::ctxt, CrateTranslation) { let time_passes = analysis.ty_cx.sess.time_passes(); - time(time_passes, "resolving dependency formats", (), |_| - dependency_format::calculate(&analysis.ty_cx)); + { + let _timer = Timer::new(time_passes, "dependency format resolution"); + dependency_format::calculate(&analysis.ty_cx) + } - // Option dance to work around the lack of stack once closures. - time(time_passes, "translation", (krate, analysis), |(krate, analysis)| - trans::base::trans_crate(krate, analysis, outputs)) + { + let _timer = Timer::new(time_passes, "translation to LLVM IR"); + trans::base::trans_crate(krate, analysis, outputs) + } } /// Run LLVM itself, producing a bitcode file, assembly file or object file @@ -388,8 +450,10 @@ pub fn phase_5_run_llvm_passes(sess: &Session, if sess.opts.cg.no_integrated_as { let output_type = link::OutputTypeAssembly; - time(sess.time_passes(), "LLVM passes", (), |_| - link::write::run_passes(sess, trans, [output_type], outputs)); + { + let _timer = Timer::new(sess.time_passes(), "LLVM passes"); + link::write::run_passes(sess, trans, [output_type], outputs); + } link::write::run_assembler(sess, outputs); @@ -398,11 +462,11 @@ pub fn phase_5_run_llvm_passes(sess: &Session, fs::unlink(&outputs.temp_path(link::OutputTypeAssembly)).unwrap(); } } else { - time(sess.time_passes(), "LLVM passes", (), |_| - link::write::run_passes(sess, - trans, - sess.opts.output_types.as_slice(), - outputs)); + let _timer = Timer::new(sess.time_passes(), "LLVM passes"); + link::write::run_passes(sess, + trans, + sess.opts.output_types.as_slice(), + outputs); } } @@ -411,11 +475,8 @@ pub fn phase_5_run_llvm_passes(sess: &Session, pub fn phase_6_link_output(sess: &Session, trans: &CrateTranslation, outputs: &OutputFilenames) { - time(sess.time_passes(), "linking", (), |_| - link::link_binary(sess, - trans, - outputs, - &trans.link.crateid)); + let _timer = Timer::new(sess.time_passes(), "linking"); + link::link_binary(sess, trans, outputs, &trans.link.crateid); } pub fn stop_after_phase_3(sess: &Session) -> bool { @@ -492,6 +553,7 @@ fn write_out_deps(sess: &Session, _ => return, }; + let deps_filename_ptr = &deps_filename; let result = (|| { // Build a list of files used to compile the output and // write Makefile-compatible dependency rules @@ -499,7 +561,7 @@ fn write_out_deps(sess: &Session, .iter().filter(|fmap| fmap.is_real_file()) .map(|fmap| fmap.name.to_string()) .collect(); - let mut file = try!(io::File::create(&deps_filename)); + let mut file = try!(io::File::create(deps_filename_ptr)); for path in out_filenames.iter() { try!(write!(&mut file as &mut Writer, "{}: {}\n\n", path.display(), files.connect(" "))); @@ -511,7 +573,7 @@ fn write_out_deps(sess: &Session, Ok(()) => {} Err(e) => { sess.fatal(format!("error writing dependencies to `{}`: {}", - deps_filename.display(), e).as_slice()); + deps_filename_ptr.display(), e).as_slice()); } } } @@ -652,21 +714,28 @@ pub fn pretty_print_input(sess: Session, } PpmFlowGraph(nodeid) => { let ast_map = ast_map.expect("--pretty flowgraph missing ast_map"); - let node = ast_map.find(nodeid).unwrap_or_else(|| { - sess.fatal(format_strbuf!("--pretty flowgraph couldn't find id: {}", - nodeid).as_slice()) - }); - let block = match node { - syntax::ast_map::NodeBlock(block) => block, - _ => { - let message = format_strbuf!("--pretty=flowgraph needs block, got {:?}", - node); - - // point to what was found, if there's an - // accessible span. - match ast_map.opt_span(nodeid) { - Some(sp) => sess.span_fatal(sp, message.as_slice()), - None => sess.fatal(message.as_slice()) + let block = { + let sess_ptr = &sess; + let node = ast_map.find(nodeid).unwrap_or_else(|| { + sess_ptr.fatal(format_strbuf!( + "--pretty flowgraph couldn't find id: {}", + nodeid).as_slice()) + }); + match node { + syntax::ast_map::NodeBlock(block) => block, + _ => { + let message = format_strbuf!("--pretty=flowgraph \ + needs block, got {:?}", + node); + + // point to what was found, if there's an + // accessible span. + match ast_map.opt_span(nodeid) { + Some(sp) => { + sess_ptr.span_fatal(sp, message.as_slice()) + } + None => sess_ptr.fatal(message.as_slice()) + } } } }; diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs index 04bc46e5dfc0d..dfd932ebea4e3 100644 --- a/src/librustc/driver/mod.rs +++ b/src/librustc/driver/mod.rs @@ -72,9 +72,12 @@ fn run_compiler(args: &[String]) { let odir = matches.opt_str("out-dir").map(|o| Path::new(o)); let ofile = matches.opt_str("o").map(|o| Path::new(o)); - let pretty = matches.opt_default("pretty", "normal").map(|a| { - parse_pretty(&sess, a.as_slice()) - }); + let pretty = { + let sess_ptr = &sess; + matches.opt_default("pretty", "normal").map(|a| { + parse_pretty(sess_ptr, a.as_slice()) + }) + }; match pretty { Some::(ppm) => { driver::pretty_print_input(sess, cfg, &input, ppm, ofile); diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index e613fa7eb76c8..b1acff55a943b 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -82,11 +82,14 @@ fn dump_crates(cstore: &CStore) { fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) { let mut map = HashMap::new(); - cstore.iter_crate_data(|cnum, data| { - let crateid = data.crate_id(); - let key = (crateid.name.clone(), crateid.path.clone()); - map.find_or_insert_with(key, |_| Vec::new()).push(cnum); - }); + { + let map_ptr = &mut map; + cstore.iter_crate_data(|cnum, data| { + let crateid = data.crate_id(); + let key = (crateid.name.clone(), crateid.path.clone()); + map_ptr.find_or_insert_with(key, |_| Vec::new()).push(cnum); + }); + } for ((name, _), dupes) in map.move_iter() { if dupes.len() == 1 { continue } @@ -265,16 +268,19 @@ fn visit_item(e: &Env, i: &ast::Item) { fn existing_match(e: &Env, crate_id: &CrateId, hash: Option<&Svh>) -> Option { let mut ret = None; - e.sess.cstore.iter_crate_data(|cnum, data| { - let other_id = data.crate_id(); - if crate_id.matches(&other_id) { - let other_hash = data.hash(); - match hash { - Some(hash) if *hash != other_hash => {} - Some(..) | None => { ret = Some(cnum); } + { + let ret_ptr = &mut ret; + e.sess.cstore.iter_crate_data(|cnum, data| { + let other_id = data.crate_id(); + if crate_id.matches(&other_id) { + let other_hash = data.hash(); + match hash { + Some(hash) if *hash != other_hash => {} + Some(..) | None => *ret_ptr = Some(cnum), + } } - } - }); + }); + } return ret; } @@ -441,9 +447,14 @@ impl<'a> CrateLoader for Loader<'a> { None => { load_ctxt.report_load_errs(); unreachable!() }, }; let macros = decoder::get_exported_macros(library.metadata.as_slice()); - let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| { - decoder::get_symbol(library.metadata.as_slice(), id).to_string() - }); + let registrar = { + let library_ptr = &library; + decoder::get_macro_registrar_fn(library.metadata.as_slice()) + .map(|id| { + decoder::get_symbol(library_ptr.metadata.as_slice(), + id).to_string() + }) + }; let mc = MacroCrate { lib: library.dylib.clone(), macros: macros.move_iter().map(|x| x.to_string()).collect(), diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index ddd493b2c1354..fd732b5307aa8 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -65,15 +65,18 @@ fn lookup_hash<'a>(d: ebml::Doc<'a>, eq_fn: |&[u8]| -> bool, let belt = tag_index_buckets_bucket_elt; let mut ret = None; - reader::tagged_docs(tagged_doc.doc, belt, |elt| { - let pos = u64_from_be_bytes(elt.data, elt.start, 4) as uint; - if eq_fn(elt.data.slice(elt.start + 4, elt.end)) { - ret = Some(reader::doc_at(d.data, pos).unwrap().doc); - false - } else { - true - } - }); + { + let ret_ptr = &mut ret; + reader::tagged_docs(tagged_doc.doc, belt, |elt| { + let pos = u64_from_be_bytes(elt.data, elt.start, 4) as uint; + if eq_fn(elt.data.slice(elt.start + 4, elt.end)) { + *ret_ptr = Some(reader::doc_at(d.data, pos).unwrap().doc); + false + } else { + true + } + }); + } ret } @@ -178,10 +181,13 @@ fn item_sized(item: ebml::Doc) -> ast::Sized { fn item_method_sort(item: ebml::Doc) -> char { let mut ret = 'r'; - reader::tagged_docs(item, tag_item_trait_method_sort, |doc| { - ret = doc.as_str_slice()[0] as char; - false - }); + { + let ret_ptr = &mut ret; + reader::tagged_docs(item, tag_item_trait_method_sort, |doc| { + *ret_ptr = doc.as_str_slice()[0] as char; + false + }); + } ret } @@ -191,10 +197,13 @@ fn item_symbol(item: ebml::Doc) -> String { fn item_parent_item(d: ebml::Doc) -> Option { let mut ret = None; - reader::tagged_docs(d, tag_items_data_parent_item, |did| { - ret = Some(reader::with_doc_data(did, parse_def_id)); - false - }); + { + let ret_ptr = &mut ret; + reader::tagged_docs(d, tag_items_data_parent_item, |did| { + *ret_ptr = Some(reader::with_doc_data(did, parse_def_id)); + false + }); + } ret } @@ -258,20 +267,25 @@ fn item_ty_param_defs(item: ebml::Doc, tag: uint) -> Rc > { let mut bounds = Vec::new(); - reader::tagged_docs(item, tag, |p| { - let bd = parse_type_param_def_data( - p.data, p.start, cdata.cnum, tcx, - |_, did| translate_def_id(cdata, did)); - bounds.push(bd); - true - }); + { + let bounds_ptr = &mut bounds; + reader::tagged_docs(item, tag, |p| { + let bd = parse_type_param_def_data( + p.data, p.start, cdata.cnum, tcx, + |_, did| translate_def_id(cdata, did)); + bounds_ptr.push(bd); + true + }); + } Rc::new(bounds) } fn item_region_param_defs(item_doc: ebml::Doc, cdata: Cmd) -> Rc > { let mut v = Vec::new(); - reader::tagged_docs(item_doc, tag_region_param_def, |rp_doc| { + { + let v_ptr = &mut v; + reader::tagged_docs(item_doc, tag_region_param_def, |rp_doc| { let ident_str_doc = reader::get_doc(rp_doc, tag_region_param_def_ident); let ident = item_name(&*token::get_ident_interner(), ident_str_doc); @@ -279,21 +293,27 @@ fn item_region_param_defs(item_doc: ebml::Doc, cdata: Cmd) tag_region_param_def_def_id); let def_id = reader::with_doc_data(def_id_doc, parse_def_id); let def_id = translate_def_id(cdata, def_id); - v.push(ty::RegionParameterDef { name: ident.name, - def_id: def_id }); + v_ptr.push(ty::RegionParameterDef { + name: ident.name, + def_id: def_id, + }); true }); + } Rc::new(v) } fn enum_variant_ids(item: ebml::Doc, cdata: Cmd) -> Vec { let mut ids: Vec = Vec::new(); let v = tag_items_data_item_variant; - reader::tagged_docs(item, v, |p| { - let ext = reader::with_doc_data(p, parse_def_id); - ids.push(ast::DefId { krate: cdata.cnum, node: ext.node }); - true - }); + { + let ids_ptr = &mut ids; + reader::tagged_docs(item, v, |p| { + let ext = reader::with_doc_data(p, parse_def_id); + ids_ptr.push(ast::DefId { krate: cdata.cnum, node: ext.node }); + true + }); + } return ids; } @@ -304,18 +324,21 @@ fn item_path(item_doc: ebml::Doc) -> Vec { let len = reader::doc_as_u32(len_doc) as uint; let mut result = Vec::with_capacity(len); - reader::docs(path_doc, |tag, elt_doc| { - if tag == tag_path_elem_mod { - let s = elt_doc.as_str_slice(); - result.push(ast_map::PathMod(token::intern(s))); - } else if tag == tag_path_elem_name { - let s = elt_doc.as_str_slice(); - result.push(ast_map::PathName(token::intern(s))); - } else { - // ignore tag_path_len element - } - true - }); + { + let result_ptr = &mut result; + reader::docs(path_doc, |tag, elt_doc| { + if tag == tag_path_elem_mod { + let s = elt_doc.as_str_slice(); + result_ptr.push(ast_map::PathMod(token::intern(s))); + } else if tag == tag_path_elem_name { + let s = elt_doc.as_str_slice(); + result_ptr.push(ast_map::PathName(token::intern(s))); + } else { + // ignore tag_path_len element + } + true + }); + } result } @@ -384,26 +407,34 @@ pub fn get_trait_def(cdata: Cmd, let rp_defs = item_region_param_defs(item_doc, cdata); let sized = item_sized(item_doc); let mut bounds = ty::EmptyBuiltinBounds(); - // Collect the builtin bounds from the encoded supertraits. - // FIXME(#8559): They should be encoded directly. - reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| { - // NB. Bypasses real supertraits. See get_supertraits() if you wanted them. - let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); - tcx.lang_items.to_builtin_kind(trait_ref.def_id).map(|bound| { - bounds.add(bound); - }); - true - }); - // Turn sized into a bound, FIXME(#8559). - if sized == ast::StaticSize { - tcx.lang_items.to_builtin_kind(tcx.lang_items.sized_trait().unwrap()).map(|bound| { - bounds.add(bound); + { + let bounds_ptr = &mut bounds; + // Collect the builtin bounds from the encoded supertraits. + // FIXME(#8559): They should be encoded directly. + reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| { + // NB. Bypasses real supertraits. See get_supertraits() if you + // wanted them. + let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); + tcx.lang_items.to_builtin_kind(trait_ref.def_id).map(|bound| { + bounds_ptr.add(bound); + }); + true }); + // Turn sized into a bound, FIXME(#8559). + if sized == ast::StaticSize { + tcx.lang_items + .to_builtin_kind(tcx.lang_items.sized_trait().unwrap()) + .map(|bound| { + bounds_ptr.add(bound); + }); + } } ty::TraitDef { - generics: ty::Generics {type_param_defs: tp_defs, - region_param_defs: rp_defs}, + generics: ty::Generics { + type_param_defs: tp_defs, + region_param_defs: rp_defs, + }, bounds: bounds, trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)) } @@ -484,11 +515,15 @@ pub type GetCrateDataCb<'a> = |ast::CrateNum|: 'a -> Rc; fn each_child_of_item_or_crate(intr: Rc, cdata: Cmd, item_doc: ebml::Doc, - get_crate_data: GetCrateDataCb, - callback: |DefLike, - ast::Ident, - ast::Visibility|) { + mut get_crate_data: GetCrateDataCb, + mut callback: |DefLike, + ast::Ident, + ast::Visibility|) { + let get_crate_data_ptr = &mut get_crate_data; + let callback_ptr = &mut callback; + // Iterate over all children. + let intr_ptr = &intr; let _ = reader::tagged_docs(item_doc, tag_mod_child, |child_info_doc| { let child_def_id = reader::with_doc_data(child_info_doc, parse_def_id); @@ -499,7 +534,7 @@ fn each_child_of_item_or_crate(intr: Rc, let crate_data = if child_def_id.krate == cdata.cnum { None } else { - Some(get_crate_data(child_def_id.krate)) + Some((*get_crate_data_ptr)(child_def_id.krate)) }; let crate_data = match crate_data { Some(ref cdata) => &**cdata, @@ -513,12 +548,12 @@ fn each_child_of_item_or_crate(intr: Rc, None => {} Some(child_item_doc) => { // Hand off the item to the callback. - let child_name = item_name(&*intr, child_item_doc); + let child_name = item_name(&**intr_ptr, child_item_doc); let def_like = item_to_def_like(child_item_doc, child_def_id, cdata.cnum); let visibility = item_visibility(child_item_doc); - callback(def_like, child_name, visibility); + (*callback_ptr)(def_like, child_name, visibility); } } @@ -554,14 +589,16 @@ fn each_child_of_item_or_crate(intr: Rc, // Hand off the static method // to the callback. let static_method_name = - item_name(&*intr, impl_method_doc); + item_name(&**intr_ptr, + impl_method_doc); let static_method_def_like = item_to_def_like(impl_method_doc, impl_method_def_id, cdata.cnum); - callback(static_method_def_like, - static_method_name, - item_visibility(impl_method_doc)); + (*callback_ptr)( + static_method_def_like, + static_method_name, + item_visibility(impl_method_doc)); } _ => {} } @@ -592,7 +629,7 @@ fn each_child_of_item_or_crate(intr: Rc, let crate_data = if child_def_id.krate == cdata.cnum { None } else { - Some(get_crate_data(child_def_id.krate)) + Some((*get_crate_data_ptr)(child_def_id.krate)) }; let crate_data = match crate_data { Some(ref cdata) => &**cdata, @@ -611,7 +648,9 @@ fn each_child_of_item_or_crate(intr: Rc, child_def_id.krate); // These items have a public visibility because they're part of // a public re-export. - callback(def_like, token::str_to_ident(name), ast::Public); + (*callback_ptr)(def_like, + token::str_to_ident(name), + ast::Public); } } @@ -699,6 +738,7 @@ pub fn get_enum_variants(intr: Rc, cdata: Cmd, id: ast::NodeId, let items = reader::get_doc(reader::Doc(data), tag_items); let item = find_item(id, items); let mut disr_val = 0; + let disr_val_ptr = &mut disr_val; enum_variant_ids(item, cdata).iter().map(|did| { let item = find_item(did.node, items); let ctor_ty = item_type(ast::DefId { krate: cdata.cnum, node: id}, @@ -709,11 +749,11 @@ pub fn get_enum_variants(intr: Rc, cdata: Cmd, id: ast::NodeId, _ => Vec::new(), // Nullary enum variant. }; match variant_disr_val(item) { - Some(val) => { disr_val = val; } + Some(val) => { *disr_val_ptr = val; } _ => { /* empty */ } } - let old_disr_val = disr_val; - disr_val += 1; + let old_disr_val = *disr_val_ptr; + *disr_val_ptr += 1; Rc::new(ty::VariantInfo { args: arg_tys, arg_names: None, @@ -754,21 +794,24 @@ fn get_explicit_self(item: ebml::Doc) -> ast::ExplicitSelf_ { /// Returns information about the given implementation. pub fn get_impl_methods(cdata: Cmd, impl_id: ast::NodeId) -> Vec { let mut methods = Vec::new(); - reader::tagged_docs(lookup_item(impl_id, cdata.data()), - tag_item_impl_method, |doc| { - let m_did = reader::with_doc_data(doc, parse_def_id); - methods.push(translate_def_id(cdata, m_did)); - true - }); + + { + let methods_ptr = &mut methods; + reader::tagged_docs(lookup_item(impl_id, cdata.data()), + tag_item_impl_method, |doc| { + let m_did = reader::with_doc_data(doc, parse_def_id); + methods_ptr.push(translate_def_id(cdata, m_did)); + true + }); + } methods } -pub fn get_method_name_and_explicit_self( - intr: Rc, - cdata: Cmd, - id: ast::NodeId) -> (ast::Ident, ast::ExplicitSelf_) -{ +pub fn get_method_name_and_explicit_self(intr: Rc, + cdata: Cmd, + id: ast::NodeId) + -> (ast::Ident, ast::ExplicitSelf_) { let method_doc = lookup_item(id, cdata.data()); let name = item_name(&*intr, method_doc); let explicit_self = get_explicit_self(method_doc); @@ -818,10 +861,13 @@ pub fn get_trait_method_def_ids(cdata: Cmd, let data = cdata.data(); let item = lookup_item(id, data); let mut result = Vec::new(); - reader::tagged_docs(item, tag_item_trait_method, |mth| { - result.push(item_def_id(mth, cdata)); - true - }); + { + let result_ptr = &mut result; + reader::tagged_docs(item, tag_item_trait_method, |mth| { + result_ptr.push(item_def_id(mth, cdata)); + true + }); + } result } @@ -839,16 +885,23 @@ pub fn get_provided_trait_methods(intr: Rc, cdata: Cmd, let data = cdata.data(); let item = lookup_item(id, data); let mut result = Vec::new(); - - reader::tagged_docs(item, tag_item_trait_method, |mth_id| { - let did = item_def_id(mth_id, cdata); - let mth = lookup_item(did.node, data); - - if item_method_sort(mth) == 'p' { - result.push(Rc::new(get_method(intr.clone(), cdata, did.node, tcx))); - } - true - }); + let intr_ptr = &intr; + + { + let result_ptr = &mut result; + reader::tagged_docs(item, tag_item_trait_method, |mth_id| { + let did = item_def_id(mth_id, cdata); + let mth = lookup_item(did.node, data); + + if item_method_sort(mth) == 'p' { + result_ptr.push(Rc::new(get_method((*intr_ptr).clone(), + cdata, + did.node, + tcx))); + } + true + }); + } return result; } @@ -858,16 +911,19 @@ pub fn get_supertraits(cdata: Cmd, id: ast::NodeId, tcx: &ty::ctxt) -> Vec> { let mut results = Vec::new(); let item_doc = lookup_item(id, cdata.data()); - reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| { - // NB. Only reads the ones that *aren't* builtin-bounds. See also - // get_trait_def() for collecting the builtin bounds. - // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place. - let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); - if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() { - results.push(Rc::new(trait_ref)); - } - true - }); + { + let results_ptr = &mut results; + reader::tagged_docs(item_doc, tag_item_super_trait_ref, |trait_doc| { + // NB. Only reads the ones that *aren't* builtin-bounds. See also + // get_trait_def() for collecting the builtin bounds. + // FIXME(#8559): The builtin bounds shouldn't be encoded in the first place. + let trait_ref = doc_trait_ref(trait_doc, tcx, cdata); + if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_none() { + results_ptr.push(Rc::new(trait_ref)); + } + true + }); + } return results; } @@ -879,12 +935,12 @@ pub fn get_type_name_if_impl(cdata: Cmd, } let mut ret = None; + let ret_ptr = &mut ret; reader::tagged_docs(item, tag_item_impl_type_basename, |doc| { - ret = Some(token::str_to_ident(doc.as_str_slice())); + *ret_ptr = Some(token::str_to_ident(doc.as_str_slice())); false }); - - ret + *ret_ptr } pub fn get_static_methods_if_impl(intr: Rc, @@ -904,13 +960,15 @@ pub fn get_static_methods_if_impl(intr: Rc, if !ret { return None } let mut impl_method_ids = Vec::new(); + let impl_method_ids_ptr = &mut impl_method_ids; reader::tagged_docs(item, tag_item_impl_method, |impl_method_doc| { - impl_method_ids.push(reader::with_doc_data(impl_method_doc, parse_def_id)); + impl_method_ids_ptr.push(reader::with_doc_data(impl_method_doc, + parse_def_id)); true }); let mut static_impl_methods = Vec::new(); - for impl_method_id in impl_method_ids.iter() { + for impl_method_id in impl_method_ids_ptr.iter() { let impl_method_doc = lookup_item(impl_method_id.node, cdata.data()); let family = item_family(impl_method_doc); match family { @@ -944,10 +1002,16 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd, { let item = lookup_item(node_id, cdata.data()); let mut ret = None; - reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor, |_| { - ret = Some(item_reqd_and_translated_parent_item(cdata.cnum, item)); - false - }); + { + let ret_ptr = &mut ret; + reader::tagged_docs(item, + tag_items_data_item_is_tuple_struct_ctor, + |_| { + *ret_ptr = Some(item_reqd_and_translated_parent_item(cdata.cnum, + item)); + false + }); + } ret } @@ -976,91 +1040,105 @@ pub fn get_struct_fields(intr: Rc, cdata: Cmd, id: ast::NodeId) let data = cdata.data(); let item = lookup_item(id, data); let mut result = Vec::new(); - reader::tagged_docs(item, tag_item_field, |an_item| { - let f = item_family(an_item); - if f == PublicField || f == InheritedField { - // FIXME #6993: name should be of type Name, not Ident - let name = item_name(&*intr, an_item); + { + let result_ptr = &mut result; + reader::tagged_docs(item, tag_item_field, |an_item| { + let f = item_family(an_item); + if f == PublicField || f == InheritedField { + // FIXME #6993: name should be of type Name, not Ident + let name = item_name(&*intr, an_item); + let did = item_def_id(an_item, cdata); + let tagdoc = reader::get_doc(an_item, tag_item_field_origin); + let origin_id = translate_def_id( + cdata, + reader::with_doc_data(tagdoc, parse_def_id)); + result_ptr.push(ty::field_ty { + name: name.name, + id: did, + vis: struct_field_family_to_visibility(f), + origin: origin_id, + }); + } + true + }); + reader::tagged_docs(item, tag_item_unnamed_field, |an_item| { let did = item_def_id(an_item, cdata); let tagdoc = reader::get_doc(an_item, tag_item_field_origin); - let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); - result.push(ty::field_ty { - name: name.name, + let f = item_family(an_item); + let origin_id = + translate_def_id(cdata, + reader::with_doc_data(tagdoc, parse_def_id)); + result_ptr.push(ty::field_ty { + name: special_idents::unnamed_field.name, id: did, vis: struct_field_family_to_visibility(f), origin: origin_id, }); - } - true - }); - reader::tagged_docs(item, tag_item_unnamed_field, |an_item| { - let did = item_def_id(an_item, cdata); - let tagdoc = reader::get_doc(an_item, tag_item_field_origin); - let f = item_family(an_item); - let origin_id = translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id)); - result.push(ty::field_ty { - name: special_idents::unnamed_field.name, - id: did, - vis: struct_field_family_to_visibility(f), - origin: origin_id, + true }); - true - }); + } result } fn get_meta_items(md: ebml::Doc) -> Vec<@ast::MetaItem> { let mut items: Vec<@ast::MetaItem> = Vec::new(); - reader::tagged_docs(md, tag_meta_item_word, |meta_item_doc| { - let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); - let n = token::intern_and_get_ident(nd.as_str_slice()); - items.push(attr::mk_word_item(n)); - true - }); - reader::tagged_docs(md, tag_meta_item_name_value, |meta_item_doc| { - let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); - let vd = reader::get_doc(meta_item_doc, tag_meta_item_value); - let n = token::intern_and_get_ident(nd.as_str_slice()); - let v = token::intern_and_get_ident(vd.as_str_slice()); - // FIXME (#623): Should be able to decode MetaNameValue variants, - // but currently the encoder just drops them - items.push(attr::mk_name_value_item_str(n, v)); - true - }); - reader::tagged_docs(md, tag_meta_item_list, |meta_item_doc| { - let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); - let n = token::intern_and_get_ident(nd.as_str_slice()); - let subitems = get_meta_items(meta_item_doc); - items.push(attr::mk_list_item(n, subitems.move_iter().collect())); - true - }); + { + let items_ptr = &mut items; + reader::tagged_docs(md, tag_meta_item_word, |meta_item_doc| { + let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); + let n = token::intern_and_get_ident(nd.as_str_slice()); + items_ptr.push(attr::mk_word_item(n)); + true + }); + reader::tagged_docs(md, tag_meta_item_name_value, |meta_item_doc| { + let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); + let vd = reader::get_doc(meta_item_doc, tag_meta_item_value); + let n = token::intern_and_get_ident(nd.as_str_slice()); + let v = token::intern_and_get_ident(vd.as_str_slice()); + // FIXME (#623): Should be able to decode MetaNameValue variants, + // but currently the encoder just drops them + items_ptr.push(attr::mk_name_value_item_str(n, v)); + true + }); + reader::tagged_docs(md, tag_meta_item_list, |meta_item_doc| { + let nd = reader::get_doc(meta_item_doc, tag_meta_item_name); + let n = token::intern_and_get_ident(nd.as_str_slice()); + let subitems = get_meta_items(meta_item_doc); + items_ptr.push( + attr::mk_list_item(n, subitems.move_iter().collect())); + true + }); + } return items; } fn get_attributes(md: ebml::Doc) -> Vec { let mut attrs: Vec = Vec::new(); - match reader::maybe_get_doc(md, tag_attributes) { - option::Some(attrs_d) => { - reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| { - let meta_items = get_meta_items(attr_doc); - // Currently it's only possible to have a single meta item on - // an attribute - assert_eq!(meta_items.len(), 1u); - let meta_item = *meta_items.get(0); - attrs.push( - codemap::Spanned { - node: ast::Attribute_ { - id: attr::mk_attr_id(), - style: ast::AttrOuter, - value: meta_item, - is_sugared_doc: false, - }, - span: codemap::DUMMY_SP - }); - true - }); - } - option::None => () + { + let attrs_ptr = &mut attrs; + match reader::maybe_get_doc(md, tag_attributes) { + option::Some(attrs_d) => { + reader::tagged_docs(attrs_d, tag_attribute, |attr_doc| { + let meta_items = get_meta_items(attr_doc); + // Currently it's only possible to have a single meta item on + // an attribute + assert_eq!(meta_items.len(), 1u); + let meta_item = *meta_items.get(0); + attrs_ptr.push( + codemap::Spanned { + node: ast::Attribute_ { + id: attr::mk_attr_id(), + style: ast::AttrOuter, + value: meta_item, + is_sugared_doc: false, + }, + span: codemap::DUMMY_SP + }); + true + }); + } + option::None => () + } } return attrs; } @@ -1093,23 +1171,30 @@ pub fn get_crate_deps(data: &[u8]) -> Vec { let cratedoc = reader::Doc(data); let depsdoc = reader::get_doc(cratedoc, tag_crate_deps); let mut crate_num = 1; + let crate_num_ptr = &mut crate_num; fn docstr(doc: ebml::Doc, tag_: uint) -> String { let d = reader::get_doc(doc, tag_); d.as_str_slice().to_string() } - reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| { - let crate_id = - from_str(docstr(depdoc, - tag_crate_dep_crateid).as_slice()).unwrap(); - let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash).as_slice()); - deps.push(CrateDep { - cnum: crate_num, - crate_id: crate_id, - hash: hash, + + { + let deps_ptr = &mut deps; + reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| { + let crate_id = + from_str(docstr(depdoc, + tag_crate_dep_crateid).as_slice()).unwrap(); + let hash = Svh::new(docstr(depdoc, + tag_crate_dep_hash).as_slice()); + deps_ptr.push(CrateDep { + cnum: *crate_num_ptr, + crate_id: crate_id, + hash: hash, + }); + *crate_num_ptr += 1; + true }); - crate_num += 1; - true - }); + } + return deps; } @@ -1182,37 +1267,39 @@ pub fn translate_def_id(cdata: Cmd, did: ast::DefId) -> ast::DefId { } } -pub fn each_impl(cdata: Cmd, callback: |ast::DefId|) { +pub fn each_impl(cdata: Cmd, mut callback: |ast::DefId|) { let impls_doc = reader::get_doc(reader::Doc(cdata.data()), tag_impls); + let callback_ptr = &mut callback; let _ = reader::tagged_docs(impls_doc, tag_impls_impl, |impl_doc| { - callback(item_def_id(impl_doc, cdata)); + (*callback_ptr)(item_def_id(impl_doc, cdata)); true }); } pub fn each_implementation_for_type(cdata: Cmd, id: ast::NodeId, - callback: |ast::DefId|) { + mut callback: |ast::DefId|) { let item_doc = lookup_item(id, cdata.data()); + let callback_ptr = &mut callback; reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl, |impl_doc| { let implementation_def_id = item_def_id(impl_doc, cdata); - callback(implementation_def_id); + (*callback_ptr)(implementation_def_id); true }); } pub fn each_implementation_for_trait(cdata: Cmd, id: ast::NodeId, - callback: |ast::DefId|) { + mut callback: |ast::DefId|) { let item_doc = lookup_item(id, cdata.data()); - + let callback_ptr = &mut callback; let _ = reader::tagged_docs(item_doc, tag_items_data_item_extension_impl, |impl_doc| { let implementation_def_id = item_def_id(impl_doc, cdata); - callback(implementation_def_id); + (*callback_ptr)(implementation_def_id); true }); } @@ -1242,15 +1329,20 @@ pub fn get_native_libraries(cdata: Cmd) let libraries = reader::get_doc(reader::Doc(cdata.data()), tag_native_libraries); let mut result = Vec::new(); - reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| { - let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind); - let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name); - let kind: cstore::NativeLibaryKind = - FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); - let name = name_doc.as_str().to_string(); - result.push((kind, name)); - true - }); + { + let result_ptr = &mut result; + reader::tagged_docs(libraries, tag_native_libraries_lib, |lib_doc| { + let kind_doc = reader::get_doc(lib_doc, + tag_native_libraries_kind); + let name_doc = reader::get_doc(lib_doc, + tag_native_libraries_name); + let kind: cstore::NativeLibaryKind = + FromPrimitive::from_u32(reader::doc_as_u32(kind_doc)).unwrap(); + let name = name_doc.as_str().to_string(); + result_ptr.push((kind, name)); + true + }); + } return result; } @@ -1263,10 +1355,13 @@ pub fn get_exported_macros(data: &[u8]) -> Vec { let macros = reader::get_doc(reader::Doc(data), tag_exported_macros); let mut result = Vec::new(); - reader::tagged_docs(macros, tag_macro_def, |macro_doc| { - result.push(macro_doc.as_str().to_string()); - true - }); + { + let result_ptr = &mut result; + reader::tagged_docs(macros, tag_macro_def, |macro_doc| { + result_ptr.push(macro_doc.as_str().to_string()); + true + }); + } result } @@ -1277,22 +1372,26 @@ pub fn get_dylib_dependency_formats(cdata: Cmd) tag_dylib_dependency_formats); let mut result = Vec::new(); - debug!("found dylib deps: {}", formats.as_str_slice()); - for spec in formats.as_str_slice().split(',') { - if spec.len() == 0 { continue } - let cnum = spec.split(':').nth(0).unwrap(); - let link = spec.split(':').nth(1).unwrap(); - let cnum = from_str(cnum).unwrap(); - let cnum = match cdata.cnum_map.find(&cnum) { - Some(&n) => n, - None => fail!("didn't find a crate in the cnum_map") - }; - result.push((cnum, if link == "d" { - cstore::RequireDynamic - } else { - cstore::RequireStatic - })); + { + let result_ptr = &mut result; + debug!("found dylib deps: {}", formats.as_str_slice()); + for spec in formats.as_str_slice().split(',') { + if spec.len() == 0 { continue } + let cnum = spec.split(':').nth(0).unwrap(); + let link = spec.split(':').nth(1).unwrap(); + let cnum = from_str(cnum).unwrap(); + let cnum = match cdata.cnum_map.find(&cnum) { + Some(&n) => n, + None => fail!("didn't find a crate in the cnum_map") + }; + result_ptr.push((cnum, if link == "d" { + cstore::RequireDynamic + } else { + cstore::RequireStatic + })); + } } + return result; } @@ -1301,26 +1400,34 @@ pub fn get_missing_lang_items(cdata: Cmd) { let items = reader::get_doc(reader::Doc(cdata.data()), tag_lang_items); let mut result = Vec::new(); - reader::tagged_docs(items, tag_lang_items_missing, |missing_doc| { - let item: lang_items::LangItem = - FromPrimitive::from_u32(reader::doc_as_u32(missing_doc)).unwrap(); - result.push(item); - true - }); + { + let result_ptr = &mut result; + reader::tagged_docs(items, tag_lang_items_missing, |missing_doc| { + let item: lang_items::LangItem = FromPrimitive::from_u32( + reader::doc_as_u32(missing_doc)).unwrap(); + result_ptr.push(item); + true + }); + } return result; } pub fn get_method_arg_names(cdata: Cmd, id: ast::NodeId) -> Vec { let mut ret = Vec::new(); - let method_doc = lookup_item(id, cdata.data()); - match reader::maybe_get_doc(method_doc, tag_method_argument_names) { - Some(args_doc) => { - reader::tagged_docs(args_doc, tag_method_argument_name, |name_doc| { - ret.push(name_doc.as_str_slice().to_string()); - true - }); + { + let ret_ptr = &mut ret; + let method_doc = lookup_item(id, cdata.data()); + match reader::maybe_get_doc(method_doc, tag_method_argument_names) { + Some(args_doc) => { + reader::tagged_docs(args_doc, + tag_method_argument_name, + |name_doc| { + ret_ptr.push(name_doc.as_str_slice().to_string()); + true + }); + } + None => {} } - None => {} } return ret; } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 60562e55ce687..d1cbfb0e30622 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1274,8 +1274,9 @@ fn my_visit_item(i: &Item, let mut ebml_w = unsafe { ebml_w.unsafe_clone() }; // See above let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) }; + let ebml_w_ptr = &mut ebml_w; ecx.tcx.map.with_path(i.id, |path| { - encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis); + encode_info_for_item(ecx, ebml_w_ptr, i, index, path, i.vis); }); } @@ -1293,10 +1294,9 @@ fn my_visit_foreign_item(ni: &ForeignItem, ebml_w.unsafe_clone() }; let abi = ecx.tcx.map.get_foreign_abi(ni.id); + let ebml_w_ptr = &mut ebml_w; ecx.tcx.map.with_path(ni.id, |path| { - encode_info_for_foreign_item(ecx, &mut ebml_w, - ni, index, - path, abi); + encode_info_for_foreign_item(ecx, ebml_w_ptr, ni, index, path, abi); }); } @@ -1484,14 +1484,17 @@ fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec { // Pull the cnums and name,vers,hash out of cstore let mut deps = Vec::new(); - cstore.iter_crate_data(|key, val| { - let dep = decoder::CrateDep { - cnum: key, - crate_id: decoder::get_crate_id(val.data()), - hash: decoder::get_crate_hash(val.data()) - }; - deps.push(dep); - }); + { + let deps_ptr = &mut deps; + cstore.iter_crate_data(|key, val| { + let dep = decoder::CrateDep { + cnum: key, + crate_id: decoder::get_crate_id(val.data()), + hash: decoder::get_crate_hash(val.data()) + }; + deps_ptr.push(dep); + }); + } // Sort by cnum deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum)); diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index c47d4e5d9c265..d3926f4baa611 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -34,6 +34,16 @@ pub struct FileSearch<'a> { pub triple: &'a str, } +impl<'a> Clone for FileSearch<'a> { + fn clone(&self) -> FileSearch<'a> { + FileSearch { + sysroot: self.sysroot, + addl_lib_search_paths: self.addl_lib_search_paths, + triple: self.triple, + } + } +} + impl<'a> FileSearch<'a> { pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) { let mut visited_dirs = HashSet::new(); diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 5cc8d9f7a1569..73660eb29fd56 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -195,53 +195,61 @@ impl<'a> Context<'a> { // of the crate id (path/name/id). // // The goal of this step is to look at as little metadata as possible. - self.filesearch.search(|path| { - let file = match path.filename_str() { - None => return FileDoesntMatch, - Some(file) => file, - }; - if file.starts_with(rlib_prefix.as_slice()) && - file.ends_with(".rlib") { - info!("rlib candidate: {}", path.display()); - match self.try_match(file, rlib_prefix.as_slice(), ".rlib") { - Some(hash) => { - info!("rlib accepted, hash: {}", hash); - let slot = candidates.find_or_insert_with(hash, |_| { - (HashSet::new(), HashSet::new()) - }); - let (ref mut rlibs, _) = *slot; - rlibs.insert(fs::realpath(path).unwrap()); - FileMatches - } - None => { - info!("rlib rejected"); - FileDoesntMatch - } - } - } else if file.starts_with(dylib_prefix.as_slice()) && - file.ends_with(dysuffix){ - info!("dylib candidate: {}", path.display()); - match self.try_match(file, - dylib_prefix.as_slice(), - dysuffix) { - Some(hash) => { - info!("dylib accepted, hash: {}", hash); - let slot = candidates.find_or_insert_with(hash, |_| { - (HashSet::new(), HashSet::new()) - }); - let (_, ref mut dylibs) = *slot; - dylibs.insert(fs::realpath(path).unwrap()); - FileMatches + { + let filesearch = self.filesearch.clone(); + let candidates_ptr = &mut candidates; + filesearch.search(|path| { + let file = match path.filename_str() { + None => return FileDoesntMatch, + Some(file) => file, + }; + if file.starts_with(rlib_prefix.as_slice()) && + file.ends_with(".rlib") { + info!("rlib candidate: {}", path.display()); + match self.try_match(file, + rlib_prefix.as_slice(), + ".rlib") { + Some(hash) => { + info!("rlib accepted, hash: {}", hash); + let slot = + candidates_ptr.find_or_insert_with(hash, |_| { + (HashSet::new(), HashSet::new()) + }); + let (ref mut rlibs, _) = *slot; + rlibs.insert(fs::realpath(path).unwrap()); + FileMatches + } + None => { + info!("rlib rejected"); + FileDoesntMatch + } } - None => { - info!("dylib rejected"); - FileDoesntMatch + } else if file.starts_with(dylib_prefix.as_slice()) && + file.ends_with(dysuffix){ + info!("dylib candidate: {}", path.display()); + match self.try_match(file, + dylib_prefix.as_slice(), + dysuffix) { + Some(hash) => { + info!("dylib accepted, hash: {}", hash); + let slot = + candidates_ptr.find_or_insert_with(hash, |_| { + (HashSet::new(), HashSet::new()) + }); + let (_, ref mut dylibs) = *slot; + dylibs.insert(fs::realpath(path).unwrap()); + FileMatches + } + None => { + info!("dylib rejected"); + FileDoesntMatch + } } + } else { + FileDoesntMatch } - } else { - FileDoesntMatch - } - }); + }); + } // We have now collected all known libraries into a set of candidates // keyed of the filename hash listed. For each filename, we also have a @@ -574,17 +582,22 @@ fn get_metadata_section_imp(os: Os, filename: &Path) -> Result found = Ok(MetadataVec(inflated)), - None => { - found = - Err(format_strbuf!("failed to decompress \ - metadata for: '{}'", - filename.display())) + { + let found_ptr = &mut found; + slice::raw::buf_as_slice(cvbuf1, csz-vlen, |bytes| { + match flate::inflate_bytes(bytes) { + Some(inflated) => { + *found_ptr = Ok(MetadataVec(inflated)) + } + None => { + *found_ptr = + Err(format_strbuf!("failed to decompress \ + metadata for: '{}'", + filename.display())) + } } - } - }); + }); + } if found.is_ok() { return found; } diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 9fd1fb674501d..2e9f5351e9591 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -162,14 +162,16 @@ fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore { } } -fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs { - let regions = parse_region_substs(st, |x,y| conv(x,y)); - - let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) ); +fn parse_substs(st: &mut PState, mut conv: conv_did) -> ty::substs { + let conv_ptr = &mut conv; + let regions = parse_region_substs(st, |x,y| (*conv_ptr)(x,y)); + let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| (*conv_ptr)(x,y)) ); assert_eq!(next(st), '['); let mut params: Vec = Vec::new(); - while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); } + while peek(st) != ']' { + params.push(parse_ty(st, |x,y| (*conv_ptr)(x,y))); + } st.pos = st.pos + 1u; return ty::substs { @@ -179,13 +181,15 @@ fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs { }; } -fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts { +fn parse_region_substs(st: &mut PState, mut conv: conv_did) + -> ty::RegionSubsts { + let conv_ptr = &mut conv; match next(st) { 'e' => ty::ErasedRegions, 'n' => { let mut regions = vec!(); while peek(st) != '.' { - let r = parse_region(st, |x,y| conv(x,y)); + let r = parse_region(st, |x,y| (*conv_ptr)(x,y)); regions.push(r); } assert_eq!(next(st), '.'); @@ -195,7 +199,9 @@ fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts { } } -fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion { +fn parse_bound_region(st: &mut PState, mut conv: conv_did) + -> ty::BoundRegion { + let conv_ptr = &mut conv; match next(st) { 'a' => { let id = parse_uint(st); @@ -203,7 +209,7 @@ fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion { ty::BrAnon(id) } '[' => { - let def = parse_def(st, RegionParameter, |x,y| conv(x,y)); + let def = parse_def(st, RegionParameter, |x,y| (*conv_ptr)(x,y)); let ident = token::str_to_ident(parse_str(st, ']').as_slice()); ty::BrNamed(def, ident.name) } @@ -216,13 +222,14 @@ fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::BoundRegion { } } -fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region { +fn parse_region(st: &mut PState, mut conv: conv_did) -> ty::Region { + let conv_ptr = &mut conv; match next(st) { 'b' => { assert_eq!(next(st), '['); let id = parse_uint(st) as ast::NodeId; assert_eq!(next(st), '|'); - let br = parse_bound_region(st, |x,y| conv(x,y)); + let br = parse_bound_region(st, |x,y| (*conv_ptr)(x,y)); assert_eq!(next(st), ']'); ty::ReLateBound(id, br) } @@ -239,7 +246,7 @@ fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region { assert_eq!(next(st), '['); let id = parse_uint(st) as ast::NodeId; assert_eq!(next(st), '|'); - let br = parse_bound_region(st, |x,y| conv(x,y)); + let br = parse_bound_region(st, |x,y| (*conv_ptr)(x,y)); assert_eq!(next(st), ']'); ty::ReFree(ty::FreeRegion {scope_id: id, bound_region: br}) @@ -278,13 +285,15 @@ fn parse_str(st: &mut PState, term: char) -> String { result } -fn parse_trait_ref(st: &mut PState, conv: conv_did) -> ty::TraitRef { - let def = parse_def(st, NominalType, |x,y| conv(x,y)); - let substs = parse_substs(st, |x,y| conv(x,y)); +fn parse_trait_ref(st: &mut PState, mut conv: conv_did) -> ty::TraitRef { + let conv_ptr = &mut conv; + let def = parse_def(st, NominalType, |x,y| (*conv_ptr)(x,y)); + let substs = parse_substs(st, |x,y| (*conv_ptr)(x,y)); ty::TraitRef {def_id: def, substs: substs} } -fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { +fn parse_ty(st: &mut PState, mut conv: conv_did) -> ty::t { + let conv_ptr = &mut conv; match next(st) { 'n' => return ty::mk_nil(), 'z' => return ty::mk_bot(), @@ -310,39 +319,39 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { 'c' => return ty::mk_char(), 't' => { assert_eq!(next(st), '['); - let def = parse_def(st, NominalType, |x,y| conv(x,y)); - let substs = parse_substs(st, |x,y| conv(x,y)); + let def = parse_def(st, NominalType, |x,y| (*conv_ptr)(x,y)); + let substs = parse_substs(st, |x,y| (*conv_ptr)(x,y)); assert_eq!(next(st), ']'); return ty::mk_enum(st.tcx, def, substs); } 'x' => { assert_eq!(next(st), '['); - let def = parse_def(st, NominalType, |x,y| conv(x,y)); - let substs = parse_substs(st, |x,y| conv(x,y)); - let store = parse_trait_store(st, |x,y| conv(x,y)); - let bounds = parse_bounds(st, |x,y| conv(x,y)); + let def = parse_def(st, NominalType, |x,y| (*conv_ptr)(x,y)); + let substs = parse_substs(st, |x,y| (*conv_ptr)(x,y)); + let store = parse_trait_store(st, |x,y| (*conv_ptr)(x,y)); + let bounds = parse_bounds(st, |x,y| (*conv_ptr)(x,y)); assert_eq!(next(st), ']'); return ty::mk_trait(st.tcx, def, substs, store, bounds.builtin_bounds); } 'p' => { - let did = parse_def(st, TypeParameter, |x,y| conv(x,y)); + let did = parse_def(st, TypeParameter, |x,y| (*conv_ptr)(x,y)); debug!("parsed ty_param: did={:?}", did); return ty::mk_param(st.tcx, parse_uint(st), did); } 's' => { - let did = parse_def(st, TypeParameter, |x,y| conv(x,y)); + let did = parse_def(st, TypeParameter, |x,y| (*conv_ptr)(x,y)); return ty::mk_self(st.tcx, did); } - '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| conv(x,y))), - '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| conv(x,y))), - '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| conv(x,y))), + '@' => return ty::mk_box(st.tcx, parse_ty(st, |x,y| (*conv_ptr)(x,y))), + '~' => return ty::mk_uniq(st.tcx, parse_ty(st, |x,y| (*conv_ptr)(x,y))), + '*' => return ty::mk_ptr(st.tcx, parse_mt(st, |x,y| (*conv_ptr)(x,y))), '&' => { - let r = parse_region(st, |x,y| conv(x,y)); - let mt = parse_mt(st, |x,y| conv(x,y)); + let r = parse_region(st, |x,y| (*conv_ptr)(x,y)); + let mt = parse_mt(st, |x,y| (*conv_ptr)(x,y)); return ty::mk_rptr(st.tcx, r, mt); } 'V' => { - let mt = parse_mt(st, |x,y| conv(x,y)); + let mt = parse_mt(st, |x,y| (*conv_ptr)(x,y)); let sz = parse_size(st); return ty::mk_vec(st.tcx, mt, sz); } @@ -352,15 +361,19 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { 'T' => { assert_eq!(next(st), '['); let mut params = Vec::new(); - while peek(st) != ']' { params.push(parse_ty(st, |x,y| conv(x,y))); } + while peek(st) != ']' { + params.push(parse_ty(st, |x,y| (*conv_ptr)(x,y))); + } st.pos = st.pos + 1u; return ty::mk_tup(st.tcx, params); } 'f' => { - return ty::mk_closure(st.tcx, parse_closure_ty(st, |x,y| conv(x,y))); + return ty::mk_closure(st.tcx, + parse_closure_ty(st, |x,y| (*conv_ptr)(x,y))); } 'F' => { - return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y))); + return ty::mk_bare_fn(st.tcx, + parse_bare_fn_ty(st, |x,y| (*conv_ptr)(x,y))); } '#' => { let pos = parse_hex(st); @@ -379,19 +392,19 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { pos: pos, .. *st }; - let tt = parse_ty(&mut ps, |x,y| conv(x,y)); + let tt = parse_ty(&mut ps, |x,y| (*conv_ptr)(x,y)); st.tcx.rcache.borrow_mut().insert(key, tt); return tt; } '"' => { - let _ = parse_def(st, TypeWithId, |x,y| conv(x,y)); - let inner = parse_ty(st, |x,y| conv(x,y)); + let _ = parse_def(st, TypeWithId, |x,y| (*conv_ptr)(x,y)); + let inner = parse_ty(st, |x,y| (*conv_ptr)(x,y)); inner } 'a' => { assert_eq!(next(st), '['); - let did = parse_def(st, NominalType, |x,y| conv(x,y)); - let substs = parse_substs(st, |x,y| conv(x,y)); + let did = parse_def(st, NominalType, |x,y| (*conv_ptr)(x,y)); + let substs = parse_substs(st, |x,y| (*conv_ptr)(x,y)); assert_eq!(next(st), ']'); return ty::mk_struct(st.tcx, did, substs); } @@ -406,13 +419,17 @@ fn parse_mutability(st: &mut PState) -> ast::Mutability { } } -fn parse_mt(st: &mut PState, conv: conv_did) -> ty::mt { +fn parse_mt(st: &mut PState, mut conv: conv_did) -> ty::mt { + let conv_ptr = &mut conv; let m = parse_mutability(st); - ty::mt { ty: parse_ty(st, |x,y| conv(x,y)), mutbl: m } + ty::mt { + ty: parse_ty(st, |x,y| (*conv_ptr)(x,y)), + mutbl: m, + } } -fn parse_def(st: &mut PState, source: DefIdSource, - conv: conv_did) -> ast::DefId { +fn parse_def(st: &mut PState, source: DefIdSource, conv: conv_did) + -> ast::DefId { return conv(source, scan(st, |c| { c == '|' }, parse_def_id)); } @@ -464,12 +481,13 @@ fn parse_onceness(c: char) -> ast::Onceness { } } -fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy { +fn parse_closure_ty(st: &mut PState, mut conv: conv_did) -> ty::ClosureTy { + let conv_ptr = &mut conv; let fn_style = parse_fn_style(next(st)); let onceness = parse_onceness(next(st)); - let store = parse_trait_store(st, |x,y| conv(x,y)); - let bounds = parse_bounds(st, |x,y| conv(x,y)); - let sig = parse_sig(st, |x,y| conv(x,y)); + let store = parse_trait_store(st, |x,y| (*conv_ptr)(x,y)); + let bounds = parse_bounds(st, |x,y| (*conv_ptr)(x,y)); + let sig = parse_sig(st, |x,y| (*conv_ptr)(x,y)); ty::ClosureTy { fn_style: fn_style, onceness: onceness, @@ -479,10 +497,11 @@ fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy { } } -fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy { +fn parse_bare_fn_ty(st: &mut PState, mut conv: conv_did) -> ty::BareFnTy { + let conv_ptr = &mut conv; let fn_style = parse_fn_style(next(st)); let abi = parse_abi_set(st); - let sig = parse_sig(st, |x,y| conv(x,y)); + let sig = parse_sig(st, |x,y| (*conv_ptr)(x,y)); ty::BareFnTy { fn_style: fn_style, abi: abi, @@ -490,13 +509,14 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy { } } -fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig { +fn parse_sig(st: &mut PState, mut conv: conv_did) -> ty::FnSig { + let conv_ptr = &mut conv; assert_eq!(next(st), '['); let id = parse_uint(st) as ast::NodeId; assert_eq!(next(st), '|'); let mut inputs = Vec::new(); while peek(st) != ']' { - inputs.push(parse_ty(st, |x,y| conv(x,y))); + inputs.push(parse_ty(st, |x,y| (*conv_ptr)(x,y))); } st.pos += 1u; // eat the ']' let variadic = match next(st) { @@ -504,11 +524,13 @@ fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig { 'N' => false, r => fail!(format!("bad variadic: {}", r)), }; - let ret_ty = parse_ty(st, |x,y| conv(x,y)); - ty::FnSig {binder_id: id, - inputs: inputs, - output: ret_ty, - variadic: variadic} + let ret_ty = parse_ty(st, |x,y| (*conv_ptr)(x,y)); + ty::FnSig { + binder_id: id, + inputs: inputs, + output: ret_ty, + variadic: variadic, + } } // Rust metadata parsing @@ -545,16 +567,19 @@ pub fn parse_type_param_def_data(data: &[u8], start: uint, parse_type_param_def(&mut st, conv) } -fn parse_type_param_def(st: &mut PState, conv: conv_did) -> ty::TypeParameterDef { +fn parse_type_param_def(st: &mut PState, mut conv: conv_did) + -> ty::TypeParameterDef { + let conv_ptr = &mut conv; ty::TypeParameterDef { ident: parse_ident(st, ':'), - def_id: parse_def(st, NominalType, |x,y| conv(x,y)), - bounds: Rc::new(parse_bounds(st, |x,y| conv(x,y))), - default: parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y))) + def_id: parse_def(st, NominalType, |x,y| (*conv_ptr)(x,y)), + bounds: Rc::new(parse_bounds(st, |x,y| (*conv_ptr)(x,y))), + default: parse_opt(st, |st| parse_ty(st, |x,y| (*conv_ptr)(x,y))) } } -fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { +fn parse_bounds(st: &mut PState, mut conv: conv_did) -> ty::ParamBounds { + let conv_ptr = &mut conv; let mut param_bounds = ty::ParamBounds { builtin_bounds: ty::EmptyBuiltinBounds(), trait_bounds: Vec::new() @@ -577,7 +602,8 @@ fn parse_bounds(st: &mut PState, conv: conv_did) -> ty::ParamBounds { param_bounds.builtin_bounds.add(ty::BoundShare); } 'I' => { - param_bounds.trait_bounds.push(Rc::new(parse_trait_ref(st, |x,y| conv(x,y)))); + param_bounds.trait_bounds.push(Rc::new( + parse_trait_ref(st, |x,y| (*conv_ptr)(x,y)))); } '.' => { return param_bounds; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index dbc23348e2bd4..462a61f6e8ded 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -822,22 +822,24 @@ impl<'a> ebml_writer_helpers for Encoder<'a> { fn emit_tpbt(&mut self, ecx: &e::EncodeContext, tpbt: ty::ty_param_bounds_and_ty) { + let tpbt_ref = &tpbt; self.emit_struct("ty_param_bounds_and_ty", 2, |this| { this.emit_struct_field("generics", 0, |this| { this.emit_struct("Generics", 2, |this| { this.emit_struct_field("type_param_defs", 0, |this| { - this.emit_from_vec(tpbt.generics.type_param_defs(), + this.emit_from_vec(tpbt_ref.generics + .type_param_defs(), |this, type_param_def| { Ok(this.emit_type_param_def(ecx, type_param_def)) }) }); this.emit_struct_field("region_param_defs", 1, |this| { - tpbt.generics.region_param_defs().encode(this) + tpbt_ref.generics.region_param_defs().encode(this) }) }) }); this.emit_struct_field("ty", 1, |this| { - Ok(this.emit_ty(ecx, tpbt.ty)) + Ok(this.emit_ty(ecx, tpbt_ref.ty)) }) }); } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 052baac785540..c0284df34a4f7 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -152,10 +152,13 @@ impl<'a> CheckLoanCtxt<'a> { //! we encounter `scope_id`. let mut result = Vec::new(); - self.dfcx_loans.each_gen_bit_frozen(scope_id, |loan_index| { - result.push(loan_index); - true - }); + { + let result_ptr = &mut result; + self.dfcx_loans.each_gen_bit_frozen(scope_id, |loan_index| { + result_ptr.push(loan_index); + true + }); + } return result; } @@ -168,19 +171,20 @@ impl<'a> CheckLoanCtxt<'a> { debug!("check_for_conflicting_loans(scope_id={:?})", scope_id); let new_loan_indices = self.loans_generated_by(scope_id); + let new_loan_indices_ptr = &new_loan_indices; debug!("new_loan_indices = {:?}", new_loan_indices); self.each_issued_loan(scope_id, |issued_loan| { - for &new_loan_index in new_loan_indices.iter() { + for &new_loan_index in new_loan_indices_ptr.iter() { let new_loan = &self.all_loans[new_loan_index]; self.report_error_if_loans_conflict(issued_loan, new_loan); } true }); - for (i, &x) in new_loan_indices.iter().enumerate() { + for (i, &x) in new_loan_indices_ptr.iter().enumerate() { let old_loan = &self.all_loans[x]; - for &y in new_loan_indices.slice_from(i+1).iter() { + for &y in new_loan_indices_ptr.slice_from(i+1).iter() { let new_loan = &self.all_loans[y]; self.report_error_if_loans_conflict(old_loan, new_loan); } @@ -413,10 +417,11 @@ impl<'a> CheckLoanCtxt<'a> { if self.is_local_variable(cmt.clone()) { assert!(cmt.mutbl.is_immutable()); // no "const" locals let lp = opt_loan_path(&cmt).unwrap(); - self.move_data.each_assignment_of(expr.id, &lp, |assign| { + let lp_ptr = &lp; + self.move_data.each_assignment_of(expr.id, lp_ptr, |assign| { self.bccx.report_reassigned_immutable_variable( expr.span, - &*lp, + &**lp_ptr, assign); false }); @@ -461,10 +466,6 @@ impl<'a> CheckLoanCtxt<'a> { return; } - mc::cat_upvar(..) => { - return; - } - mc::cat_deref(_, _, mc::GcPtr) => { assert_eq!(cmt.mutbl, mc::McImmutable); return; @@ -579,16 +580,21 @@ impl<'a> CheckLoanCtxt<'a> { // `RESTR_MUTATE` restriction whenever the contents of an // owned pointer are borrowed, and hence while `v[*]` is not // restricted from being written, `v` is. - let cont = this.each_in_scope_restriction(expr.id, - &*loan_path, - |loan, restr| { - if restr.set.intersects(RESTR_MUTATE) { - this.report_illegal_mutation(expr, &*loan_path, loan); - false - } else { - true - } - }); + let cont = { + let loan_path_ptr = &*loan_path; + this.each_in_scope_restriction(expr.id, + loan_path_ptr, + |loan, restr| { + if restr.set.intersects(RESTR_MUTATE) { + this.report_illegal_mutation(expr, + loan_path_ptr, + loan); + false + } else { + true + } + }) + }; if !cont { return false } @@ -633,6 +639,7 @@ impl<'a> CheckLoanCtxt<'a> { // Here the restriction that `v` not be mutated would be misapplied // to block the subpath `v[1]`. let full_loan_path = loan_path.clone(); + let full_loan_path_ptr = &*full_loan_path; let mut loan_path = loan_path; loop { loan_path = match *loan_path { @@ -654,16 +661,20 @@ impl<'a> CheckLoanCtxt<'a> { }; // Check for a non-const loan of `loan_path` + let loan_path_ptr = &mut loan_path; let cont = this.each_in_scope_loan(expr.id, |loan| { - if loan.loan_path == loan_path { - this.report_illegal_mutation(expr, &*full_loan_path, loan); + if loan.loan_path == *loan_path_ptr { + this.report_illegal_mutation(expr, + full_loan_path_ptr, + loan); false } else { true } }); - - if !cont { return false } + if !cont { + return false + } } } } @@ -721,19 +732,13 @@ impl<'a> CheckLoanCtxt<'a> { fn check_captured_variables(&self, closure_id: ast::NodeId, span: Span) { - let freevar_mode = freevars::get_capture_mode(self.tcx(), closure_id); freevars::with_freevars(self.tcx(), closure_id, |freevars| { for freevar in freevars.iter() { let var_id = ast_util::def_id_of_def(freevar.def).node; let var_path = Rc::new(LpVar(var_id)); self.check_if_path_is_moved(closure_id, span, MovedInCapture, &var_path); - match freevar_mode { - freevars::CaptureByRef => { } - freevars::CaptureByValue => { - check_by_move_capture(self, closure_id, freevar, &*var_path); - } - } + check_by_move_capture(self, closure_id, freevar, &*var_path); } }); return; @@ -775,11 +780,15 @@ impl<'a> CheckLoanCtxt<'a> { // check for a conflicting loan: let mut ret = MoveOk; - self.each_in_scope_restriction(expr_id, move_path, |loan, _| { - // Any restriction prevents moves. - ret = MoveWhileBorrowed(loan.loan_path.clone(), loan.span); - false - }); + { + let ret_ptr = &mut ret; + self.each_in_scope_restriction(expr_id, move_path, |loan, _| { + // Any restriction prevents moves. + *ret_ptr = MoveWhileBorrowed(loan.loan_path.clone(), + loan.span); + false + }); + } if ret != MoveOk { return ret diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 16fd03c1aadd4..c1bff52f8bb5f 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -128,7 +128,7 @@ fn check_and_get_illegal_move_origin(bccx: &BorrowckCtxt, mc::cat_deref(_, _, mc::BorrowedPtr(..)) | mc::cat_deref(_, _, mc::GcPtr) | mc::cat_deref(_, _, mc::UnsafePtr(..)) | - mc::cat_upvar(..) | mc::cat_static_item | + mc::cat_static_item | mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => { Some(cmt.clone()) } diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 3337a56edf008..b28ce3121bd69 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -72,7 +72,6 @@ impl<'a> GuaranteeLifetimeContext<'a> { mc::cat_copied_upvar(..) | // L-Local mc::cat_local(..) | // L-Local mc::cat_arg(..) | // L-Local - mc::cat_upvar(..) | mc::cat_deref(_, _, mc::BorrowedPtr(..)) | // L-Deref-Borrowed mc::cat_deref(_, _, mc::UnsafePtr(..)) => { self.check_scope(self.scope(cmt)) @@ -168,7 +167,6 @@ impl<'a> GuaranteeLifetimeContext<'a> { mc::cat_rvalue(temp_scope) => { temp_scope } - mc::cat_upvar(..) | mc::cat_copied_upvar(_) => { ty::ReScope(self.item_scope_id) } diff --git a/src/librustc/middle/borrowck/gather_loans/move_error.rs b/src/librustc/middle/borrowck/gather_loans/move_error.rs index 925244849bc8a..8c83368ca443b 100644 --- a/src/librustc/middle/borrowck/gather_loans/move_error.rs +++ b/src/librustc/middle/borrowck/gather_loans/move_error.rs @@ -126,7 +126,7 @@ fn report_cannot_move_out_of(bccx: &BorrowckCtxt, move_from: mc::cmt) { mc::cat_deref(_, _, mc::BorrowedPtr(..)) | mc::cat_deref(_, _, mc::GcPtr) | mc::cat_deref(_, _, mc::UnsafePtr(..)) | - mc::cat_upvar(..) | mc::cat_static_item | + mc::cat_static_item | mc::cat_copied_upvar(mc::CopiedUpvar { onceness: ast::Many, .. }) => { bccx.span_err( move_from.span, diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 552381e421653..898614f31cff6 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -73,8 +73,7 @@ impl<'a> RestrictionsContext<'a> { } mc::cat_local(local_id) | - mc::cat_arg(local_id) | - mc::cat_upvar(ty::UpvarId {var_id: local_id, ..}, _) => { + mc::cat_arg(local_id) => { // R-Variable let lp = Rc::new(LpVar(local_id)); SafeIf(lp.clone(), vec!(Restriction { diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 5dd988a82ce42..612168240f148 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -225,8 +225,7 @@ pub fn opt_loan_path(cmt: &mc::cmt) -> Option> { mc::cat_local(id) | mc::cat_arg(id) | - mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) | - mc::cat_upvar(ty::UpvarId {var_id: id, ..}, _) => { + mc::cat_copied_upvar(mc::CopiedUpvar { upvar_id: id, .. }) => { Some(Rc::new(LpVar(id))) } diff --git a/src/librustc/middle/borrowck/move_data.rs b/src/librustc/middle/borrowck/move_data.rs index 068f8442c5184..16cd7c6bf5f74 100644 --- a/src/librustc/middle/borrowck/move_data.rs +++ b/src/librustc/middle/borrowck/move_data.rs @@ -448,15 +448,16 @@ impl MoveData { fn each_extending_path(&self, index: MovePathIndex, - f: |MovePathIndex| -> bool) + mut f: |MovePathIndex| -> bool) -> bool { - if !f(index) { + let f_ptr = &mut f; + if !(*f_ptr)(index) { return false; } let mut p = self.path_first_child(index); while p != InvalidMovePathIndex { - if !self.each_extending_path(p, |x| f(x)) { + if !self.each_extending_path(p, |x| (*f_ptr)(x)) { return false; } p = self.path_next_sibling(p); @@ -467,21 +468,23 @@ impl MoveData { fn each_applicable_move(&self, index0: MovePathIndex, - f: |MoveIndex| -> bool) + mut f: |MoveIndex| -> bool) -> bool { + let f_ptr = &mut f; let mut ret = true; + let ret_ptr = &mut ret; self.each_extending_path(index0, |index| { let mut p = self.path_first_move(index); while p != InvalidMoveIndex { - if !f(p) { - ret = false; + if !(*f_ptr)(p) { + *ret_ptr = false; break; } p = self.move_next_move(p); } - ret + *ret_ptr }); - ret + *ret_ptr } fn kill_moves(&self, @@ -540,7 +543,7 @@ impl<'a> FlowedMoveData<'a> { pub fn each_move_of(&self, id: ast::NodeId, loan_path: &Rc, - f: |&Move, &LoanPath| -> bool) + mut f: |&Move, &LoanPath| -> bool) -> bool { /*! * Iterates through each move of `loan_path` (or some base path @@ -559,6 +562,8 @@ impl<'a> FlowedMoveData<'a> { // // 4. move of `a.b.c`, use of `a.b.d` + let f_ptr = &mut f; + let base_indices = self.move_data.existing_base_paths(loan_path); if base_indices.is_empty() { return true; @@ -567,6 +572,7 @@ impl<'a> FlowedMoveData<'a> { let opt_loan_path_index = self.move_data.existing_move_path(loan_path); let mut ret = true; + let ret_ptr = &mut ret; self.dfcx_moves.each_bit_on_entry_frozen(id, |index| { let move = self.move_data.moves.borrow(); @@ -575,8 +581,9 @@ impl<'a> FlowedMoveData<'a> { if base_indices.iter().any(|x| x == &moved_path) { // Scenario 1 or 2: `loan_path` or some base path of // `loan_path` was moved. - if !f(move, &*self.move_data.path_loan_path(moved_path)) { - ret = false; + if !(*f_ptr)(move, + &*self.move_data.path_loan_path(moved_path)) { + *ret_ptr = false; } } else { for &loan_path_index in opt_loan_path_index.iter() { @@ -584,15 +591,20 @@ impl<'a> FlowedMoveData<'a> { if p == loan_path_index { // Scenario 3: some extension of `loan_path` // was moved - f(move, &*self.move_data.path_loan_path(moved_path)) + (*f_ptr)(move, + &*self.move_data + .path_loan_path(moved_path)) } else { true } }); - if !cont { ret = false; break } + if !cont { + *ret_ptr = false; + break + } } } - ret + *ret_ptr }) } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index c33580d869b15..1088a174ac613 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -94,7 +94,13 @@ impl<'a> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a> { impl<'a> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for &'a cfg::CFG { fn nodes(&self) -> dot::Nodes<'a, Node<'a>> { let mut v = Vec::new(); - self.graph.each_node(|i, nd| { v.push((i, nd)); true }); + { + let v_ptr = &mut v; + self.graph.each_node(|i, nd| { + v_ptr.push((i, nd)); + true + }); + } dot::maybe_owned_vec::Growable(v) } fn edges(&self) -> dot::Edges<'a, Edge<'a>> { diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index bbea1349c1474..c28e0563b8679 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -345,16 +345,21 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, arity: uint, lty: ty::t) -> useful { - let ms = m.iter().filter_map(|r| { - specialize(cx, r.as_slice(), &ctor, arity, lty) - }).collect::(); - let could_be_useful = match specialize(cx, v, &ctor, arity, lty) { - Some(v) => is_useful(cx, &ms, v.as_slice()), - None => return not_useful, - }; + let ms; + let could_be_useful; + { + let ctor_ptr = &ctor; + ms = m.iter().filter_map(|r| { + specialize(cx, r.as_slice(), ctor_ptr, arity, lty) + }).collect::(); + could_be_useful = match specialize(cx, v, ctor_ptr, arity, lty) { + Some(v) => is_useful(cx, &ms, v.as_slice()), + None => return not_useful, + }; + } match could_be_useful { - useful_ => useful(lty, ctor), - u => u, + useful_ => useful(lty, ctor), + u => u, } } @@ -964,19 +969,19 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, let tcx = cx.tcx; let def_map = &tcx.def_map; let mut by_ref_span = None; - for pat in pats.iter() { - pat_bindings(def_map, *pat, |bm, _, span, _path| { - match bm { - BindByRef(_) => { - by_ref_span = Some(span); + { + let by_ref_span_ptr = &mut by_ref_span; + for pat in pats.iter() { + pat_bindings(def_map, *pat, |bm, _, span, _path| { + match bm { + BindByRef(_) => *by_ref_span_ptr = Some(span), + BindByValue(_) => {} } - BindByValue(_) => { - } - } - }) + }) + } } - let check_move: |&Pat, Option<@Pat>| = |p, sub| { + let mut check_move: |&Pat, Option<@Pat>| = |p, sub| { // check legality of moving out of the enum // x @ Foo(..) is legal, but x @ Foo(y) isn't. @@ -998,6 +1003,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, "by-ref binding occurs here"); } }; + let check_move_ptr = &mut check_move; for pat in pats.iter() { walk_pat(*pat, |p| { @@ -1006,7 +1012,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt, PatIdent(BindByValue(_), _, sub) => { let pat_ty = ty::node_id_to_type(tcx, p.id); if ty::type_moves_by_default(tcx, pat_ty) { - check_move(p, sub); + (*check_move_ptr)(p, sub); } } PatIdent(BindByRef(_), _, _) => { diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 91c1c0bcf9fb1..5836cb0a2b3dc 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -205,12 +205,13 @@ impl<'a, O:DataFlowOperator> DataFlowContext<'a, O> { fn compute_id_range(&mut self, id: ast::NodeId) -> (uint, uint) { let mut expanded = false; + let expanded_ptr = &mut expanded; let len = self.nodeid_to_bitset.len(); let n = self.nodeid_to_bitset.find_or_insert_with(id, |_| { - expanded = true; + *expanded_ptr = true; len }); - if expanded { + if *expanded_ptr { let entry = if self.oper.initial_value() { uint::MAX } else {0}; for _ in range(0, self.words_per_id) { self.gens.push(0); @@ -713,15 +714,16 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> { fn walk_pat(&mut self, pat: @ast::Pat, - in_out: &mut [uint], + mut in_out: &mut [uint], _loop_scopes: &mut Vec ) { debug!("DataFlowContext::walk_pat(pat={}, in_out={})", pat.repr(self.dfcx.tcx), bits_to_str(in_out)); + let in_out = &mut in_out; ast_util::walk_pat(pat, |p| { - debug!(" p.id={} in_out={}", p.id, bits_to_str(in_out)); - self.merge_with_entry_set(p.id, in_out); - self.dfcx.apply_gen_kill(p.id, in_out); + debug!(" p.id={} in_out={}", p.id, bits_to_str(*in_out)); + self.merge_with_entry_set(p.id, *in_out); + self.dfcx.apply_gen_kill(p.id, *in_out); true }); } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index b9288fd9fe56f..590ed4ad1e4e9 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -132,14 +132,15 @@ fn calculate_type(sess: &session::Session, // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. + let formats_ptr = &mut formats; sess.cstore.iter_crate_data(|cnum, data| { let src = sess.cstore.get_used_crate_source(cnum).unwrap(); if src.dylib.is_some() { - add_library(sess, cnum, cstore::RequireDynamic, &mut formats); + add_library(sess, cnum, cstore::RequireDynamic, formats_ptr); debug!("adding dylib: {}", data.name); let deps = csearch::get_dylib_dependency_formats(&sess.cstore, cnum); for &(depnum, style) in deps.iter() { - add_library(sess, depnum, style, &mut formats); + add_library(sess, depnum, style, formats_ptr); debug!("adding {}: {}", style, sess.cstore.get_crate_data(depnum).name.clone()); } @@ -148,7 +149,7 @@ fn calculate_type(sess: &session::Session, // Collect what we've got so far in the return vector. let mut ret = range(1, sess.cstore.next_crate_num()).map(|i| { - match formats.find(&i).map(|v| *v) { + match formats_ptr.find(&i).map(|v| *v) { v @ Some(cstore::RequireDynamic) => v, _ => None, } @@ -156,15 +157,19 @@ fn calculate_type(sess: &session::Session, // Run through the dependency list again, and add any missing libraries as // static libraries. - sess.cstore.iter_crate_data(|cnum, data| { - let src = sess.cstore.get_used_crate_source(cnum).unwrap(); - if src.dylib.is_none() && !formats.contains_key(&cnum) { - assert!(src.rlib.is_some()); - add_library(sess, cnum, cstore::RequireStatic, &mut formats); - *ret.get_mut(cnum as uint - 1) = Some(cstore::RequireStatic); - debug!("adding staticlib: {}", data.name); - } - }); + { + let ret_ptr = &mut ret; + sess.cstore.iter_crate_data(|cnum, data| { + let src = sess.cstore.get_used_crate_source(cnum).unwrap(); + if src.dylib.is_none() && !formats_ptr.contains_key(&cnum) { + assert!(src.rlib.is_some()); + add_library(sess, cnum, cstore::RequireStatic, formats_ptr); + *ret_ptr.get_mut(cnum as uint - 1) = + Some(cstore::RequireStatic); + debug!("adding staticlib: {}", data.name); + } + }); + } // When dylib B links to dylib A, then when using B we must also link to A. // It could be the case, however, that the rlib for A is present (hence we diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 9d735dbaeae56..8f30cefad61a5 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -791,53 +791,46 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> { let tcx = self.typer.tcx(); freevars::with_freevars(tcx, closure_expr.id, |freevars| { - match freevars::get_capture_mode(self.tcx(), closure_expr.id) { - freevars::CaptureByRef => { - self.walk_by_ref_captures(closure_expr, freevars); - } - freevars::CaptureByValue => { - self.walk_by_value_captures(closure_expr, freevars); + for freevar in freevars.iter() { + let cmt_var = return_if_err!(self.cat_captured_var( + closure_expr.id, + closure_expr.span, + freevar.def)); + let upvar_id = ty::UpvarId { + var_id: ast_util::def_id_of_def(freevar.def).node, + closure_expr_id: closure_expr.id, + }; + match self.typer + .tcx() + .upvar_borrow_map + .borrow() + .find(&upvar_id) { + None => { + self.delegate_consume(closure_expr.id, + freevar.span, + cmt_var); + } + Some(upvar_borrow) => { + let region = + ty::ty_region(tcx, + freevar.span, + upvar_borrow.reborrowed_type); + // Borrow `*x`, not `x`. + let upvar_cmt = self.mc.cat_deref(closure_expr, + cmt_var, + 0); + self.delegate.borrow(closure_expr.id, + closure_expr.span, + upvar_cmt, + region, + ty::UniqueImmBorrow, + ClosureCapture(freevar.span)); + } } } }); } - fn walk_by_ref_captures(&mut self, - closure_expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { - for freevar in freevars.iter() { - let id_var = ast_util::def_id_of_def(freevar.def).node; - let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, - closure_expr.span, - freevar.def)); - - // Lookup the kind of borrow the callee requires, as - // inferred by regionbk - let upvar_id = ty::UpvarId { var_id: id_var, - closure_expr_id: closure_expr.id }; - let upvar_borrow = self.tcx().upvar_borrow_map.borrow() - .get_copy(&upvar_id); - - self.delegate.borrow(closure_expr.id, - closure_expr.span, - cmt_var, - upvar_borrow.region, - upvar_borrow.kind, - ClosureCapture(freevar.span)); - } - } - - fn walk_by_value_captures(&mut self, - closure_expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { - for freevar in freevars.iter() { - let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id, - closure_expr.span, - freevar.def)); - self.delegate_consume(closure_expr.id, freevar.span, cmt_var); - } - } - fn cat_captured_var(&mut self, closure_id: ast::NodeId, closure_span: Span, diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 47523f4f750c1..344e841ba65bf 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -22,15 +22,6 @@ use syntax::{ast, ast_util}; use syntax::visit; use syntax::visit::Visitor; -#[deriving(Show)] -pub enum CaptureMode { - /// Copy/move the value from this llvm ValueRef into the environment. - CaptureByValue, - - /// Access by reference (used for stack closures). - CaptureByRef -} - // A vector of defs representing the free variables referred to in a function. // (The def_upvar will already have been stripped). #[deriving(Encodable, Decodable)] @@ -142,13 +133,3 @@ pub fn with_freevars(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[freevar_entry]| } } -pub fn get_capture_mode(tcx: &ty::ctxt, - closure_expr_id: ast::NodeId) - -> CaptureMode -{ - let fn_ty = ty::node_id_to_type(tcx, closure_expr_id); - match ty::ty_closure_store(fn_ty) { - ty::RegionTraitStore(..) => CaptureByRef, - ty::UniqTraitStore => CaptureByValue - } -} diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 5773d0bafa1d1..cb2a5568a6251 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -338,8 +338,9 @@ mod test { fn each_node() { let graph = create_graph(); let expected = ["A", "B", "C", "D", "E", "F"]; - graph.each_node(|idx, node| { - assert_eq!(&expected[idx.get()], graph.node_data(idx)); + let graph_ptr = &graph; + graph_ptr.each_node(|idx, node| { + assert_eq!(&expected[idx.get()], graph_ptr.node_data(idx)); assert_eq!(expected[idx.get()], node.data); true }); @@ -349,8 +350,9 @@ mod test { fn each_edge() { let graph = create_graph(); let expected = ["AB", "BC", "BD", "DE", "EC", "FB"]; - graph.each_edge(|idx, edge| { - assert_eq!(&expected[idx.get()], graph.edge_data(idx)); + let graph_ptr = &graph; + graph_ptr.each_edge(|idx, edge| { + assert_eq!(&expected[idx.get()], graph_ptr.edge_data(idx)); assert_eq!(expected[idx.get()], edge.data); true }); @@ -364,40 +366,48 @@ mod test { assert!(graph.node_data(start_index) == &start_data); let mut counter = 0; + let counter_ptr = &mut counter; graph.each_incoming_edge(start_index, |edge_index, edge| { assert!(graph.edge_data(edge_index) == &edge.data); - assert!(counter < expected_incoming.len()); + assert!(*counter_ptr < expected_incoming.len()); debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", - counter, expected_incoming[counter], edge_index, edge); - match expected_incoming[counter] { + *counter_ptr, + expected_incoming[*counter_ptr], + edge_index, + edge); + match expected_incoming[*counter_ptr] { (ref e, ref n) => { assert!(e == &edge.data); assert!(n == graph.node_data(edge.source)); assert!(start_index == edge.target); } } - counter += 1; + *counter_ptr += 1; true }); - assert_eq!(counter, expected_incoming.len()); + assert_eq!(*counter_ptr, expected_incoming.len()); let mut counter = 0; + let counter_ptr = &mut counter; graph.each_outgoing_edge(start_index, |edge_index, edge| { assert!(graph.edge_data(edge_index) == &edge.data); - assert!(counter < expected_outgoing.len()); + assert!(*counter_ptr < expected_outgoing.len()); debug!("counter={:?} expected={:?} edge_index={:?} edge={:?}", - counter, expected_outgoing[counter], edge_index, edge); - match expected_outgoing[counter] { + *counter_ptr, + expected_outgoing[*counter_ptr], + edge_index, + edge); + match expected_outgoing[*counter_ptr] { (ref e, ref n) => { assert!(e == &edge.data); assert!(start_index == edge.source); assert!(n == graph.node_data(edge.target)); } } - counter += 1; + *counter_ptr += 1; true }); - assert_eq!(counter, expected_outgoing.len()); + assert_eq!(*counter_ptr, expected_outgoing.len()); } #[test] diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 2b82dd6fd579f..907fc025b31cc 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -112,7 +112,10 @@ fn check_struct_safe_for_destructor(cx: &mut Context, } } -fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_type: &Ty) { +fn check_impl_of_trait(cx: &mut Context, + it: &Item, + trait_ref: &TraitRef, + self_type: &Ty) { let ast_trait_def = *cx.tcx.def_map.borrow() .find(&trait_ref.ref_id) .expect("trait ref not in def map!"); @@ -124,11 +127,12 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t // If this trait has builtin-kind supertraits, meet them. let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id); debug!("checking impl with self type {:?}", ty::get(self_ty).sty); - check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| { + let self_ty_ptr = &self_ty; + check_builtin_bounds(cx, *self_ty_ptr, trait_def.bounds, |cx, missing| { cx.tcx.sess.span_err(self_type.span, format!("the type `{}', which does not fulfill `{}`, cannot implement this \ trait", - ty_to_str(cx.tcx, self_ty), + ty_to_str(cx.tcx, *self_ty_ptr), missing.user_string(cx.tcx)).as_slice()); cx.tcx.sess.span_note(self_type.span, format!("types implementing this trait must fulfill `{}`", @@ -140,9 +144,14 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t match self_type.node { TyPath(_, ref bounds, path_node_id) => { assert!(bounds.is_none()); - let struct_def = cx.tcx.def_map.borrow().get_copy(&path_node_id); + let struct_def = cx.tcx + .def_map + .borrow() + .get_copy(&path_node_id); let struct_did = ast_util::def_id_of_def(struct_def); - check_struct_safe_for_destructor(cx, self_type.span, struct_did); + check_struct_safe_for_destructor(cx, + self_type.span, + struct_did); } _ => { cx.tcx.sess.span_bug(self_type.span, @@ -170,7 +179,8 @@ fn check_item(cx: &mut Context, item: &Item) { // closure. fn with_appropriate_checker(cx: &Context, id: NodeId, - b: |checker: |&Context, &freevar_entry||) { + b: |cx: &Context, + checker: |&Context, &freevar_entry||) { fn check_for_uniq(cx: &Context, fv: &freevar_entry, bounds: ty::BuiltinBounds) { // all captured data must be owned, regardless of whether it is // moved in or copied in. @@ -202,14 +212,14 @@ fn with_appropriate_checker(cx: &Context, match ty::get(fty).sty { ty::ty_closure(box ty::ClosureTy { store: ty::UniqTraitStore, bounds, .. - }) => b(|cx, fv| check_for_uniq(cx, fv, bounds)), + }) => b(cx, |cx, fv| check_for_uniq(cx, fv, bounds)), ty::ty_closure(box ty::ClosureTy { store: ty::RegionTraitStore(region, _), bounds, .. - }) => b(|cx, fv| check_for_block(cx, fv, bounds, region)), + }) => b(cx, |cx, fv| check_for_block(cx, fv, bounds, region)), ty::ty_bare_fn(_) => { - b(check_for_bare) + b(cx, check_for_bare) } ref s => { cx.tcx.sess.bug(format!("expect fn type in kind checker, not \ @@ -230,7 +240,7 @@ fn check_fn( fn_id: NodeId) { // Check kinds on free variables: - with_appropriate_checker(cx, fn_id, |chk| { + with_appropriate_checker(cx, fn_id, |cx, chk| { freevars::with_freevars(cx.tcx, fn_id, |freevars| { for fv in freevars.iter() { chk(cx, fv); @@ -369,7 +379,7 @@ fn check_ty(cx: &mut Context, aty: &Ty) { pub fn check_builtin_bounds(cx: &Context, ty: ty::t, bounds: ty::BuiltinBounds, - any_missing: |ty::BuiltinBounds|) { + any_missing: |&Context, ty::BuiltinBounds|) { let kind = ty::type_contents(cx.tcx, ty); let mut missing = ty::EmptyBuiltinBounds(); for bound in bounds.iter() { @@ -378,7 +388,7 @@ pub fn check_builtin_bounds(cx: &Context, } } if !missing.is_empty() { - any_missing(missing); + any_missing(cx, missing); } } @@ -389,7 +399,7 @@ pub fn check_typaram_bounds(cx: &Context, check_builtin_bounds(cx, ty, type_param_def.bounds.builtin_bounds, - |missing| { + |cx, missing| { cx.tcx.sess.span_err( sp, format!("instantiating a type parameter with an incompatible type \ @@ -402,7 +412,7 @@ pub fn check_typaram_bounds(cx: &Context, pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, bounds: ty::BuiltinBounds, referenced_ty: Option) { - check_builtin_bounds(cx, ty, bounds, |missing| { + check_builtin_bounds(cx, ty, bounds, |cx, missing| { // Will be Some if the freevar is implicitly borrowed (stack closure). // Emit a less mysterious error message in this case. match referenced_ty { @@ -431,7 +441,7 @@ pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t, pub fn check_trait_cast_bounds(cx: &Context, sp: Span, ty: ty::t, bounds: ty::BuiltinBounds) { - check_builtin_bounds(cx, ty, bounds, |missing| { + check_builtin_bounds(cx, ty, bounds, |cx, missing| { cx.tcx.sess.span_err(sp, format!("cannot pack type `{}`, which does not fulfill \ `{}`, as a trait bounded by {}", @@ -514,12 +524,13 @@ pub fn check_cast_for_escaping_regions( // ensure that these lifetimes are shorter than all lifetimes that are in // the source type. See test `src/test/compile-fail/regions-trait-2.rs` let mut target_regions = Vec::new(); + let target_regions_ptr = &mut target_regions; ty::walk_regions_and_ty( cx.tcx, target_ty, |r| { if !r.is_bound() { - target_regions.push(r); + target_regions_ptr.push(r); } }, |_| ()); @@ -527,7 +538,7 @@ pub fn check_cast_for_escaping_regions( // Check, based on the region associated with the trait, whether it can // possibly escape the enclosing fn item (note that all type parameters // must have been declared on the enclosing fn item). - if target_regions.iter().any(|r| is_ReScope(*r)) { + if target_regions_ptr.iter().any(|r| is_ReScope(*r)) { return; /* case (1) */ } diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index eba0bc03bf776..daeeefc3cc3f6 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -583,34 +583,37 @@ impl<'a> Context<'a> { // of what we changed so we can roll everything back after invoking the // specified closure let mut pushed = 0u; - each_lint(&self.tcx.sess, attrs, |meta, level, lintname| { - match self.dict.find_equiv(&lintname) { - None => { - self.span_lint( - UnrecognizedLint, - meta.span, - format!("unknown `{}` attribute: `{}`", - level_to_str(level), lintname).as_slice()); - } - Some(lint) => { - let lint = lint.lint; - let now = self.get_level(lint); - if now == Forbid && level != Forbid { - self.tcx.sess.span_err(meta.span, - format!("{}({}) overruled by outer forbid({})", - level_to_str(level), - lintname, - lintname).as_slice()); - } else if now != level { - let src = self.get_source(lint); - self.lint_stack.push((lint, now, src)); - pushed += 1; - self.set_level(lint, level, Node(meta.span)); + { + let pushed_ptr = &mut pushed; + each_lint(&self.tcx.sess, attrs, |meta, level, lintname| { + match self.dict.find_equiv(&lintname) { + None => { + self.span_lint( + UnrecognizedLint, + meta.span, + format!("unknown `{}` attribute: `{}`", + level_to_str(level), lintname).as_slice()); + } + Some(lint) => { + let lint = lint.lint; + let now = self.get_level(lint); + if now == Forbid && level != Forbid { + self.tcx.sess.span_err(meta.span, + format!("{}({}) overruled by outer forbid({})", + level_to_str(level), + lintname, + lintname).as_slice()); + } else if now != level { + let src = self.get_source(lint); + self.lint_stack.push((lint, now, src)); + *pushed_ptr += 1; + self.set_level(lint, level, Node(meta.span)); + } } } - } - true - }); + true + }); + } let old_is_doc_hidden = self.is_doc_hidden; self.is_doc_hidden = @@ -980,26 +983,30 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) { let mut n_box = 0; let mut n_uniq = 0; - ty::fold_ty(cx.tcx, ty, |t| { - match ty::get(t).sty { - ty::ty_box(_) => { - n_box += 1; - } - ty::ty_uniq(_) | - ty::ty_trait(box ty::TyTrait { - store: ty::UniqTraitStore, .. - }) | - ty::ty_closure(box ty::ClosureTy { - store: ty::UniqTraitStore, - .. - }) => { - n_uniq += 1; - } + { + let n_box_ptr = &mut n_box; + let n_uniq_ptr = &mut n_uniq; + ty::fold_ty(cx.tcx, ty, |t| { + match ty::get(t).sty { + ty::ty_box(_) => { + *n_box_ptr += 1; + } + ty::ty_uniq(_) | + ty::ty_trait(box ty::TyTrait { + store: ty::UniqTraitStore, .. + }) | + ty::ty_closure(box ty::ClosureTy { + store: ty::UniqTraitStore, + .. + }) => { + *n_uniq_ptr += 1; + } - _ => () - }; - t - }); + _ => () + }; + t + }); + } if n_uniq > 0 && lint != ManagedHeapMemory { let s = ty_to_str(cx.tcx, ty); @@ -1128,11 +1135,12 @@ fn check_crate_attrs_usage(cx: &Context, attrs: &[ast::Attribute]) { for attr in attrs.iter() { let name = attr.node.value.name(); + let name_ptr = &name; let mut iter = crate_attrs.iter().chain(other_attrs.iter()); - if !iter.any(|other_attr| { name.equiv(other_attr) }) { + if !iter.any(|other_attr| (*name_ptr).equiv(other_attr)) { cx.span_lint(AttributeUsage, attr.span, "unknown crate attribute"); } - if name.equiv(&("link")) { + if (*name_ptr).equiv(&("link")) { cx.tcx.sess.span_err(attr.span, "obsolete crate `link` attribute"); cx.tcx.sess.note("the link attribute has been superceded by the crate_id \ @@ -1275,11 +1283,12 @@ fn check_unused_result(cx: &Context, s: &ast::Stmt) { _ => {} } } else { + let warned_ptr = &mut warned; csearch::get_item_attrs(&cx.tcx.sess.cstore, did, |attrs| { if attr::contains_name(attrs.as_slice(), "must_use") { cx.span_lint(UnusedMustUse, s.span, "unused result which must be used"); - warned = true; + *warned_ptr = true; } }); } @@ -1481,31 +1490,38 @@ fn check_unused_mut_pat(cx: &Context, pats: &[@ast::Pat]) { // collect all mutable pattern and group their NodeIDs by their Identifier to // avoid false warnings in match arms with multiple patterns let mut mutables = HashMap::new(); - for &p in pats.iter() { - pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path| { - match mode { - ast::BindByValue(ast::MutMutable) => { - if path.segments.len() != 1 { - cx.tcx.sess.span_bug(p.span, - "mutable binding that doesn't consist \ - of exactly one segment"); + { + let mutables_ptr = &mut mutables; + for &p in pats.iter() { + let p_span = p.span.clone(); + pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path| { + match mode { + ast::BindByValue(ast::MutMutable) => { + if path.segments.len() != 1 { + cx.tcx.sess.span_bug(p_span, + "mutable binding that \ + doesn't consist of exactly \ + one segment"); + } + let ident = path.segments.get(0).identifier; + if !token::get_ident(ident).get().starts_with("_") { + mutables_ptr.insert_or_update_with( + ident.name as uint, vec!(id), |_, old| { + old.push(id); + }); + } } - let ident = path.segments.get(0).identifier; - if !token::get_ident(ident).get().starts_with("_") { - mutables.insert_or_update_with(ident.name as uint, vec!(id), |_, old| { - old.push(id); - }); + _ => { } } - _ => { - } - } - }); + }); + } } let used_mutables = cx.tcx.used_mut_nodes.borrow(); for (_, v) in mutables.iter() { - if !v.iter().any(|e| used_mutables.contains(e)) { + let used_mutables_ptr = &used_mutables; + if !v.iter().any(|e| used_mutables_ptr.contains(e)) { cx.span_lint(UnusedMut, cx.tcx.map.span(*v.get(0)), "variable does not need to be mutable"); } @@ -1737,11 +1753,14 @@ fn check_stability(cx: &Context, e: &ast::Expr) { let mut s = None; // run through all the attributes and take the first // stability one. - csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |attrs| { - if s.is_none() { - s = attr::find_stability(attrs.as_slice()) - } - }); + { + let s_ptr = &mut s; + csearch::get_item_attrs(&cx.tcx.sess.cstore, id, |attrs| { + if s_ptr.is_none() { + *s_ptr = attr::find_stability(attrs.as_slice()) + } + }); + } s }; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 5759a1005f093..34f9af36a7052 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -366,9 +366,11 @@ fn visit_fn(ir: &mut IrMaps, // swap in a new set of IR maps for this function body: let mut fn_maps = IrMaps(ir.tcx); + let fn_maps_ptr = &mut fn_maps; unsafe { - debug!("creating fn_maps: {}", transmute::<&IrMaps, *IrMaps>(&fn_maps)); + debug!("creating fn_maps: {}", + transmute::<&IrMaps, *IrMaps>(fn_maps_ptr)); } for arg in decl.inputs.iter() { @@ -377,26 +379,26 @@ fn visit_fn(ir: &mut IrMaps, |_bm, arg_id, _x, path| { debug!("adding argument {}", arg_id); let ident = ast_util::path_to_ident(path); - fn_maps.add_variable(Arg(arg_id, ident)); + fn_maps_ptr.add_variable(Arg(arg_id, ident)); }) }; // gather up the various local variables, significant expressions, // and so forth: - visit::walk_fn(&mut fn_maps, fk, decl, body, sp, ()); + visit::walk_fn(fn_maps_ptr, fk, decl, body, sp, ()); // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or fail // - implicit_ret_var is a pseudo-variable that represents // an implicit return let specials = Specials { - exit_ln: fn_maps.add_live_node(ExitNode), - fallthrough_ln: fn_maps.add_live_node(ExitNode), - no_ret_var: fn_maps.add_variable(ImplicitRet) + exit_ln: fn_maps_ptr.add_live_node(ExitNode), + fallthrough_ln: fn_maps_ptr.add_live_node(ExitNode), + no_ret_var: fn_maps_ptr.add_variable(ImplicitRet) }; // compute liveness - let mut lsets = Liveness(&mut fn_maps, specials); + let mut lsets = Liveness(fn_maps_ptr, specials); let entry_ln = lsets.compute(decl, body); // check for various error conditions @@ -481,33 +483,29 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) { // in better error messages than just pointing at the closure // construction site. let mut call_caps = Vec::new(); - let fv_mode = freevars::get_capture_mode(ir.tcx, expr.id); - freevars::with_freevars(ir.tcx, expr.id, |freevars| { - for fv in freevars.iter() { - match moved_variable_node_id_from_def(fv.def) { - Some(rv) => { - let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); - let fv_id = ast_util::def_id_of_def(fv.def).node; - let fv_ty = ty::node_id_to_type(ir.tcx, fv_id); - let is_move = match fv_mode { + { + let call_caps_ptr = &mut call_caps; + freevars::with_freevars(ir.tcx, expr.id, |freevars| { + for fv in freevars.iter() { + match moved_variable_node_id_from_def(fv.def) { + Some(rv) => { + let fv_ln = ir.add_live_node(FreeVarNode(fv.span)); + let fv_id = ast_util::def_id_of_def(fv.def).node; + let fv_ty = ty::node_id_to_type(ir.tcx, fv_id); // var must be dead afterwards - freevars::CaptureByValue => { - ty::type_moves_by_default(ir.tcx, fv_ty) - } - - // var can still be used - freevars::CaptureByRef => { - false - } - }; - call_caps.push(CaptureInfo {ln: fv_ln, - is_move: is_move, - var_nid: rv}); + let is_move = ty::type_moves_by_default(ir.tcx, + fv_ty); + call_caps_ptr.push(CaptureInfo { + ln: fv_ln, + is_move: is_move, + var_nid: rv, + }); + } + None => {} } - None => {} } - } - }); + }); + } ir.set_captures(expr.id, call_caps); visit::walk_expr(ir, expr, ()); @@ -646,12 +644,13 @@ impl<'a> Liveness<'a> { fn define_bindings_in_arm_pats(&mut self, pats: &[@Pat], succ: LiveNode) -> LiveNode { let mut succ = succ; + let succ_ptr = &mut succ; self.arm_pats_bindings(pats, |this, ln, var, _sp, _id| { - this.init_from_succ(ln, succ); + this.init_from_succ(ln, *succ_ptr); this.define(ln, var); - succ = ln; + *succ_ptr = ln; }); - succ + *succ_ptr } fn idx(&self, ln: LiveNode, var: Variable) -> uint { @@ -795,20 +794,21 @@ impl<'a> Liveness<'a> { if ln == succ_ln { return false; } let mut changed = false; + let changed_ptr = &mut changed; self.indices2(ln, succ_ln, |this, idx, succ_idx| { - changed |= copy_if_invalid(this.users.get(succ_idx).reader, + *changed_ptr |= copy_if_invalid(this.users.get(succ_idx).reader, &mut this.users.get_mut(idx).reader); - changed |= copy_if_invalid(this.users.get(succ_idx).writer, + *changed_ptr |= copy_if_invalid(this.users.get(succ_idx).writer, &mut this.users.get_mut(idx).writer); if this.users.get(succ_idx).used && !this.users.get(idx).used { this.users.get_mut(idx).used = true; - changed = true; + *changed_ptr = true; } }); debug!("merge_from_succ(ln={}, succ={}, first_merge={}, changed={})", - ln.to_str(), self.ln_str(succ_ln), first_merge, changed); - return changed; + ln.to_str(), self.ln_str(succ_ln), first_merge, *changed_ptr); + return *changed_ptr; fn copy_if_invalid(src: LiveNode, dst: &mut LiveNode) -> bool { if src.is_valid() && !dst.is_valid() { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 10357ef3d5677..8c2fe91e81f1b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -44,20 +44,6 @@ * themselves. For example, auto-derefs are explicit. Also, an index a[b] is * decomposed into two operations: a derefence to reach the array data and * then an index to jump forward to the relevant item. - * - * ## By-reference upvars - * - * One part of the translation which may be non-obvious is that we translate - * closure upvars into the dereference of a borrowed pointer; this more closely - * resembles the runtime translation. So, for example, if we had: - * - * let mut x = 3; - * let y = 5; - * let inc = || x += y; - * - * Then when we categorize `x` (*within* the closure) we would yield a - * result of `*x'`, effectively, where `x'` is a `cat_upvar` reference - * tied to `x`. The type of `x'` will be a borrowed pointer. */ #![allow(non_camel_case_types)] @@ -80,8 +66,7 @@ use std::rc::Rc; pub enum categorization { cat_rvalue(ty::Region), // temporary val, argument is its scope cat_static_item, - cat_copied_upvar(CopiedUpvar), // upvar copied into proc env - cat_upvar(ty::UpvarId, ty::UpvarBorrow), // by ref upvar from stack closure + cat_copied_upvar(CopiedUpvar), // upvar copied into closure environ. cat_local(ast::NodeId), // local variable cat_arg(ast::NodeId), // formal argument cat_deref(cmt, uint, PointerKind), // deref of a ptr @@ -546,33 +531,17 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { let ty = if_ok!(self.node_ty(fn_node_id)); match ty::get(ty).sty { ty::ty_closure(ref closure_ty) => { - // Decide whether to use implicit reference or by copy/move - // capture for the upvar. This, combined with the onceness, - // determines whether the closure can move out of it. - let var_is_refd = match (closure_ty.store, closure_ty.onceness) { - // Many-shot stack closures can never move out. - (ty::RegionTraitStore(..), ast::Many) => true, - // 1-shot stack closures can move out. - (ty::RegionTraitStore(..), ast::Once) => false, - // Heap closures always capture by copy/move, and can - // move out if they are once. - (ty::UniqTraitStore, _) => false, - - }; - if var_is_refd { - self.cat_upvar(id, span, var_id, fn_node_id) - } else { - // FIXME #2152 allow mutation of moved upvars - Ok(Rc::new(cmt_ { - id:id, - span:span, - cat:cat_copied_upvar(CopiedUpvar { - upvar_id: var_id, - onceness: closure_ty.onceness}), - mutbl:McImmutable, - ty:expr_ty - })) - } + // FIXME #2152 allow mutation of moved upvars + Ok(Rc::new(cmt_ { + id: id, + span: span, + cat: cat_copied_upvar(CopiedUpvar { + upvar_id: var_id, + onceness: closure_ty.onceness + }), + mutbl: McImmutable, + ty: expr_ty + })) } _ => { self.tcx().sess.span_bug( @@ -603,56 +572,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { } } - fn cat_upvar(&self, - id: ast::NodeId, - span: Span, - var_id: ast::NodeId, - fn_node_id: ast::NodeId) - -> McResult { - /*! - * Upvars through a closure are in fact indirect - * references. That is, when a closure refers to a - * variable from a parent stack frame like `x = 10`, - * that is equivalent to `*x_ = 10` where `x_` is a - * borrowed pointer (`&mut x`) created when the closure - * was created and store in the environment. This - * equivalence is expose in the mem-categorization. - */ - - let upvar_id = ty::UpvarId { var_id: var_id, - closure_expr_id: fn_node_id }; - - let upvar_borrow = self.typer.upvar_borrow(upvar_id); - - let var_ty = if_ok!(self.node_ty(var_id)); - - // We can't actually represent the types of all upvars - // as user-describable types, since upvars support const - // and unique-imm borrows! Therefore, we cheat, and just - // give err type. Nobody should be inspecting this type anyhow. - let upvar_ty = ty::mk_err(); - - let base_cmt = Rc::new(cmt_ { - id:id, - span:span, - cat:cat_upvar(upvar_id, upvar_borrow), - mutbl:McImmutable, - ty:upvar_ty, - }); - - let ptr = BorrowedPtr(upvar_borrow.kind, upvar_borrow.region); - - let deref_cmt = Rc::new(cmt_ { - id:id, - span:span, - cat:cat_deref(base_cmt, 0, ptr), - mutbl:MutabilityCategory::from_borrow_kind(upvar_borrow.kind), - ty:var_ty, - }); - - Ok(deref_cmt) - } - pub fn cat_rvalue_node(&self, id: ast::NodeId, span: Span, @@ -701,11 +620,11 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { self.cat_deref_common(node, base_cmt, 0, ty::mk_nil()) } - fn cat_deref(&self, - node: &N, - base_cmt: cmt, - deref_cnt: uint) - -> cmt { + pub fn cat_deref(&self, + node: &N, + base_cmt: cmt, + deref_cnt: uint) + -> cmt { let method_call = typeck::MethodCall { expr_id: node.id(), autoderef: deref_cnt as u32 @@ -924,10 +843,10 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { pub fn cat_pattern(&self, cmt: cmt, pat: &ast::Pat, - op: |&MemCategorizationContext, - cmt, - &ast::Pat|) - -> McResult<()> { + mut op: |&MemCategorizationContext, + cmt, + &ast::Pat|) + -> McResult<()> { // Here, `cmt` is the categorization for the value being // matched and pat is the pattern it is being matched against. // @@ -977,7 +896,8 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { pat.id, pprust::pat_to_str(pat), cmt.repr(self.tcx())); - op(self, cmt.clone(), pat); + let op_ptr = &mut op; + (*op_ptr)(self, cmt.clone(), pat); match pat.node { ast::PatWild | ast::PatWildMulti => { @@ -1008,7 +928,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { pat, downcast_cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(subcmt, + subpat, + |x,y,z| (*op_ptr)(x,y,z))); } } Some(&ast::DefFn(..)) | @@ -1019,12 +941,16 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { self.cat_imm_interior( pat, cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - if_ok!(self.cat_pattern(cmt_field, subpat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(cmt_field, + subpat, + |x,y,z| (*op_ptr)(x,y,z))); } } Some(&ast::DefStatic(..)) => { for &subpat in subpats.iter() { - if_ok!(self.cat_pattern(cmt.clone(), subpat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(cmt.clone(), + subpat, + |x,y,z| (*op_ptr)(x,y,z))); } } _ => { @@ -1036,7 +962,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { } ast::PatIdent(_, _, Some(subpat)) => { - if_ok!(self.cat_pattern(cmt, subpat, op)); + if_ok!(self.cat_pattern(cmt, + subpat, + |x, y, z| (*op_ptr)(x, y, z))); } ast::PatIdent(_, _, None) => { @@ -1048,7 +976,9 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { for fp in field_pats.iter() { let field_ty = if_ok!(self.pat_ty(fp.pat)); // see (*2) let cmt_field = self.cat_field(pat, cmt.clone(), fp.ident, field_ty); - if_ok!(self.cat_pattern(cmt_field, fp.pat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(cmt_field, + fp.pat, + |x,y,z| (*op_ptr)(x,y,z))); } } @@ -1060,28 +990,38 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { self.cat_imm_interior( pat, cmt.clone(), subpat_ty, InteriorField(PositionalField(i))); - if_ok!(self.cat_pattern(subcmt, subpat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(subcmt, + subpat, + |x,y,z| (*op_ptr)(x,y,z))); } } ast::PatUniq(subpat) | ast::PatRegion(subpat) => { // @p1, ~p1 let subcmt = self.cat_deref(pat, cmt, 0); - if_ok!(self.cat_pattern(subcmt, subpat, op)); + if_ok!(self.cat_pattern(subcmt, + subpat, + |x, y, z| (*op_ptr)(x, y, z))); } ast::PatVec(ref before, slice, ref after) => { let elt_cmt = self.cat_index(pat, cmt, 0); for &before_pat in before.iter() { - if_ok!(self.cat_pattern(elt_cmt.clone(), before_pat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(elt_cmt.clone(), + before_pat, + |x,y,z| (*op_ptr)(x,y,z))); } for &slice_pat in slice.iter() { let slice_ty = if_ok!(self.pat_ty(slice_pat)); let slice_cmt = self.cat_rvalue_node(pat.id(), pat.span(), slice_ty); - if_ok!(self.cat_pattern(slice_cmt, slice_pat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(slice_cmt, + slice_pat, + |x,y,z| (*op_ptr)(x,y,z))); } for &after_pat in after.iter() { - if_ok!(self.cat_pattern(elt_cmt.clone(), after_pat, |x,y,z| op(x,y,z))); + if_ok!(self.cat_pattern(elt_cmt.clone(), + after_pat, + |x,y,z| (*op_ptr)(x,y,z))); } } @@ -1103,7 +1043,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { "static item".to_string() } cat_copied_upvar(_) => { - "captured outer variable in a proc".to_string() + "captured outer variable".to_string() } cat_rvalue(..) => { "non-lvalue".to_string() @@ -1114,16 +1054,8 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { cat_arg(..) => { "argument".to_string() } - cat_deref(ref base, _, pk) => { - match base.cat { - cat_upvar(..) => { - "captured outer variable".to_string() - } - _ => { - format_strbuf!("dereference of `{}`-pointer", - ptr_sigil(pk)) - } - } + cat_deref(_, _, pk) => { + format_strbuf!("dereference of `{}`-pointer", ptr_sigil(pk)) } cat_interior(_, InteriorField(NamedField(_))) => { "field".to_string() @@ -1140,9 +1072,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> { cat_interior(_, InteriorElement(OtherElement)) => { "indexed content".to_string() } - cat_upvar(..) => { - "captured outer variable".to_string() - } cat_discr(ref cmt, _) => { self.cmt_to_str(&**cmt) } @@ -1180,8 +1109,7 @@ impl cmt_ { cat_arg(..) | cat_deref(_, _, UnsafePtr(..)) | cat_deref(_, _, GcPtr(..)) | - cat_deref(_, _, BorrowedPtr(..)) | - cat_upvar(..) => { + cat_deref(_, _, BorrowedPtr(..)) => { Rc::new((*self).clone()) } cat_downcast(ref b) | @@ -1217,14 +1145,13 @@ impl cmt_ { cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) | cat_rvalue(..) | cat_local(..) | - cat_upvar(..) | cat_arg(_) | cat_deref(_, _, UnsafePtr(..)) => { // yes, it's aliasable, but... None } cat_copied_upvar(CopiedUpvar {onceness: ast::Many, ..}) => { - Some(AliasableOther) + None } cat_static_item(..) => { @@ -1269,7 +1196,6 @@ impl Repr for categorization { cat_rvalue(..) | cat_copied_upvar(..) | cat_local(..) | - cat_upvar(..) | cat_arg(..) => { format_strbuf!("{:?}", *self) } diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 842d3bae6a764..7b8f92b91500a 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -22,9 +22,12 @@ pub type PatIdMap = HashMap; // use the NodeId of their namesake in the first pattern. pub fn pat_id_map(dm: &resolve::DefMap, pat: &Pat) -> PatIdMap { let mut map = HashMap::new(); - pat_bindings(dm, pat, |_bm, p_id, _s, n| { - map.insert(path_to_ident(n), p_id); - }); + { + let map_ptr = &mut map; + pat_bindings(dm, pat, |_bm, p_id, _s, n| { + map_ptr.insert(path_to_ident(n), p_id); + }); + } map } @@ -90,15 +93,16 @@ pub fn pat_bindings(dm: &resolve::DefMap, /// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`. pub fn pat_contains_bindings(dm: &resolve::DefMap, pat: &Pat) -> bool { let mut contains_bindings = false; + let contains_bindings_ptr = &mut contains_bindings; walk_pat(pat, |p| { if pat_is_binding(dm, p) { - contains_bindings = true; + *contains_bindings_ptr = true; false // there's at least one binding, can short circuit now. } else { true } }); - contains_bindings + *contains_bindings_ptr } pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> { diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 1a29cff3cd6dd..61271cbce2043 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1880,15 +1880,17 @@ impl<'a> Resolver<'a> { Some(def_id) => def_id, }; + let new_module = module.clone(); csearch::each_child_of_item(&self.session.cstore, def_id, |def_like, child_ident, visibility| { debug!("(populating external module) ... found ident: {}", token::get_ident(child_ident)); - self.build_reduced_graph_for_external_crate_def(module.clone(), - def_like, - child_ident, - visibility) + self.build_reduced_graph_for_external_crate_def( + new_module.clone(), + def_like, + child_ident, + visibility) }); module.populated.set(true) } @@ -4050,12 +4052,16 @@ impl<'a> Resolver<'a> { // user and one 'x' came from the macro. fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { let mut result = HashMap::new(); - pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| { - let name = mtwt::resolve(path_to_ident(path)); - result.insert(name, - binding_info {span: sp, - binding_mode: binding_mode}); - }); + { + let result_ptr = &mut result; + pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path| { + let name = mtwt::resolve(path_to_ident(path)); + result_ptr.insert(name, binding_info { + span: sp, + binding_mode: binding_mode, + }); + }); + } return result; } @@ -4260,6 +4266,7 @@ impl<'a> Resolver<'a> { // pattern that binds them mut bindings_list: Option<&mut HashMap>) { let pat_id = pattern.id; + let bindings_list_ptr = &mut bindings_list; walk_pat(pattern, |pattern| { match pattern.node { PatIdent(binding_mode, ref path, _) @@ -4347,7 +4354,7 @@ impl<'a> Resolver<'a> { // because that breaks the assumptions later // passes make about or-patterns.) - match bindings_list { + match *bindings_list_ptr { Some(ref mut bindings_list) if !bindings_list.contains_key(&renamed) => { let this = &mut *self; @@ -5120,16 +5127,30 @@ impl<'a> Resolver<'a> { } _ => { let mut method_scope = false; - self.value_ribs.borrow().iter().rev().advance(|rib| { - let res = match *rib { - Rib { bindings: _, kind: MethodRibKind(_, _) } => true, - Rib { bindings: _, kind: OpaqueFunctionRibKind } => false, - _ => return true, // Keep advancing - }; + { + let method_scope_ptr = &mut method_scope; + self.value_ribs.borrow() + .iter() + .rev() + .advance(|rib| { + let res = match *rib { + Rib { + bindings: _, + kind: MethodRibKind(_, _) + } => true, + Rib { + bindings: _, + kind: OpaqueFunctionRibKind + } => false, + _ => { + return true // Keep advancing + } + }; - method_scope = res; - false // Stop advancing - }); + *method_scope_ptr = res; + false // Stop advancing + }); + } if method_scope && token::get_name(self.self_ident.name).get() == wrong_name.as_slice() { @@ -5358,17 +5379,18 @@ impl<'a> Resolver<'a> { assert!(match lp {LastImport{..} => false, _ => true}, "Import should only be used for `use` directives"); self.last_private.insert(node_id, lp); + let session = self.session; self.def_map.borrow_mut().insert_or_update_with(node_id, def, |_, old_value| { // Resolve appears to "resolve" the same ID multiple // times, so here is a sanity check it at least comes to // the same conclusion! - nmatsakis if def != *old_value { - self.session - .bug(format!("node_id {:?} resolved first to {:?} and \ - then {:?}", - node_id, - *old_value, - def).as_slice()); + session.bug( + format!("node_id {:?} resolved first to {:?} and \ + then {:?}", + node_id, + *old_value, + def).as_slice()); } }); } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 8df57e7adfbe8..bef66c1b2d3b6 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -598,6 +598,7 @@ fn enter_opt<'a, 'b>( let tcx = bcx.tcx(); let dummy = @ast::Pat {id: 0, node: ast::PatWild, span: DUMMY_SP}; let mut i = 0; + let i_ptr = &mut i; enter_match(bcx, &tcx.def_map, m, col, val, |p| { let answer = match p.node { ast::PatEnum(..) | @@ -677,7 +678,7 @@ fn enter_opt<'a, 'b>( }; match slice { - Some(slice) if i >= lo && i <= hi => { + Some(slice) if *i_ptr >= lo && *i_ptr <= hi => { let n = before.len() + after.len(); let this_opt = vec_len(n, vec_len_ge(before.len()), (lo, hi)); @@ -695,7 +696,7 @@ fn enter_opt<'a, 'b>( None } } - None if i >= lo && i <= hi => { + None if *i_ptr >= lo && *i_ptr <= hi => { let n = before.len(); if opt_eq(tcx, &vec_len(n, vec_len_eq, (lo,hi)), opt) { let mut new_before = Vec::new(); @@ -715,7 +716,7 @@ fn enter_opt<'a, 'b>( Some(Vec::from_elem(variant_size, dummy)) } }; - i += 1; + *i_ptr += 1; answer }) } @@ -883,15 +884,22 @@ fn enter_region<'a, 'b>( fn get_options(bcx: &Block, m: &[Match], col: uint) -> Vec { let ccx = bcx.ccx(); fn add_to_set(tcx: &ty::ctxt, set: &mut Vec, val: Opt) { - if set.iter().any(|l| opt_eq(tcx, l, &val)) {return;} + { + let val_ptr = &val; + if set.iter().any(|l| opt_eq(tcx, l, val_ptr)) { + return + } + } set.push(val); } // Vector comparisons are special in that since the actual // conditions over-match, we need to be careful about them. This // means that in order to properly handle things in order, we need // to not always merge conditions. - fn add_veclen_to_set(set: &mut Vec , i: uint, - len: uint, vlo: VecLenOpt) { + fn add_veclen_to_set(set: &mut Vec, + i: uint, + len: uint, + vlo: VecLenOpt) { match set.last() { // If the last condition in the list matches the one we want // to add, then extend its range. Otherwise, make a new @@ -1509,10 +1517,19 @@ fn compile_submatch_continue<'a, 'b>( Some(ref rec_fields) => { let pat_ty = node_id_type(bcx, pat_id); let pat_repr = adt::represent_type(bcx.ccx(), pat_ty); + let pat_repr_ptr = &*pat_repr; expr::with_field_tys(tcx, pat_ty, Some(pat_id), |discr, field_tys| { + let discr_ptr = &discr; + let field_tys_ptr = &field_tys; let rec_vals = rec_fields.iter().map(|field_name| { - let ix = ty::field_idx_strict(tcx, field_name.name, field_tys); - adt::trans_field_ptr(bcx, &*pat_repr, val, discr, ix) + let ix = ty::field_idx_strict(tcx, + field_name.name, + *field_tys_ptr); + adt::trans_field_ptr(bcx, + pat_repr_ptr, + val, + *discr_ptr, + ix) }).collect::>(); compile_submatch( bcx, @@ -1845,38 +1862,41 @@ fn create_bindings_map(bcx: &Block, pat: @ast::Pat) -> BindingsMap { let ccx = bcx.ccx(); let tcx = bcx.tcx(); let mut bindings_map = HashMap::new(); - pat_bindings(&tcx.def_map, pat, |bm, p_id, span, path| { - let ident = path_to_ident(path); - let variable_ty = node_id_type(bcx, p_id); - let llvariable_ty = type_of::type_of(ccx, variable_ty); - - let llmatch; - let trmode; - match bm { - ast::BindByValue(_) => { - // in this case, the final type of the variable will be T, - // but during matching we need to store a *T as explained - // above - llmatch = alloca(bcx, llvariable_ty.ptr_to(), "__llmatch"); - trmode = TrByValue(alloca(bcx, - llvariable_ty, - bcx.ident(ident).as_slice())); - } - ast::BindByRef(_) => { - llmatch = alloca(bcx, - llvariable_ty, - bcx.ident(ident).as_slice()); - trmode = TrByRef; - } - }; - bindings_map.insert(ident, BindingInfo { - llmatch: llmatch, - trmode: trmode, - id: p_id, - span: span, - ty: variable_ty + { + let bindings_map_ptr = &mut bindings_map; + pat_bindings(&tcx.def_map, pat, |bm, p_id, span, path| { + let ident = path_to_ident(path); + let variable_ty = node_id_type(bcx, p_id); + let llvariable_ty = type_of::type_of(ccx, variable_ty); + + let llmatch; + let trmode; + match bm { + ast::BindByValue(_) => { + // in this case, the final type of the variable will be T, + // but during matching we need to store a *T as explained + // above + llmatch = alloca(bcx, llvariable_ty.ptr_to(), "__llmatch"); + trmode = TrByValue(alloca(bcx, + llvariable_ty, + bcx.ident(ident).as_slice())); + } + ast::BindByRef(_) => { + llmatch = alloca(bcx, + llvariable_ty, + bcx.ident(ident).as_slice()); + trmode = TrByRef; + } + }; + bindings_map_ptr.insert(ident, BindingInfo { + llmatch: llmatch, + trmode: trmode, + id: p_id, + span: span, + ty: variable_ty + }); }); - }); + } return bindings_map; } @@ -2038,13 +2058,19 @@ pub fn store_local<'a>(bcx: &'a Block<'a>, -> &'a Block<'a> { // create dummy memory for the variables if we have no // value to store into them immediately - let tcx = bcx.tcx(); - pat_bindings(&tcx.def_map, pat, |_, p_id, _, path| { - let scope = cleanup::var_scope(tcx, p_id); - bcx = mk_binding_alloca( - bcx, p_id, path, BindLocal, scope, (), - |(), bcx, llval, ty| { zero_mem(bcx, llval, ty); bcx }); + { + let bcx_ptr = &mut bcx; + let tcx = bcx.tcx(); + pat_bindings(&tcx.def_map, pat, |_, p_id, _, path| { + let scope = cleanup::var_scope(tcx, p_id); + *bcx_ptr = mk_binding_alloca( + *bcx_ptr, p_id, path, BindLocal, scope, (), + |(), bcx, llval, ty| { + zero_mem(bcx, llval, ty); + bcx + }); }); + } bcx } } @@ -2249,18 +2275,27 @@ fn bind_irrefutable_pat<'a>( } } ast::PatStruct(_, ref fields, _) => { - let tcx = bcx.tcx(); - let pat_ty = node_id_type(bcx, pat.id); - let pat_repr = adt::represent_type(bcx.ccx(), pat_ty); - expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| { - for f in fields.iter() { - let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys); - let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val, - discr, ix); - bcx = bind_irrefutable_pat(bcx, f.pat, fldptr, - binding_mode, cleanup_scope); - } - }) + { + let bcx_ptr = &mut bcx; + let tcx = bcx_ptr.tcx(); + let pat_ty = node_id_type(*bcx_ptr, pat.id); + let pat_repr = adt::represent_type(bcx_ptr.ccx(), pat_ty); + expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| { + for f in fields.iter() { + let ix = ty::field_idx_strict(tcx, f.ident.name, field_tys); + let fldptr = adt::trans_field_ptr(*bcx_ptr, + &*pat_repr, + val, + discr, + ix); + *bcx_ptr = bind_irrefutable_pat(*bcx_ptr, + f.pat, + fldptr, + binding_mode, + cleanup_scope); + } + }) + } } ast::PatTup(ref elems) => { let repr = adt::represent_node(bcx, pat.id); diff --git a/src/librustc/middle/trans/asm.rs b/src/librustc/middle/trans/asm.rs index 140f60c1ea973..c4306810823f4 100644 --- a/src/librustc/middle/trans/asm.rs +++ b/src/librustc/middle/trans/asm.rs @@ -32,43 +32,53 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm) let fcx = bcx.fcx; let mut bcx = bcx; let mut constraints = Vec::new(); + let constraints_ptr = &mut constraints; let mut output_types = Vec::new(); + let output_types_ptr = &mut output_types; let temp_scope = fcx.push_custom_cleanup_scope(); // Prepare the output operands - let outputs = ia.outputs.iter().map(|&(ref c, out)| { - constraints.push((*c).clone()); - - let out_datum = unpack_datum!(bcx, expr::trans(bcx, out)); - output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty)); - out_datum.val - - }).collect::>(); + let outputs = { + let bcx_ptr = &mut bcx; + ia.outputs.iter().map(|&(ref c, out)| { + constraints_ptr.push((*c).clone()); + + let out_datum = unpack_datum!(*bcx_ptr, + expr::trans(*bcx_ptr, out)); + output_types_ptr.push(type_of::type_of(bcx_ptr.ccx(), + out_datum.ty)); + out_datum.val + }).collect::>() + }; // Now the input operands - let inputs = ia.inputs.iter().map(|&(ref c, input)| { - constraints.push((*c).clone()); - - let in_datum = unpack_datum!(bcx, expr::trans(bcx, input)); - unpack_result!(bcx, { - callee::trans_arg_datum(bcx, - expr_ty(bcx, input), - in_datum, - cleanup::CustomScope(temp_scope), - callee::DontAutorefArg) - }) - }).collect::>(); + let inputs = { + let bcx_ptr = &mut bcx; + ia.inputs.iter().map(|&(ref c, input)| { + constraints_ptr.push((*c).clone()); + + let in_datum = unpack_datum!(*bcx_ptr, + expr::trans(*bcx_ptr, input)); + unpack_result!(*bcx_ptr, { + callee::trans_arg_datum(*bcx_ptr, + expr_ty(*bcx_ptr, input), + in_datum, + cleanup::CustomScope(temp_scope), + callee::DontAutorefArg) + }) + }).collect::>() + }; // no failure occurred preparing operands, no need to cleanup fcx.pop_custom_cleanup_scope(temp_scope); let mut constraints = - String::from_str(constraints.iter() - .map(|s| s.get().to_string()) - .collect::>() - .connect(",") - .as_slice()); + String::from_str(constraints_ptr.iter() + .map(|s| s.get().to_string()) + .collect::>() + .connect(",") + .as_slice()); let mut clobbers = getClobbers(); if !ia.clobbers.get().is_empty() && !clobbers.is_empty() { @@ -93,9 +103,9 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm) let output_type = if num_outputs == 0 { Type::void(bcx.ccx()) } else if num_outputs == 1 { - *output_types.get(0) + *output_types_ptr.get(0) } else { - Type::struct_(bcx.ccx(), output_types.as_slice(), false) + Type::struct_(bcx.ccx(), output_types_ptr.as_slice(), false) }; let dialect = match ia.dialect { @@ -103,18 +113,16 @@ pub fn trans_inline_asm<'a>(bcx: &'a Block<'a>, ia: &ast::InlineAsm) ast::AsmIntel => lib::llvm::AD_Intel }; - let r = ia.asm.get().with_c_str(|a| { - constraints.as_slice().with_c_str(|c| { - InlineAsmCall(bcx, - a, - c, + let asm_c = ia.asm.get().to_c_str(); + let constraints_c = constraints.to_c_str(); + let r = InlineAsmCall(bcx, + asm_c.with_ref(|x| x), + constraints_c.with_ref(|x| x), inputs.as_slice(), output_type, ia.volatile, ia.alignstack, - dialect) - }) - }); + dialect); // Again, based on how many outputs we have if num_outputs == 1 { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 77ce3b3249f3b..7fec1a09c7862 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -623,7 +623,7 @@ pub fn iter_structural_ty<'r, cx: &'b Block<'b>, av: ValueRef, t: ty::t, - f: val_and_ty_fn<'r,'b>) + mut f: val_and_ty_fn<'r,'b>) -> &'b Block<'b> { let _icx = push_ctxt("iter_structural_ty"); @@ -652,10 +652,16 @@ pub fn iter_structural_ty<'r, match ty::get(t).sty { ty::ty_struct(..) => { let repr = adt::represent_type(cx.ccx(), t); - expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| { + let f_ptr = &mut f; + let cx_ptr = &mut cx; + expr::with_field_tys(cx_ptr.tcx(), t, None, |discr, field_tys| { for (i, field_ty) in field_tys.iter().enumerate() { - let llfld_a = adt::trans_field_ptr(cx, &*repr, av, discr, i); - cx = f(cx, llfld_a, field_ty.mt.ty); + let llfld_a = adt::trans_field_ptr(*cx_ptr, + &*repr, + av, + discr, + i); + *cx_ptr = (*f_ptr)(*cx_ptr, llfld_a, field_ty.mt.ty); } }) } @@ -688,7 +694,8 @@ pub fn iter_structural_ty<'r, substs, f); } (_match::switch, Some(lldiscrim_a)) => { - cx = f(cx, lldiscrim_a, ty::mk_int()); + let f_ptr = &mut f; + cx = (*f_ptr)(cx, lldiscrim_a, ty::mk_int()); let unr_cx = fcx.new_temp_block("enum-iter-unr"); Unreachable(unr_cx); let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, @@ -715,7 +722,7 @@ pub fn iter_structural_ty<'r, av, &**variant, substs, - |x,y,z| f(x,y,z)); + |x,y,z| (*f_ptr)(x,y,z)); Br(variant_cx, next_cx.llbb); } cx = next_cx; @@ -2327,9 +2334,12 @@ pub fn trans_crate(krate: ast::Crate, let link_meta = ccx.link_meta.clone(); let llmod = ccx.llmod; - let mut reachable: Vec = ccx.reachable.iter().filter_map(|id| { - ccx.item_symbols.borrow().find(id).map(|s| s.to_string()) - }).collect(); + let mut reachable: Vec = { + let ccx_ptr = &ccx; + ccx_ptr.reachable.iter().filter_map(|id| { + ccx_ptr.item_symbols.borrow().find(id).map(|s| s.to_string()) + }).collect() + }; // Make sure that some other crucial symbols are not eliminated from the // module. This includes the main function, the crate map (used for debug diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 29ea9157126d8..9635923730276 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -99,13 +99,12 @@ use syntax::ast_util; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ pub struct EnvValue { - action: freevars::CaptureMode, datum: Datum } impl EnvValue { pub fn to_str(&self, ccx: &CrateContext) -> String { - format_strbuf!("{}({})", self.action, self.datum.to_str(ccx)) + format_strbuf!("({})", self.datum.to_str(ccx)) } } @@ -117,12 +116,7 @@ pub fn mk_closure_tys(tcx: &ty::ctxt, // is the actual types that will be stored in the map, not the // logical types as the user sees them, so by-ref upvars must be // converted to ptrs. - let bound_tys = bound_values.iter().map(|bv| { - match bv.action { - freevars::CaptureByValue => bv.datum.ty, - freevars::CaptureByRef => ty::mk_mut_ptr(tcx, bv.datum.ty) - } - }).collect(); + let bound_tys = bound_values.iter().map(|bv| bv.datum.ty).collect(); let cdata_ty = ty::mk_tup(tcx, bound_tys); debug!("cdata_ty={}", ty_to_str(tcx, cdata_ty)); return cdata_ty; @@ -209,15 +203,7 @@ pub fn store_environment<'a>( } let bound_data = GEPi(bcx, llbox, [0u, abi::box_field_body, i]); - - match bv.action { - freevars::CaptureByValue => { - bcx = bv.datum.store_to(bcx, bound_data); - } - freevars::CaptureByRef => { - Store(bcx, bv.datum.to_llref(), bound_data); - } - } + bcx = bv.datum.store_to(bcx, bound_data); } ClosureResult { llbox: llbox, cdata_ty: cdata_ty, bcx: bcx } @@ -226,7 +212,6 @@ pub fn store_environment<'a>( // Given a context and a list of upvars, build a closure. This just // collects the upvars and packages them up for store_environment. fn build_closure<'a>(bcx0: &'a Block<'a>, - freevar_mode: freevars::CaptureMode, freevars: &Vec, store: ty::TraitStore) -> ClosureResult<'a> @@ -240,7 +225,9 @@ fn build_closure<'a>(bcx0: &'a Block<'a>, let mut env_vals = Vec::new(); for freevar in freevars.iter() { let datum = expr::trans_local_var(bcx, freevar.def); - env_vals.push(EnvValue {action: freevar_mode, datum: datum}); + env_vals.push(EnvValue { + datum: datum + }); } store_environment(bcx, env_vals, store) @@ -277,11 +264,7 @@ fn load_environment<'a>(bcx: &'a Block<'a>, // Populate the upvars from the environment let mut i = 0u; for freevar in freevars.iter() { - let mut upvarptr = GEPi(bcx, llcdata, [0u, i]); - match store { - ty::RegionTraitStore(..) => { upvarptr = Load(bcx, upvarptr); } - ty::UniqTraitStore => {} - } + let upvarptr = GEPi(bcx, llcdata, [0u, i]); let def_id = ast_util::def_id_of_def(freevar.def); bcx.fcx.llupvars.borrow_mut().insert(def_id.node, upvarptr); @@ -350,14 +333,16 @@ pub fn trans_expr_fn<'a>( // set an inline hint for all closures set_inline_hint(llfn); - let freevar_mode = freevars::get_capture_mode(tcx, id); let freevars: Vec = - freevars::with_freevars( - tcx, id, - |fv| fv.iter().map(|&fv| fv).collect()); - - let ClosureResult {llbox, cdata_ty, bcx} = - build_closure(bcx, freevar_mode, &freevars, store); + freevars::with_freevars(tcx, + id, + |fv| fv.iter().map(|&fv| fv).collect()); + + let ClosureResult { + llbox, + cdata_ty, + bcx + } = build_closure(bcx, &freevars, store); trans_closure(ccx, decl, body, llfn, bcx.fcx.param_substs, id, [], ty::ty_fn_ret(fty), diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 8b43e99b6ac6d..79f1d0308fbdd 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -539,23 +539,39 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, None => None }; + let cx_ptr = &cx; + let repr_ptr = &*repr; expr::with_field_tys(tcx, ety, Some(e.id), |discr, field_tys| { - let (cs, inlineable) = vec::unzip(field_tys.iter().enumerate() - .map(|(ix, &field_ty)| { - match fs.iter().find(|f| field_ty.ident.name == f.ident.node.name) { - Some(f) => const_expr(cx, (*f).expr, is_local), + let discr_ptr = &discr; + let field_tys_ptr = &field_tys; + let (cs, inlineable) = + vec::unzip(field_tys_ptr.iter() + .enumerate() + .map(|(ix, &field_ty)| { + let field_ty_name = field_ty.ident.name.clone(); + match fs.iter() + .find(|f| field_ty_name == f.ident.node.name) { + Some(f) => const_expr(*cx_ptr, (*f).expr, is_local), None => { match base_val { Some((bv, inlineable)) => { - (adt::const_get_field(cx, &*repr, bv, discr, ix), + (adt::const_get_field(*cx_ptr, + repr_ptr, + bv, + *discr_ptr, + ix), inlineable) } - None => cx.sess().span_bug(e.span, "missing struct field") + None => { + cx_ptr.sess() + .span_bug(e.span, + "missing struct field") + } } } } })); - (adt::trans_const(cx, &*repr, discr, cs.as_slice()), + (adt::trans_const(*cx_ptr, repr_ptr, discr, cs.as_slice()), inlineable.iter().fold(true, |a, &b| a && b)) }) } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 744200c80e8a4..973d772722e88 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -349,22 +349,23 @@ pub fn create_global_var_metadata(cx: &CrateContext, namespace_node.mangled_name_of_contained_item(var_name.as_slice()); let var_scope = namespace_node.scope; - var_name.as_slice().with_c_str(|var_name| { - linkage_name.as_slice().with_c_str(|linkage_name| { - unsafe { - llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx), - var_scope, - var_name, - linkage_name, - file_metadata, - loc.line as c_uint, - type_metadata, - is_local_to_unit, - global, - ptr::null()); - } - }) - }); + let file_metadata_ptr = &file_metadata; + let type_metadata_ptr = &type_metadata; + let var_name_c = var_name.to_c_str(); + let linkage_name_c = linkage_name.to_c_str(); + unsafe { + llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx), + var_scope, + var_name_c.with_ref(|x| x), + linkage_name_c.with_ref(|x| + x), + *file_metadata_ptr, + loc.line as c_uint, + *type_metadata_ptr, + is_local_to_unit, + global, + ptr::null()); + } } /// Creates debug information for the given local variable. @@ -744,28 +745,26 @@ pub fn create_function_debug_context(cx: &CrateContext, let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id); - let fn_metadata = function_name.as_slice().with_c_str(|function_name| { - linkage_name.as_slice().with_c_str(|linkage_name| { - unsafe { - llvm::LLVMDIBuilderCreateFunction( - DIB(cx), - containing_scope, - function_name, - linkage_name, - file_metadata, - loc.line as c_uint, - function_type_metadata, - is_local_to_unit, - true, - scope_line as c_uint, - FlagPrototyped as c_uint, - cx.sess().opts.optimize != config::No, - llfn, - template_parameters, - ptr::null()) - } - }) - }); + let function_name_c = function_name.to_c_str(); + let linkage_name_c = linkage_name.to_c_str(); + let fn_metadata = unsafe { + llvm::LLVMDIBuilderCreateFunction( + DIB(cx), + containing_scope, + function_name_c.with_ref(|x| x), + linkage_name_c.with_ref(|x| x), + file_metadata, + loc.line as c_uint, + function_type_metadata, + is_local_to_unit, + true, + scope_line as c_uint, + FlagPrototyped as c_uint, + cx.sess().opts.optimize != config::No, + llfn, + template_parameters, + ptr::null()) + }; // Initialize fn debug context (including scope map and namespace map) let fn_debug_context = box FunctionDebugContextData { @@ -981,28 +980,22 @@ fn compile_unit_metadata(cx: &CrateContext) { let producer = format!("rustc version {}", (option_env!("CFG_VERSION")).expect("CFG_VERSION")); - compile_unit_name.with_ref(|compile_unit_name| { - work_dir.as_vec().with_c_str(|work_dir| { - producer.with_c_str(|producer| { - "".with_c_str(|flags| { - "".with_c_str(|split_name| { - unsafe { - llvm::LLVMDIBuilderCreateCompileUnit( - debug_context(cx).builder, - DW_LANG_RUST, - compile_unit_name, - work_dir, - producer, - cx.sess().opts.optimize != config::No, - flags, - 0, - split_name); - } - }) - }) - }) - }) - }); + let work_dir_c = work_dir.to_c_str(); + let producer_c = producer.to_c_str(); + let flags_c = "".to_c_str(); + let split_name_c = "".to_c_str(); + unsafe { + llvm::LLVMDIBuilderCreateCompileUnit( + debug_context(cx).builder, + DW_LANG_RUST, + compile_unit_name.with_ref(|x| x), + work_dir_c.with_ref(|x| x), + producer_c.with_ref(|x| x), + cx.sess().opts.optimize != config::No, + flags_c.with_ref(|x| x), + 0, + split_name_c.with_ref(|x| x)); + } fn fallback_path(cx: &CrateContext) -> CString { cx.link_meta.crateid.name.as_slice().to_c_str() @@ -1031,6 +1024,7 @@ fn declare_local(bcx: &Block, CapturedVariable => (0, DW_TAG_auto_variable) }; + let loc_line = loc.line as c_uint; let (var_alloca, var_metadata) = name.get().with_c_str(|name| { match variable_access { DirectVariable { alloca } => ( @@ -1042,7 +1036,7 @@ fn declare_local(bcx: &Block, scope_metadata, name, file_metadata, - loc.line as c_uint, + loc_line, type_metadata, cx.sess().opts.optimize != config::No, 0, @@ -1058,7 +1052,7 @@ fn declare_local(bcx: &Block, scope_metadata, name, file_metadata, - loc.line as c_uint, + loc_line, type_metadata, address_operations.as_ptr(), address_operations.len() as c_uint, @@ -1582,44 +1576,51 @@ fn prepare_enum_metadata(cx: &CrateContext, }) .collect(); - let discriminant_type_metadata = |inttype| { - // We can reuse the type of the discriminant for all monomorphized instances of an enum - // because it doesn't depend on any type parameters. The def_id, uniquely identifying the - // enum's polytype acts as key in this cache. - let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types - .borrow() - .find_copy(&enum_def_id); - match cached_discriminant_type_metadata { - Some(discriminant_type_metadata) => discriminant_type_metadata, - None => { - let discriminant_llvm_type = adt::ll_inttype(cx, inttype); - let (discriminant_size, discriminant_align) = - size_and_align_of(cx, discriminant_llvm_type); - let discriminant_base_type_metadata = type_metadata(cx, - adt::ty_of_inttype(inttype), - codemap::DUMMY_SP); - let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); - - let discriminant_type_metadata = discriminant_name.get().with_c_str(|name| { - unsafe { + let loc_line = loc.line; + let discriminant_type_metadata = { + |inttype| { + // We can reuse the type of the discriminant for all monomorphized + // instances of an enum because it doesn't depend on any type + // parameters. The def_id, uniquely identifying the enum's + // polytype acts as key in this cache. + let cached_discriminant_type_metadata = + debug_context(cx).created_enum_disr_types + .borrow() + .find_copy(&enum_def_id); + match cached_discriminant_type_metadata { + Some(discriminant_type_metadata) => discriminant_type_metadata, + None => { + let discriminant_llvm_type = adt::ll_inttype(cx, inttype); + let (discriminant_size, discriminant_align) = + size_and_align_of(cx, discriminant_llvm_type); + let discriminant_base_type_metadata = + type_metadata(cx, + adt::ty_of_inttype(inttype), + codemap::DUMMY_SP); + let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); + + let discriminant_name = + discriminant_name.get().to_c_str(); + let discriminant_type_metadata = unsafe { llvm::LLVMDIBuilderCreateEnumerationType( DIB(cx), containing_scope, - name, + discriminant_name.with_ref(|x| x), file_metadata, - loc.line as c_uint, + loc_line as c_uint, bytes_to_bits(discriminant_size), bytes_to_bits(discriminant_align), - create_DIArray(DIB(cx), enumerators_metadata.as_slice()), + create_DIArray(DIB(cx), + enumerators_metadata.as_slice()), discriminant_base_type_metadata) - } - }); + }; - debug_context(cx).created_enum_disr_types - .borrow_mut() - .insert(enum_def_id, discriminant_type_metadata); + debug_context(cx).created_enum_disr_types + .borrow_mut() + .insert(enum_def_id, discriminant_type_metadata); - discriminant_type_metadata + discriminant_type_metadata + } } } }; @@ -1656,24 +1657,23 @@ fn prepare_enum_metadata(cx: &CrateContext, let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type); let unique_id = generate_unique_type_id("DI_ENUM_"); - let enum_metadata = enum_name.as_slice().with_c_str(|enum_name| { - unique_id.as_slice().with_c_str(|unique_id| { - unsafe { - llvm::LLVMDIBuilderCreateUnionType( - DIB(cx), - containing_scope, - enum_name, - file_metadata, - loc.line as c_uint, - bytes_to_bits(enum_type_size), - bytes_to_bits(enum_type_align), - 0, // Flags - ptr::null(), - 0, // RuntimeLang - unique_id) - } - }) - }); + let loc_line = loc.line as c_uint; + let enum_name_c = enum_name.to_c_str(); + let unique_id_c = unique_id.to_c_str(); + let enum_metadata = unsafe { + llvm::LLVMDIBuilderCreateUnionType( + DIB(cx), + containing_scope, + enum_name_c.with_ref(|x| x), + file_metadata, + loc_line, + bytes_to_bits(enum_type_size), + bytes_to_bits(enum_type_align), + 0, // Flags + ptr::null(), + 0, // RuntimeLang + unique_id_c.with_ref(|x| x)) + }; UnfinishedMetadata { cache_id: cache_id_for_type(enum_type), @@ -1802,21 +1802,20 @@ fn set_members_of_composite_type(cx: &CrateContext, ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i) }; - member_description.name.as_slice().with_c_str(|member_name| { - unsafe { - llvm::LLVMDIBuilderCreateMemberType( - DIB(cx), - composite_type_metadata, - member_name, - file_metadata, - loc.line as c_uint, - bytes_to_bits(member_size), - bytes_to_bits(member_align), - bytes_to_bits(member_offset), - 0, - member_description.type_metadata) - } - }) + let member_name_c = member_description.name.to_c_str(); + unsafe { + llvm::LLVMDIBuilderCreateMemberType( + DIB(cx), + composite_type_metadata, + member_name_c.with_ref(|x| x), + file_metadata, + loc.line as c_uint, + bytes_to_bits(member_size), + bytes_to_bits(member_align), + bytes_to_bits(member_offset), + 0, + member_description.type_metadata) + } }) .collect(); @@ -1843,28 +1842,27 @@ fn create_struct_stub(cx: &CrateContext, let unique_id = generate_unique_type_id("DI_STRUCT_"); return unsafe { - struct_type_name.with_c_str(|name| { - unique_id.as_slice().with_c_str(|unique_id| { - // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to - // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp - let empty_array = create_DIArray(DIB(cx), []); + let struct_type_name_c = struct_type_name.to_c_str(); + let unique_id_c = unique_id.to_c_str(); - llvm::LLVMDIBuilderCreateStructType( - DIB(cx), - containing_scope, - name, - file_metadata, - loc.line as c_uint, - bytes_to_bits(struct_size), - bytes_to_bits(struct_align), - 0, - ptr::null(), - empty_array, - 0, - ptr::null(), - unique_id) - }) - }) + // LLVMDIBuilderCreateStructType() wants an empty array. A null pointer will lead to + // hard to trace and debug LLVM assertions later on in llvm/lib/IR/Value.cpp + let empty_array = create_DIArray(DIB(cx), []); + + llvm::LLVMDIBuilderCreateStructType( + DIB(cx), + containing_scope, + struct_type_name_c.with_ref(|x| x), + file_metadata, + loc.line as c_uint, + bytes_to_bits(struct_size), + bytes_to_bits(struct_align), + 0, + ptr::null(), + empty_array, + 0, + ptr::null(), + unique_id_c.with_ref(|x| x)) }; } @@ -2422,9 +2420,13 @@ fn populate_scope_map(cx: &CrateContext, // Push argument identifiers onto the stack so arguments integrate nicely with variable // shadowing. for &arg_pat in arg_pats.iter() { + let scope_stack_ptr = &mut scope_stack; pat_util::pat_bindings(def_map, arg_pat, |_, _, _, path_ref| { let ident = ast_util::path_to_ident(path_ref); - scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata, ident: Some(ident) }); + scope_stack_ptr.push(ScopeStackEntry { + scope_metadata: fn_metadata, + ident: Some(ident), + }); }) } diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index f254422226fcd..9c21c93b0fd8d 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -438,13 +438,31 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>, let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field")); let repr = adt::represent_type(bcx.ccx(), base_datum.ty); - with_field_tys(bcx.tcx(), base_datum.ty, None, |discr, field_tys| { - let ix = ty::field_idx_strict(bcx.tcx(), field.name, field_tys); - let d = base_datum.get_element( + let repr_ptr = &repr; + let d = { + let bcx_ptr = &mut bcx; + with_field_tys(bcx_ptr.tcx(), + base_datum.ty, + None, + |discr, field_tys| { + let ix = ty::field_idx_strict(bcx_ptr.tcx(), + field.name, + field_tys); + base_datum.get_element( field_tys[ix].mt.ty, - |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, ix)); - DatumBlock { datum: d.to_expr_datum(), bcx: bcx } + |srcval| { + adt::trans_field_ptr(*bcx_ptr, + &**repr_ptr, + srcval, + discr, + ix) + }) }) + }; + DatumBlock { + datum: d.to_expr_datum(), + bcx: bcx, + } } fn trans_index<'a>(bcx: &'a Block<'a>, @@ -971,6 +989,7 @@ fn trans_rec_or_struct<'a>( let tcx = bcx.tcx(); with_field_tys(tcx, ty, Some(id), |discr, field_tys| { let mut need_base = Vec::from_elem(field_tys.len(), true); + let need_base_ptr = &mut need_base; let numbered_fields = fields.iter().map(|field| { let opt_pos = @@ -978,7 +997,7 @@ fn trans_rec_or_struct<'a>( field_ty.ident.name == field.ident.node.name); match opt_pos { Some(i) => { - *need_base.get_mut(i) = false; + *need_base_ptr.get_mut(i) = false; (i, field.expr) } None => { @@ -990,7 +1009,7 @@ fn trans_rec_or_struct<'a>( let optbase = match base { Some(base_expr) => { let mut leftovers = Vec::new(); - for (i, b) in need_base.iter().enumerate() { + for (i, b) in need_base_ptr.iter().enumerate() { if *b { leftovers.push((i, field_tys[i].mt.ty)) } @@ -999,7 +1018,7 @@ fn trans_rec_or_struct<'a>( fields: leftovers }) } None => { - if need_base.iter().any(|b| *b) { + if need_base_ptr.iter().any(|b| *b) { tcx.sess.span_bug(expr_span, "missing fields and no base expr") } None diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 96fb8ac0e980c..9eeb9022c2fce 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -611,13 +611,14 @@ pub fn trans_rust_fn_with_foreign_abi(ccx: &CrateContext, // Array for the arguments we will pass to the rust function. let mut llrust_args = Vec::new(); let mut next_foreign_arg_counter: c_uint = 0; + let next_foreign_arg_counter_ptr = &mut next_foreign_arg_counter; let next_foreign_arg: |pad: bool| -> c_uint = |pad: bool| { - next_foreign_arg_counter += if pad { + *next_foreign_arg_counter_ptr += if pad { 2 } else { 1 }; - next_foreign_arg_counter - 1 + *next_foreign_arg_counter_ptr - 1 }; // If there is an out pointer on the foreign function diff --git a/src/librustc/middle/trans/macros.rs b/src/librustc/middle/trans/macros.rs index 313280cb7a8cc..40f288c4585ae 100644 --- a/src/librustc/middle/trans/macros.rs +++ b/src/librustc/middle/trans/macros.rs @@ -11,7 +11,7 @@ #![macro_escape] macro_rules! unpack_datum( - ($bcx: ident, $inp: expr) => ( + ($bcx: expr, $inp: expr) => ( { let db = $inp; $bcx = db.bcx; @@ -21,7 +21,7 @@ macro_rules! unpack_datum( ) macro_rules! unpack_result( - ($bcx: ident, $inp: expr) => ( + ($bcx: expr, $inp: expr) => ( { let db = $inp; $bcx = db.bcx; diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index e0fd872fb06a7..def5dc33719e3 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -192,22 +192,27 @@ pub fn monomorphic_fn(ccx: &CrateContext, monomorphizing.insert(fn_id, depth + 1); } - let s = ccx.tcx.map.with_path(fn_id.node, |path| { - let mut state = sip::SipState::new(); - hash_id.hash(&mut state); - mono_ty.hash(&mut state); - - exported_name(path, - format!("h{}", state.result()).as_slice(), - ccx.link_meta.crateid.version_or_default()) - }); + let s = { + let hash_id_ptr = &hash_id; + ccx.tcx.map.with_path(fn_id.node, |path| { + let mut state = sip::SipState::new(); + hash_id_ptr.hash(&mut state); + mono_ty.hash(&mut state); + + exported_name(path, + format!("h{}", state.result()).as_slice(), + ccx.link_meta.crateid.version_or_default()) + }) + }; debug!("monomorphize_fn mangled to {}", s); // This shouldn't need to option dance. let mut hash_id = Some(hash_id); + let hash_id_ptr = &mut hash_id; let mk_lldecl = || { let lldecl = decl_internal_rust_fn(ccx, mono_ty, s.as_slice()); - ccx.monomorphized.borrow_mut().insert(hash_id.take_unwrap(), lldecl); + ccx.monomorphized.borrow_mut().insert(hash_id_ptr.take_unwrap(), + lldecl); lldecl }; diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 4b81463ed795f..48c8850219836 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -287,6 +287,7 @@ impl<'a, 'b> Reflector<'a, 'b> { let opaqueptrty = ty::mk_ptr(ccx.tcx(), ty::mt { ty: opaquety, mutbl: ast::MutImmutable }); + let repr_ptr = &*repr; let make_get_disr = || { let sym = mangle_internal_name_by_path_and_seq( ast_map::Values([].iter()).chain(None), "get_disr"); @@ -311,7 +312,10 @@ impl<'a, 'b> Reflector<'a, 'b> { }; let bcx = fcx.entry_bcx.borrow().clone().unwrap(); let arg = BitCast(bcx, arg, llptrty); - let ret = adt::trans_get_discr(bcx, &*repr, arg, Some(Type::i64(ccx))); + let ret = adt::trans_get_discr(bcx, + repr_ptr, + arg, + Some(Type::i64(ccx))); Store(bcx, ret, fcx.llretptr.get().unwrap()); match fcx.llreturn.get() { Some(llreturn) => Br(bcx, llreturn), @@ -336,7 +340,11 @@ impl<'a, 'b> Reflector<'a, 'b> { for (j, a) in v.args.iter().enumerate() { let bcx = this.bcx; let null = C_null(llptrty); - let ptr = adt::trans_field_ptr(bcx, &*repr, null, v.disr_val, j); + let ptr = adt::trans_field_ptr(bcx, + repr_ptr, + null, + v.disr_val, + j); let offset = p2i(ccx, ptr); let field_args = [this.c_uint(j), offset, diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 4421c84e86f3c..3a6e626b77119 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -392,10 +392,13 @@ pub fn write_content<'a>( let elem = unpack_datum!(bcx, expr::trans(bcx, element)); assert!(!ty::type_moves_by_default(bcx.tcx(), elem.ty)); - let bcx = iter_vec_loop(bcx, lldest, vt, + let bcx = { + let elem_ptr = &elem; + iter_vec_loop(bcx, lldest, vt, C_uint(bcx.ccx(), count), |set_bcx, lleltptr, _| { - elem.shallow_copy_and_take(set_bcx, lleltptr) - }); + elem_ptr.shallow_copy_and_take(set_bcx, lleltptr) + }) + }; elem.add_clean_if_rvalue(bcx, element.id); bcx diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index fe8db6fa8a11f..d335c5d75e815 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -551,59 +551,10 @@ pub enum BorrowKind { MutBorrow } -/** - * Information describing the borrowing of an upvar. This is computed - * during `typeck`, specifically by `regionck`. The general idea is - * that the compiler analyses treat closures like: - * - * let closure: &'e fn() = || { - * x = 1; // upvar x is assigned to - * use(y); // upvar y is read - * foo(&z); // upvar z is borrowed immutably - * }; - * - * as if they were "desugared" to something loosely like: - * - * struct Vars<'x,'y,'z> { x: &'x mut int, - * y: &'y const int, - * z: &'z int } - * let closure: &'e fn() = { - * fn f(env: &Vars) { - * *env.x = 1; - * use(*env.y); - * foo(env.z); - * } - * let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x, - * y: &'y const y, - * z: &'z z }; - * (env, f) - * }; - * - * This is basically what happens at runtime. The closure is basically - * an existentially quantified version of the `(env, f)` pair. - * - * This data structure indicates the region and mutability of a single - * one of the `x...z` borrows. - * - * It may not be obvious why each borrowed variable gets its own - * lifetime (in the desugared version of the example, these are indicated - * by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition). - * Each such lifetime must encompass the lifetime `'e` of the closure itself, - * but need not be identical to it. The reason that this makes sense: - * - * - Callers are only permitted to invoke the closure, and hence to - * use the pointers, within the lifetime `'e`, so clearly `'e` must - * be a sublifetime of `'x...'z`. - * - The closure creator knows which upvars were borrowed by the closure - * and thus `x...z` will be reserved for `'x...'z` respectively. - * - Through mutation, the borrowed upvars can actually escape - * the closure, so sometimes it is necessary for them to be larger - * than the closure lifetime itself. - */ +/// Information describing the borrowing of an upvar. #[deriving(Eq, Clone)] pub struct UpvarBorrow { - pub kind: BorrowKind, - pub region: ty::Region, + pub reborrowed_type: t, } pub type UpvarBorrowMap = HashMap; @@ -1481,30 +1432,41 @@ pub fn walk_ty(ty: t, f: |t|) { maybe_walk_ty(ty, |t| { f(t); true }); } -pub fn maybe_walk_ty(ty: t, f: |t| -> bool) { - if !f(ty) { +pub fn maybe_walk_ty(ty: t, mut f: |t| -> bool) { + let f_ptr = &mut f; + if !(*f_ptr)(ty) { return; } match get(ty).sty { - ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_str | ty_self(_) | + ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | + ty_float(_) | ty_str | ty_self(_) | ty_infer(_) | ty_param(_) | ty_err => {} - ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f), + ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, |x| (*f_ptr)(x)), ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => { - maybe_walk_ty(tm.ty, f); + maybe_walk_ty(tm.ty, |x| (*f_ptr)(x)); } ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_trait(box TyTrait { ref substs, .. }) => { - for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); } + for subty in (*substs).tps.iter() { + maybe_walk_ty(*subty, |x| (*f_ptr)(x)); + } + } + ty_tup(ref ts) => { + for tt in ts.iter() { + maybe_walk_ty(*tt, |x| (*f_ptr)(x)); + } } - ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } } ty_bare_fn(ref ft) => { - for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); } - maybe_walk_ty(ft.sig.output, f); + for a in ft.sig.inputs.iter() { + maybe_walk_ty(*a, |x| (*f_ptr)(x)); + } + maybe_walk_ty(ft.sig.output, |x| (*f_ptr)(x)); } ty_closure(ref ft) => { - for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); } - maybe_walk_ty(ft.sig.output, f); + for a in ft.sig.inputs.iter() { + maybe_walk_ty(*a, |x| (*f_ptr)(x)); + } + maybe_walk_ty(ft.sig.output, |x| (*f_ptr)(x)); } } } @@ -1730,11 +1692,13 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t, let mut encountered_box = encountered_box; let mut needs_unwind_cleanup = false; + let encountered_box_ptr = &mut encountered_box; + let needs_unwind_cleanup_ptr = &mut needs_unwind_cleanup; maybe_walk_ty(ty, |ty| { - let old_encountered_box = encountered_box; + let old_encountered_box = *encountered_box_ptr; let result = match get(ty).sty { ty_box(_) => { - encountered_box = true; + *encountered_box_ptr = true; true } ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | @@ -1745,34 +1709,34 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t, for v in (*enum_variants(cx, did)).iter() { for aty in v.args.iter() { let t = subst(cx, substs, *aty); - needs_unwind_cleanup |= + *needs_unwind_cleanup_ptr |= type_needs_unwind_cleanup_(cx, t, tycache, - encountered_box); + *encountered_box_ptr); } } - !needs_unwind_cleanup + !*needs_unwind_cleanup_ptr } ty_uniq(_) => { // Once we're inside a box, the annihilator will find // it and destroy it. - if !encountered_box { - needs_unwind_cleanup = true; + if !*encountered_box_ptr { + *needs_unwind_cleanup_ptr = true; false } else { true } } _ => { - needs_unwind_cleanup = true; + *needs_unwind_cleanup_ptr = true; false } }; - encountered_box = old_encountered_box; + *encountered_box_ptr = old_encountered_box; result }); - return needs_unwind_cleanup; + return *needs_unwind_cleanup_ptr; } /** @@ -2250,8 +2214,9 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { -> TypeContents { let _i = indenter(); let mut tc = TC::All; + let tc_ptr = &mut tc; each_inherited_builtin_bound(cx, bounds, traits, |bound| { - tc = tc - match bound { + *tc_ptr = *tc_ptr - match bound { BoundStatic => TC::Nonstatic, BoundSend => TC::Nonsendable, BoundSized => TC::Nonsized, @@ -2259,7 +2224,7 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { BoundShare => TC::Nonsharable, }; }); - return tc; + return *tc_ptr; // Iterates over all builtin bounds on the type parameter def, including // those inherited from traits with builtin-kind-supertraits. @@ -3218,14 +3183,15 @@ pub fn method_idx(id: ast::Ident, meths: &[Rc]) -> Option { /// to a bitset or some other representation. pub fn param_tys_in_type(ty: t) -> Vec { let mut rslt = Vec::new(); - walk_ty(ty, |ty| { - match get(ty).sty { - ty_param(p) => { - rslt.push(p); - } - _ => () - } - }); + { + let rslt_ptr = &mut rslt; + walk_ty(ty, |ty| { + match get(ty).sty { + ty_param(p) => rslt_ptr.push(p), + _ => () + } + }); + } rslt } @@ -3797,12 +3763,14 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc>> { match item.node { ast::ItemEnum(ref enum_definition, _) => { let mut last_discriminant: Option = None; + let last_discriminant_ptr = &mut last_discriminant; Rc::new(enum_definition.variants.iter().map(|&variant| { - let mut discriminant = match last_discriminant { - Some(val) => val + 1, - None => INITIAL_DISCRIMINANT_VALUE - }; + let mut discriminant = + match *last_discriminant_ptr { + Some(val) => val + 1, + None => INITIAL_DISCRIMINANT_VALUE + }; match variant.node.disr_expr { Some(e) => match const_eval::eval_const_expr_partial(cx, e) { @@ -3827,7 +3795,7 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc>> { None => {} }; - last_discriminant = Some(discriminant); + *last_discriminant_ptr = Some(discriminant); Rc::new(VariantInfo::from_ast_variant(cx, variant, discriminant)) }).collect()) @@ -3897,16 +3865,19 @@ pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc { /// Iterate over attributes of a definition. // (This should really be an iterator, but that would require csearch and // decoder to use iterators instead of higher-order functions.) -pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool { +pub fn each_attr(tcx: &ctxt, did: DefId, mut f: |&ast::Attribute| -> bool) + -> bool { if is_local(did) { let item = tcx.map.expect_item(did.node); item.attrs.iter().advance(|attr| f(attr)) } else { info!("getting foreign attrs"); let mut cont = true; + let cont_ptr = &mut cont; + let f_ptr = &mut f; csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| { - if cont { - cont = attrs.iter().advance(|attr| f(attr)); + if *cont_ptr { + *cont_ptr = attrs.iter().advance(|attr| (*f_ptr)(attr)); } }); info!("done"); @@ -3917,15 +3888,16 @@ pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool { /// Determine whether an item is annotated with an attribute pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool { let mut found = false; + let found_ptr = &mut found; each_attr(tcx, did, |item| { if item.check_name(attr) { - found = true; + *found_ptr = true; false } else { true } }); - found + *found_ptr } /// Determine whether an item is annotated with `#[packed]` @@ -3941,11 +3913,14 @@ pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool { // Obtain the representation annotation for a definition. pub fn lookup_repr_hint(tcx: &ctxt, did: DefId) -> attr::ReprAttr { let mut acc = attr::ReprAny; + let acc_ptr = &mut acc; ty::each_attr(tcx, did, |meta| { - acc = attr::find_repr_attr(tcx.sess.diagnostic(), meta, acc); + *acc_ptr = attr::find_repr_attr(tcx.sess.diagnostic(), + meta, + *acc_ptr); true }); - return acc; + return *acc_ptr; } // Look up a field ID, whether or not it's local @@ -3973,11 +3948,12 @@ pub fn lookup_field_type(tcx: &ctxt, // Lookup all ancestor structs of a struct indicated by did. That is the reflexive, // transitive closure of doing a single lookup in cx.superstructs. -fn each_super_struct(cx: &ctxt, mut did: ast::DefId, f: |ast::DefId|) { +fn each_super_struct(cx: &ctxt, mut did: ast::DefId, mut f: |ast::DefId|) { let superstructs = cx.superstructs.borrow(); + let f_ptr = &mut f; loop { - f(did); + (*f_ptr)(did); match superstructs.find(&did) { Some(&Some(def_id)) => { did = def_id; @@ -4002,16 +3978,20 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec { // we could cache the whole list of fields here. let struct_fields = cx.struct_fields.borrow(); let mut results: SmallVector<&[field_ty]> = SmallVector::zero(); - each_super_struct(cx, did, |s| { - match struct_fields.find(&s) { - Some(fields) => results.push(fields.as_slice()), - _ => { - cx.sess.bug( - format!("ID not mapped to struct fields: {}", - cx.map.node_to_str(did.node)).as_slice()); + { + let struct_fields_ptr = &struct_fields; + let results_ptr = &mut results; + each_super_struct(cx, did, |s| { + match struct_fields_ptr.find(&s) { + Some(fields) => results_ptr.push(fields.as_slice()), + _ => { + cx.sess.bug( + format!("ID not mapped to struct fields: {}", + cx.map.node_to_str(did.node)).as_slice()); + } } - } - }); + }); + } let len = results.as_slice().iter().map(|x| x.len()).sum(); let mut result: Vec = Vec::with_capacity(len); @@ -4486,8 +4466,10 @@ pub fn trait_method_of_method(tcx: &ctxt, /// context it's calculated within. This is used by the `type_id` intrinsic. pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { let mut state = sip::SipState::new(); - macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } ); - macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } ); + let state_ptr = &mut state; + + macro_rules! byte( ($b:expr) => { ($b as u8).hash(state_ptr) } ); + macro_rules! hash( ($e:expr) => { $e.hash(state_ptr) } ); let region = |_state: &mut sip::SipState, r: Region| { match r { @@ -4538,7 +4520,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { } ty_enum(d, _) => { byte!(8); - did(&mut state, d); + did(state_ptr, d); } ty_box(_) => { byte!(9); @@ -4548,22 +4530,22 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { } ty_vec(m, Some(_)) => { byte!(11); - mt(&mut state, m); - 1u8.hash(&mut state); + mt(state_ptr, m); + 1u8.hash(state_ptr); } ty_vec(m, None) => { byte!(11); - mt(&mut state, m); - 0u8.hash(&mut state); + mt(state_ptr, m); + 0u8.hash(state_ptr); } ty_ptr(m) => { byte!(12); - mt(&mut state, m); + mt(state_ptr, m); } ty_rptr(r, m) => { byte!(13); - region(&mut state, r); - mt(&mut state, m); + region(state_ptr, r); + mt(state_ptr, m); } ty_bare_fn(ref b) => { byte!(14); @@ -4579,19 +4561,19 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1) - region(&mut state, r); + region(state_ptr, r); assert_eq!(m, ast::MutMutable); } } } ty_trait(box ty::TyTrait { def_id: d, store, bounds, .. }) => { byte!(17); - did(&mut state, d); + did(state_ptr, d); match store { UniqTraitStore => byte!(0), RegionTraitStore(r, m) => { byte!(1) - region(&mut state, r); + region(state_ptr, r); hash!(m); } } @@ -4599,7 +4581,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { } ty_struct(d, _) => { byte!(18); - did(&mut state, d); + did(state_ptr, d); } ty_tup(ref inner) => { byte!(19); @@ -4608,18 +4590,18 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { ty_param(p) => { byte!(20); hash!(p.idx); - did(&mut state, p.def_id); + did(state_ptr, p.def_id); } ty_self(d) => { byte!(21); - did(&mut state, d); + did(state_ptr, d); } ty_infer(_) => unreachable!(), ty_err => byte!(23), } }); - state.result() + state_ptr.result() } impl Variance { @@ -4695,15 +4677,21 @@ pub fn construct_parameter_environment( // Compute the bounds on Self and the type parameters. // - let self_bound_substd = self_bound.map(|b| b.subst(tcx, &free_substs)); - let type_param_bounds_substd = Vec::from_fn(num_type_params, |i| { - if i < num_item_type_params { - (*item_type_params[i].bounds).subst(tcx, &free_substs) - } else { - let j = i - num_item_type_params; - (*method_type_params[j].bounds).subst(tcx, &free_substs) - } - }); + let self_bound_substd = { + let free_substs_ptr = &free_substs; + self_bound.map(|b| b.subst(tcx, free_substs_ptr)) + }; + let type_param_bounds_substd = { + let free_substs_ptr = &free_substs; + Vec::from_fn(num_type_params, |i| { + if i < num_item_type_params { + (*item_type_params[i].bounds).subst(tcx, free_substs_ptr) + } else { + let j = i - num_item_type_params; + (*method_type_params[j].bounds).subst(tcx, free_substs_ptr) + } + }) + }; debug!("construct_parameter_environment: free_id={} \ free_subst={} \ diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 9cc5d2d73ca1d..20e50f4a9366a 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -793,6 +793,7 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, // new region names that appear inside of the fn decl are bound to // that function type let rb = rscope::BindingRscope::new(id); + let rb_ptr = &rb; let self_ty = opt_self_info.and_then(|self_info| { match self_info.explicit_self.node { @@ -802,7 +803,8 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, } ast::SelfRegion(ref lifetime, mutability) => { let region = - opt_ast_region_to_region(this, &rb, + opt_ast_region_to_region(this, + rb_ptr, self_info.explicit_self.span, lifetime); Some(ty::mk_rptr(this.tcx(), region, @@ -821,13 +823,14 @@ fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, } else { decl.inputs.as_slice() }; - let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None)); + let input_tys = input_tys.iter() + .map(|a| ty_of_arg(this, rb_ptr, a, None)); let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect(); let output_ty = match decl.output.node { ast::TyInfer => this.ty_infer(decl.output.span), - _ => ast_ty_to_ty(this, &rb, decl.output) + _ => ast_ty_to_ty(this, rb_ptr, decl.output) }; return ty::BareFnTy { @@ -859,18 +862,22 @@ pub fn ty_of_closure( // that function type let rb = rscope::BindingRscope::new(id); - let input_tys = decl.inputs.iter().enumerate().map(|(i, a)| { - let expected_arg_ty = expected_sig.as_ref().and_then(|e| { - // no guarantee that the correct number of expected args - // were supplied - if i < e.inputs.len() { - Some(*e.inputs.get(i)) - } else { - None - } - }); - ty_of_arg(this, &rb, a, expected_arg_ty) - }).collect(); + let input_tys = { + let expected_sig_ptr = &expected_sig; + let rb_ptr = &rb; + decl.inputs.iter().enumerate().map(|(i, a)| { + let expected_arg_ty = (*expected_sig_ptr).as_ref().and_then(|e| { + // no guarantee that the correct number of expected args + // were supplied + if i < e.inputs.len() { + Some(*e.inputs.get(i)) + } else { + None + } + }); + ty_of_arg(this, rb_ptr, a, expected_arg_ty) + }).collect() + }; let expected_ret_ty = expected_sig.map(|e| e.output); let output_ty = match decl.output.node { @@ -884,10 +891,12 @@ pub fn ty_of_closure( onceness: onceness, store: store, bounds: bounds, - sig: ty::FnSig {binder_id: id, - inputs: input_tys, - output: output_ty, - variadic: decl.variadic} + sig: ty::FnSig { + binder_id: id, + inputs: input_tys, + output: output_ty, + variadic: decl.variadic, + } } } diff --git a/src/librustc/middle/typeck/check/demand.rs b/src/librustc/middle/typeck/check/demand.rs index dc9aa1b7e8cb2..d82522ace618e 100644 --- a/src/librustc/middle/typeck/check/demand.rs +++ b/src/librustc/middle/typeck/check/demand.rs @@ -37,8 +37,11 @@ pub fn suptype_with_fn(fcx: &FnCtxt, ty_b: ty::t, handle_err: |Span, ty::t, ty::t, &ty::type_err|) { // n.b.: order of actual, expected is reversed - match infer::mk_subty(fcx.infcx(), b_is_expected, infer::Misc(sp), - ty_b, ty_a) { + match infer::mk_subty(fcx.infcx(), + b_is_expected, + infer::Misc(sp), + ty_b, + ty_a) { result::Ok(()) => { /* ok */ } result::Err(ref err) => { handle_err(sp, ty_a, ty_b, err); @@ -47,7 +50,11 @@ pub fn suptype_with_fn(fcx: &FnCtxt, } pub fn eqtype(fcx: &FnCtxt, sp: Span, expected: ty::t, actual: ty::t) { - match infer::mk_eqty(fcx.infcx(), false, infer::Misc(sp), actual, expected) { + match infer::mk_eqty(fcx.infcx(), + false, + infer::Misc(sp), + actual, + expected) { Ok(()) => { /* ok */ } Err(ref err) => { fcx.report_mismatched_types(sp, expected, actual, err); diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 6b3d026e0e515..c22b5dce6dcd5 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -219,13 +219,18 @@ fn get_method_index(tcx: &ty::ctxt, // we find the trait the method came from, counting up the // methods from them. let mut method_count = 0; - ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| { - if bound_ref.def_id == trait_ref.def_id { false } - else { - method_count += ty::trait_methods(tcx, bound_ref.def_id).len(); - true - } - }); + { + let method_count_ptr = &mut method_count; + ty::each_bound_trait_and_supertraits(tcx, &[subtrait], |bound_ref| { + if bound_ref.def_id == trait_ref.def_id { + false + } else { + *method_count_ptr += + ty::trait_methods(tcx, bound_ref.def_id).len(); + true + } + }); + } method_count + n_method } @@ -616,10 +621,11 @@ impl<'a> LookupContext<'a> { -> Option) { let tcx = self.tcx(); let mut next_bound_idx = 0; // count only trait bounds + let next_bound_idx_ptr = &mut next_bound_idx; ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| { - let this_bound_idx = next_bound_idx; - next_bound_idx += 1; + let this_bound_idx = *next_bound_idx_ptr; + *next_bound_idx_ptr += 1; let trait_methods = ty::trait_methods(tcx, bound_trait_ref.def_id); match trait_methods.iter().position(|m| { @@ -686,8 +692,13 @@ impl<'a> LookupContext<'a> { .collect::>() .repr(self.tcx())); - let method = match impl_methods.iter().map(|&did| ty::method(self.tcx(), did)) - .find(|m| m.ident.name == self.m_name) { + let my_m_name = self.m_name.clone(); + let method = match impl_methods.iter() + .map(|&did| { + ty::method(self.tcx(), did) + }).find(|m| { + m.ident.name == my_m_name + }) { Some(method) => method, None => { return; } // No method with the right name. }; @@ -1195,8 +1206,9 @@ impl<'a> LookupContext<'a> { MethodObject(..) => { // For annoying reasons, we've already handled the // substitution of self for object calls. + let all_substs_ptr = &all_substs; let args = fn_sig.inputs.slice_from(1).iter().map(|t| { - t.subst(tcx, &all_substs) + t.subst(tcx, all_substs_ptr) }); Some(*fn_sig.inputs.get(0)).move_iter().chain(args).collect() } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index cdf8b50a1cd23..bc872c6809bf8 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -78,6 +78,7 @@ type parameter). use middle::const_eval; +use middle::freevars; use middle::lang_items::{ExchangeHeapLangItem, GcLangItem}; use middle::lang_items::{ManagedHeapLangItem}; use middle::lint::UnreachableCode; @@ -485,15 +486,15 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>, }; { - let mut visit = GatherLocalsVisitor { fcx: &fcx, }; + let visit_ptr = &mut visit; // Add formal parameters. for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) { // Create type variables for each argument. pat_util::pat_bindings(&tcx.def_map, input.pat, |_bm, pat_id, _sp, _path| { - visit.assign(pat_id, None); + visit_ptr.assign(pat_id, None); }); // Check the pattern. @@ -504,7 +505,7 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>, _match::check_pat(&pcx, input.pat, *arg_ty); } - visit.visit_block(body, ()); + visit_ptr.visit_block(body, ()); } check_block_with_expected(&fcx, body, Some(ret_ty)); @@ -515,10 +516,11 @@ fn check_fn<'a>(ccx: &'a CrateCtxt<'a>, Some(tail_expr) => { // Special case: we print a special error if there appears // to be do-block/for-loop confusion + let fcx_ptr = &fcx; demand::suptype_with_fn(&fcx, tail_expr.span, false, fcx.ret_ty, fcx.expr_ty(tail_expr), |sp, e, a, s| { - fcx.report_mismatched_return_types(sp, e, a, s); + fcx_ptr.report_mismatched_return_types(sp, e, a, s); }); } None => {} @@ -804,9 +806,10 @@ fn check_impl_methods_against_trait(ccx: &CrateCtxt, // If this is an impl of a trait method, find the corresponding // method definition in the trait. + let impl_method_ty_ident_name = impl_method_ty.ident.name.clone(); let opt_trait_method_ty = trait_methods.iter(). - find(|tm| tm.ident.name == impl_method_ty.ident.name); + find(|tm| tm.ident.name == impl_method_ty_ident_name); match opt_trait_method_ty { Some(trait_method_ty) => { compare_impl_method(ccx.tcx, @@ -2308,9 +2311,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, let expected_sty = unpack_expected(fcx, expected, |x| Some((*x).clone())); - let (expected_sig, - expected_onceness, - expected_bounds) = { + let (expected_sig, expected_onceness, expected_bounds) = { match expected_sty { Some(ty::ty_closure(ref cenv)) => { let (_, sig) = @@ -2361,6 +2362,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt, decl, expected_sig); let fty_sig = fn_ty.sig.clone(); + + reborrow_mutable_upvars_if_necessary(fcx, expr, &fn_ty); + let fty = ty::mk_closure(tcx, fn_ty); debug!("check_expr_fn fty={}", fcx.infcx().ty_to_str(fty)); @@ -2375,8 +2379,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt, ty::UniqTraitStore => (ast::NormalFn, expr.id) }; - check_fn(fcx.ccx, inherited_style, &fty_sig, - decl, id, body, fn_kind, fcx.inh); + check_fn(fcx.ccx, + inherited_style, + &fty_sig, + decl, + id, + body, + fn_kind, + fcx.inh); } @@ -3179,8 +3189,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } else { let el = ty::sequence_element_type(fcx.tcx(), t1); - infer::mk_eqty(fcx.infcx(), false, - infer::Misc(sp), el, t2).is_ok() + infer::mk_eqty(fcx.infcx(), + false, + infer::Misc(sp), + el, + t2).is_ok() } } @@ -3257,6 +3270,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt, }); let mut bot_field = false; let mut err_field = false; + let bot_field_ptr = &mut bot_field; + let err_field_ptr = &mut err_field; let elt_ts = elts.iter().enumerate().map(|(i, e)| { let opt_hint = match flds { @@ -3265,13 +3280,13 @@ fn check_expr_with_unifier(fcx: &FnCtxt, }; check_expr_with_opt_hint(fcx, *e, opt_hint); let t = fcx.expr_ty(*e); - err_field = err_field || ty::type_is_error(t); - bot_field = bot_field || ty::type_is_bot(t); + *err_field_ptr = *err_field_ptr || ty::type_is_error(t); + *bot_field_ptr = *bot_field_ptr || ty::type_is_bot(t); t }).collect(); - if bot_field { + if *bot_field_ptr { fcx.write_bot(id); - } else if err_field { + } else if *err_field_ptr { fcx.write_error(id); } else { let typ = ty::mk_tup(tcx, elt_ts); @@ -4200,18 +4215,19 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt, // make a vector of booleans initially false, set to true when used if tps.len() == 0u { return; } let mut tps_used = Vec::from_elem(tps.len(), false); + let tps_used_ptr = &mut tps_used; ty::walk_ty(ty, |t| { match ty::get(t).sty { ty::ty_param(param_ty {idx, ..}) => { debug!("Found use of ty param \\#{}", idx); - *tps_used.get_mut(idx) = true; + *tps_used_ptr.get_mut(idx) = true; } _ => () } }); - for (i, b) in tps_used.iter().enumerate() { + for (i, b) in tps_used_ptr.iter().enumerate() { if !*b { ccx.tcx.sess.span_err( span, @@ -4518,3 +4534,58 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { }); } } + +fn reborrow_mutable_upvars_if_necessary(fcx: &FnCtxt, + expr: &ast::Expr, + closure_type: &ty::ClosureTy) { + freevars::with_freevars(fcx.tcx(), expr.id, |freevars| { + for freevar in freevars.iter() { + let upvar_node_id = ast_util::def_id_of_def(freevar.def).node; + let typ = fcx.node_ty(upvar_node_id); + let typ = structurally_resolved_type(fcx, freevar.span, typ); + match ty::get(typ).sty { + ty::ty_rptr(original_region, mutable) + if mutable.mutbl == ast::MutMutable => { + let upvar_id = ty::UpvarId { + var_id: upvar_node_id, + closure_expr_id: expr.id, + }; + let new_region = + fcx.infcx() + .next_region_var(infer::UpvarRegion(upvar_id, + freevar.span)); + fcx.mk_subr(true, + infer::ReborrowUpvar(freevar.span, upvar_id), + new_region, + original_region); + + let closure_lifetime = match closure_type.store { + ty::UniqTraitStore => ty::ReStatic, + ty::RegionTraitStore(region, _) => region, + }; + fcx.mk_subr(false, + infer::ReborrowUpvar(freevar.span, upvar_id), + closure_lifetime, + new_region); + + debug!("reborrowing mutable upvar: old region {}, \ + reborrowed region {}", + original_region.repr(fcx.tcx()), + new_region.repr(fcx.tcx())); + let new_type = ty::mk_rptr(fcx.tcx(), + new_region, + mutable); + fcx.inh + .upvar_borrow_map + .borrow_mut() + .insert(upvar_id, + ty::UpvarBorrow { + reborrowed_type: new_type, + }); + } + _ => {} + } + } + }); +} + diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 34e8b5e169ff8..49bf809a07eab 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -134,9 +134,7 @@ use middle::pat_util; use util::nodemap::NodeMap; use util::ppaux::{ty_to_str, region_to_str, Repr}; -use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar}; use syntax::ast; -use syntax::ast_util; use syntax::codemap::Span; use syntax::visit; use syntax::visit::Visitor; @@ -163,31 +161,6 @@ pub struct Rcx<'a> { repeating_scope: ast::NodeId, } -fn region_of_def(fcx: &FnCtxt, def: ast::Def) -> ty::Region { - /*! - * Returns the validity region of `def` -- that is, how long - * is `def` valid? - */ - - let tcx = fcx.tcx(); - match def { - DefLocal(node_id, _) | DefArg(node_id, _) | - DefBinding(node_id, _) => { - tcx.region_maps.var_region(node_id) - } - DefUpvar(_, subdef, closure_id, body_id) => { - match ty::ty_closure_store(fcx.node_ty(closure_id)) { - ty::RegionTraitStore(..) => region_of_def(fcx, *subdef), - ty::UniqTraitStore => ReScope(body_id) - } - } - _ => { - tcx.sess.bug(format!("unexpected def in region_of_def: {:?}", - def).as_slice()) - } - } -} - impl<'a> Rcx<'a> { pub fn tcx(&self) -> &'a ty::ctxt { self.fcx.ccx.tcx @@ -461,8 +434,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { visit::walk_expr(rcx, expr, ()); } - ast::ExprAssign(lhs, _) => { - adjust_borrow_kind_for_assignment_lhs(rcx, lhs); + ast::ExprAssign(..) => { visit::walk_expr(rcx, expr, ()); } @@ -471,8 +443,6 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { constrain_call(rcx, None, expr, Some(lhs), [rhs], true); } - adjust_borrow_kind_for_assignment_lhs(rcx, lhs); - visit::walk_expr(rcx, expr, ()); } @@ -617,9 +587,6 @@ fn check_expr_fn_block(rcx: &mut Rcx, // will be NULL at runtime and hence the closure // has static lifetime. } else { - // Closure must not outlive the variables it closes over. - constrain_free_variables(rcx, region, expr, freevars); - // Closure cannot outlive the appropriate temporary scope. let s = rcx.repeating_scope; rcx.fcx.mk_subr(true, infer::InfStackClosure(expr.span), @@ -633,114 +600,6 @@ fn check_expr_fn_block(rcx: &mut Rcx, let repeating_scope = rcx.set_repeating_scope(body.id); visit::walk_expr(rcx, expr, ()); rcx.set_repeating_scope(repeating_scope); - - match ty::get(function_type).sty { - ty::ty_closure(box ty::ClosureTy { - store: ty::RegionTraitStore(..), - .. - }) => { - freevars::with_freevars(tcx, expr.id, |freevars| { - propagate_upupvar_borrow_kind(rcx, expr, freevars); - }) - } - _ => () - } - - fn constrain_free_variables(rcx: &mut Rcx, - region: ty::Region, - expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { - /*! - * Make sure that all free variables referenced inside the closure - * outlive the closure itself. Also, create an entry in the - * upvar_borrows map with a region. - */ - - let tcx = rcx.fcx.ccx.tcx; - let infcx = rcx.fcx.infcx(); - debug!("constrain_free_variables({}, {})", - region.repr(tcx), expr.repr(tcx)); - for freevar in freevars.iter() { - debug!("freevar def is {:?}", freevar.def); - - // Identify the variable being closed over and its node-id. - let def = freevar.def; - let def_id = ast_util::def_id_of_def(def); - assert!(def_id.krate == ast::LOCAL_CRATE); - let upvar_id = ty::UpvarId { var_id: def_id.node, - closure_expr_id: expr.id }; - - // Create a region variable to represent this borrow. This borrow - // must outlive the region on the closure. - let origin = infer::UpvarRegion(upvar_id, expr.span); - let freevar_region = infcx.next_region_var(origin); - rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node), - region, freevar_region); - - // Create a UpvarBorrow entry. Note that we begin with a - // const borrow_kind, but change it to either mut or - // immutable as dictated by the uses. - let upvar_borrow = ty::UpvarBorrow { kind: ty::ImmBorrow, - region: freevar_region }; - rcx.fcx.inh.upvar_borrow_map.borrow_mut().insert(upvar_id, - upvar_borrow); - - // Guarantee that the closure does not outlive the variable itself. - let en_region = region_of_def(rcx.fcx, def); - debug!("en_region = {}", en_region.repr(tcx)); - rcx.fcx.mk_subr(true, infer::FreeVariable(freevar.span, def_id.node), - region, en_region); - } - } - - fn propagate_upupvar_borrow_kind(rcx: &mut Rcx, - expr: &ast::Expr, - freevars: &[freevars::freevar_entry]) { - let tcx = rcx.fcx.ccx.tcx; - debug!("propagate_upupvar_borrow_kind({})", expr.repr(tcx)); - for freevar in freevars.iter() { - // Because of the semi-hokey way that we are doing - // borrow_kind inference, we need to check for - // indirect dependencies, like so: - // - // let mut x = 0; - // outer_call(|| { - // inner_call(|| { - // x = 1; - // }); - // }); - // - // Here, the `inner_call` is basically "reborrowing" the - // outer pointer. With no other changes, `inner_call` - // would infer that it requires a mutable borrow, but - // `outer_call` would infer that a const borrow is - // sufficient. This is because we haven't linked the - // borrow_kind of the borrow that occurs in the inner - // closure to the borrow_kind of the borrow in the outer - // closure. Note that regions *are* naturally linked - // because we have a proper inference scheme there. - // - // Anyway, for borrow_kind, we basically go back over now - // after checking the inner closure (and hence - // determining the final borrow_kind) and propagate that as - // a constraint on the outer closure. - match freevar.def { - ast::DefUpvar(var_id, _, outer_closure_id, _) => { - // thing being captured is itself an upvar: - let outer_upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: outer_closure_id }; - let inner_upvar_id = ty::UpvarId { - var_id: var_id, - closure_expr_id: expr.id }; - link_upvar_borrow_kind_for_nested_closures(rcx, - inner_upvar_id, - outer_upvar_id); - } - _ => {} - } - } - } } fn constrain_callee(rcx: &mut Rcx, @@ -1209,57 +1068,14 @@ fn link_region(rcx: &Rcx, kind.repr(rcx.tcx()), cmt_borrowed.repr(rcx.tcx())); match cmt_borrowed.cat.clone() { - mc::cat_deref(base, _, mc::BorrowedPtr(_, r_borrowed)) => { - // References to an upvar `x` are translated to - // `*x`, since that is what happens in the - // underlying machine. We detect such references - // and treat them slightly differently, both to - // offer better error messages and because we need - // to infer the kind of borrow (mut, const, etc) - // to use for each upvar. - let cause = match base.cat { - mc::cat_upvar(ref upvar_id, _) => { - match rcx.fcx.inh.upvar_borrow_map.borrow_mut() - .find_mut(upvar_id) { - Some(upvar_borrow) => { - debug!("link_region: {} <= {}", - region_min.repr(rcx.tcx()), - upvar_borrow.region.repr(rcx.tcx())); - adjust_upvar_borrow_kind_for_loan( - *upvar_id, - upvar_borrow, - kind); - infer::ReborrowUpvar(span, *upvar_id) - } - None => { - rcx.tcx().sess.span_bug( - span, - format!("Illegal upvar id: {}", - upvar_id.repr( - rcx.tcx())).as_slice()); - } - } - } - - _ => { - infer::Reborrow(span) - } - }; + mc::cat_deref(_, _, mc::BorrowedPtr(_, r_borrowed)) => { + let cause = infer::Reborrow(span); debug!("link_region: {} <= {}", region_min.repr(rcx.tcx()), r_borrowed.repr(rcx.tcx())); rcx.fcx.mk_subr(true, cause, region_min, r_borrowed); - if kind != ty::ImmBorrow { - // If this is a mutable borrow, then the thing - // being borrowed will have to be unique. - // In user code, this means it must be an `&mut` - // borrow, but for an upvar, we might opt - // for an immutable-unique borrow. - adjust_upvar_borrow_kind_for_unique(rcx, base); - } - // Borrowing an `&mut` pointee for `region_min` is // only valid if the pointer resides in a unique // location which is itself valid for @@ -1289,7 +1105,6 @@ fn link_region(rcx: &Rcx, mc::cat_copied_upvar(..) | mc::cat_local(..) | mc::cat_arg(..) | - mc::cat_upvar(..) | mc::cat_rvalue(..) => { // These are all "base cases" with independent lifetimes // that are not subject to inference @@ -1299,183 +1114,3 @@ fn link_region(rcx: &Rcx, } } -fn adjust_borrow_kind_for_assignment_lhs(rcx: &Rcx, - lhs: &ast::Expr) { - /*! - * Adjusts the inferred borrow_kind as needed to account - * for upvars that are assigned to in an assignment - * expression. - */ - - let mc = mc::MemCategorizationContext::new(rcx); - let cmt = ignore_err!(mc.cat_expr(lhs)); - adjust_upvar_borrow_kind_for_mut(rcx, cmt); -} - -fn adjust_upvar_borrow_kind_for_mut(rcx: &Rcx, - cmt: mc::cmt) { - let mut cmt = cmt; - loop { - debug!("adjust_upvar_borrow_kind_for_mut(cmt={})", - cmt.repr(rcx.tcx())); - - match cmt.cat.clone() { - mc::cat_deref(base, _, mc::OwnedPtr) | - mc::cat_interior(base, _) | - mc::cat_downcast(base) | - mc::cat_discr(base, _) => { - // Interior or owned data is mutable if base is - // mutable, so iterate to the base. - cmt = base; - continue; - } - - mc::cat_deref(base, _, mc::BorrowedPtr(..)) => { - match base.cat { - mc::cat_upvar(ref upvar_id, _) => { - // if this is an implicit deref of an - // upvar, then we need to modify the - // borrow_kind of the upvar to make sure it - // is inferred to mutable if necessary - let mut upvar_borrow_map = - rcx.fcx.inh.upvar_borrow_map.borrow_mut(); - let ub = upvar_borrow_map.get_mut(upvar_id); - return adjust_upvar_borrow_kind(*upvar_id, ub, ty::MutBorrow); - } - - _ => {} - } - - // assignment to deref of an `&mut` - // borrowed pointer implies that the - // pointer itself must be unique, but not - // necessarily *mutable* - return adjust_upvar_borrow_kind_for_unique(rcx, base); - } - - mc::cat_deref(_, _, mc::UnsafePtr(..)) | - mc::cat_deref(_, _, mc::GcPtr) | - mc::cat_static_item | - mc::cat_rvalue(_) | - mc::cat_copied_upvar(_) | - mc::cat_local(_) | - mc::cat_arg(_) | - mc::cat_upvar(..) => { - return; - } - } - } -} - -fn adjust_upvar_borrow_kind_for_unique(rcx: &Rcx, cmt: mc::cmt) { - let mut cmt = cmt; - loop { - debug!("adjust_upvar_borrow_kind_for_unique(cmt={})", - cmt.repr(rcx.tcx())); - - match cmt.cat.clone() { - mc::cat_deref(base, _, mc::OwnedPtr) | - mc::cat_interior(base, _) | - mc::cat_downcast(base) | - mc::cat_discr(base, _) => { - // Interior or owned data is unique if base is - // unique. - cmt = base; - continue; - } - - mc::cat_deref(base, _, mc::BorrowedPtr(..)) => { - match base.cat { - mc::cat_upvar(ref upvar_id, _) => { - // if this is an implicit deref of an - // upvar, then we need to modify the - // borrow_kind of the upvar to make sure it - // is inferred to unique if necessary - let mut ub = rcx.fcx.inh.upvar_borrow_map.borrow_mut(); - let ub = ub.get_mut(upvar_id); - return adjust_upvar_borrow_kind(*upvar_id, ub, ty::UniqueImmBorrow); - } - - _ => {} - } - - // for a borrowed pointer to be unique, its - // base must be unique - return adjust_upvar_borrow_kind_for_unique(rcx, base); - } - - mc::cat_deref(_, _, mc::UnsafePtr(..)) | - mc::cat_deref(_, _, mc::GcPtr) | - mc::cat_static_item | - mc::cat_rvalue(_) | - mc::cat_copied_upvar(_) | - mc::cat_local(_) | - mc::cat_arg(_) | - mc::cat_upvar(..) => { - return; - } - } - } -} - -fn link_upvar_borrow_kind_for_nested_closures(rcx: &mut Rcx, - inner_upvar_id: ty::UpvarId, - outer_upvar_id: ty::UpvarId) { - /*! - * Indicates that the borrow_kind of `outer_upvar_id` must - * permit a reborrowing with the borrow_kind of `inner_upvar_id`. - * This occurs in nested closures, see comment above at the call to - * this function. - */ - - debug!("link_upvar_borrow_kind: inner_upvar_id={:?} outer_upvar_id={:?}", - inner_upvar_id, outer_upvar_id); - - let mut upvar_borrow_map = rcx.fcx.inh.upvar_borrow_map.borrow_mut(); - let inner_borrow = upvar_borrow_map.get_copy(&inner_upvar_id); - match upvar_borrow_map.find_mut(&outer_upvar_id) { - Some(outer_borrow) => { - adjust_upvar_borrow_kind(outer_upvar_id, outer_borrow, inner_borrow.kind); - } - None => { /* outer closure is not a stack closure */ } - } -} - -fn adjust_upvar_borrow_kind_for_loan(upvar_id: ty::UpvarId, - upvar_borrow: &mut ty::UpvarBorrow, - kind: ty::BorrowKind) { - debug!("adjust_upvar_borrow_kind_for_loan: upvar_id={:?} kind={:?} -> {:?}", - upvar_id, upvar_borrow.kind, kind); - - adjust_upvar_borrow_kind(upvar_id, upvar_borrow, kind) -} - -fn adjust_upvar_borrow_kind(upvar_id: ty::UpvarId, - upvar_borrow: &mut ty::UpvarBorrow, - kind: ty::BorrowKind) { - /*! - * We infer the borrow_kind with which to borrow upvars in a stack - * closure. The borrow_kind basically follows a lattice of - * `imm < unique-imm < mut`, moving from left to right as needed (but never - * right to left). Here the argument `mutbl` is the borrow_kind that - * is required by some particular use. - */ - - debug!("adjust_upvar_borrow_kind: id={:?} kind=({:?} -> {:?})", - upvar_id, upvar_borrow.kind, kind); - - match (upvar_borrow.kind, kind) { - // Take RHS: - (ty::ImmBorrow, ty::UniqueImmBorrow) | - (ty::ImmBorrow, ty::MutBorrow) | - (ty::UniqueImmBorrow, ty::MutBorrow) => { - upvar_borrow.kind = kind; - } - // Take LHS: - (ty::ImmBorrow, ty::ImmBorrow) | - (ty::UniqueImmBorrow, ty::ImmBorrow) | - (ty::UniqueImmBorrow, ty::UniqueImmBorrow) | - (ty::MutBorrow, _) => { - } - } -} diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index d9ec448c2c5cf..1d151ae70a469 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -23,17 +23,19 @@ use util::ppaux; pub fn replace_late_bound_regions_in_fn_sig( tcx: &ty::ctxt, fn_sig: &ty::FnSig, - mapf: |ty::BoundRegion| -> ty::Region) + mut mapf: |ty::BoundRegion| -> ty::Region) -> (HashMap, ty::FnSig) { debug!("replace_late_bound_regions_in_fn_sig({})", fn_sig.repr(tcx)); let mut map = HashMap::new(); let fn_sig = { + let mapf_ptr = &mut mapf; + let map_ptr = &mut map; let mut f = ty_fold::RegionFolder::regions(tcx, |r| { debug!("region r={}", r.to_str()); match r { ty::ReLateBound(s, br) if s == fn_sig.binder_id => { - *map.find_or_insert_with(br, |_| mapf(br)) + *map_ptr.find_or_insert_with(br, |_| (*mapf_ptr)(br)) } _ => r } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 5e67cb54ccc66..e2e26af136ce7 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -127,48 +127,51 @@ fn lookup_vtables_for_param(vcx: &VtableContext, // ty is the value supplied for the type parameter A... let mut param_result = Vec::new(); - ty::each_bound_trait_and_supertraits(tcx, - type_param_bounds.trait_bounds - .as_slice(), - |trait_ref| { - // ...and here trait_ref is each bound that was declared on A, - // expressed in terms of the type parameters. - - ty::populate_implementations_for_trait_if_necessary(tcx, - trait_ref.def_id); - - // Substitute the values of the type parameters that may - // appear in the bound. - let trait_ref = substs.as_ref().map_or(trait_ref.clone(), |substs| { - debug!("about to subst: {}, {}", - trait_ref.repr(tcx), substs.repr(tcx)); - trait_ref.subst(tcx, *substs) - }); - - debug!("after subst: {}", trait_ref.repr(tcx)); - - match lookup_vtable(vcx, span, ty, trait_ref.clone(), is_early) { - Some(vtable) => param_result.push(vtable), - None => { - vcx.tcx().sess.span_fatal(span, - format!("failed to find an implementation of \ - trait {} for {}", - vcx.infcx.trait_ref_to_str(&*trait_ref), - vcx.infcx.ty_to_str(ty)).as_slice()); + { + let param_result_ptr = &mut param_result; + ty::each_bound_trait_and_supertraits(tcx, + type_param_bounds.trait_bounds + .as_slice(), + |trait_ref| { + // ...and here trait_ref is each bound that was declared on A, + // expressed in terms of the type parameters. + + ty::populate_implementations_for_trait_if_necessary(tcx, + trait_ref.def_id); + + // Substitute the values of the type parameters that may + // appear in the bound. + let trait_ref = substs.as_ref().map_or(trait_ref.clone(), |substs| { + debug!("about to subst: {}, {}", + trait_ref.repr(tcx), substs.repr(tcx)); + trait_ref.subst(tcx, *substs) + }); + + debug!("after subst: {}", trait_ref.repr(tcx)); + + match lookup_vtable(vcx, span, ty, trait_ref.clone(), is_early) { + Some(vtable) => param_result_ptr.push(vtable), + None => { + vcx.tcx().sess.span_fatal(span, + format!("failed to find an implementation of \ + trait {} for {}", + vcx.infcx.trait_ref_to_str(&*trait_ref), + vcx.infcx.ty_to_str(ty)).as_slice()); + } } - } - true - }); + true + }); - debug!("lookup_vtables_for_param result(\ - span={:?}, \ - type_param_bounds={}, \ - ty={}, \ - result={})", - span, - type_param_bounds.repr(vcx.tcx()), - ty.repr(vcx.tcx()), - param_result.repr(vcx.tcx())); + debug!("lookup_vtables_for_param result(\ + span={:?}, \ + type_param_bounds={}, \ + ty={}, \ + result={})", + span, + type_param_bounds.repr(vcx.tcx()), + ty.repr(vcx.tcx()), + (*param_result_ptr).repr(vcx.tcx())); + } param_result } @@ -286,22 +289,29 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext, let mut n_bound = 0; let mut ret = None; - ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| { - debug!("checking bounds trait {}", - bound_trait_ref.repr(vcx.tcx())); - - if bound_trait_ref.def_id == trait_ref.def_id { - relate_trait_refs(vcx, span, bound_trait_ref, trait_ref.clone()); - let vtable = vtable_param(param, n_bound); - debug!("found param vtable: {:?}", - vtable); - ret = Some(vtable); - false - } else { - n_bound += 1; - true - } - }); + { + let n_bound_ptr = &mut n_bound; + let ret_ptr = &mut ret; + ty::each_bound_trait_and_supertraits(tcx, bounds, |bound_trait_ref| { + debug!("checking bounds trait {}", + bound_trait_ref.repr(vcx.tcx())); + + if bound_trait_ref.def_id == trait_ref.def_id { + relate_trait_refs(vcx, + span, + bound_trait_ref, + trait_ref.clone()); + let vtable = vtable_param(param, *n_bound_ptr); + debug!("found param vtable: {:?}", + vtable); + *ret_ptr = Some(vtable); + false + } else { + *n_bound_ptr += 1; + true + } + }); + } ret } diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 133fc9b1530ab..b400a44d98bd8 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -188,16 +188,30 @@ impl<'cx> WritebackCx<'cx> { return; } - for (upvar_id, upvar_borrow) in self.fcx.inh.upvar_borrow_map.borrow().iter() { - let r = upvar_borrow.region; - let r = self.resolve(&r, ResolvingUpvar(*upvar_id)); - let new_upvar_borrow = ty::UpvarBorrow { kind: upvar_borrow.kind, - region: r }; - debug!("Upvar borrow for {} resolved to {}", - upvar_id.repr(self.tcx()), - new_upvar_borrow.repr(self.tcx())); - self.fcx.tcx().upvar_borrow_map.borrow_mut().insert( - *upvar_id, new_upvar_borrow); + for (upvar_id, upvar_borrow) in self.fcx + .inh + .upvar_borrow_map + .borrow() + .iter() { + match ty::get(upvar_borrow.reborrowed_type).sty { + ty::ty_rptr(old_region, tm) => { + let new_region = self.resolve(&old_region, + ResolvingUpvar(*upvar_id)); + let new_upvar_borrow = ty::UpvarBorrow { + reborrowed_type: ty::mk_rptr(self.tcx(), + new_region, + tm), + }; + self.fcx + .tcx() + .upvar_borrow_map + .borrow_mut() + .insert(*upvar_id, new_upvar_borrow); + } + _ => { + self.tcx().sess.bug("reborrowed upvar wasn't an rptr"); + } + } } } diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 042bebf573f75..ade625b58288e 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -100,22 +100,23 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool { */ let mut found_nominal = false; + let found_nominal_ptr = &mut found_nominal; ty::walk_ty(original_type, |t| { match get(t).sty { ty_enum(def_id, _) | ty_struct(def_id, _) => { if def_id.krate == ast::LOCAL_CRATE { - found_nominal = true; + *found_nominal_ptr = true; } } ty_trait(box ty::TyTrait { def_id, ref store, .. }) => { if def_id.krate == ast::LOCAL_CRATE { - found_nominal = true; + *found_nominal_ptr = true; } if *store == ty::UniqTraitStore { match tcx.lang_items.owned_box() { Some(did) if did.krate == ast::LOCAL_CRATE => { - found_nominal = true; + *found_nominal_ptr = true; } _ => {} } @@ -124,7 +125,7 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool { ty_uniq(..) => { match tcx.lang_items.owned_box() { Some(did) if did.krate == ast::LOCAL_CRATE => { - found_nominal = true; + *found_nominal_ptr = true; } _ => {} } @@ -133,7 +134,7 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool { _ => { } } }); - return found_nominal; + return *found_nominal_ptr; } // Returns the def ID of the base type, if there is one. @@ -451,8 +452,9 @@ impl<'a> CoherenceChecker<'a> { }) } - fn iter_impls_of_trait(&self, trait_def_id: DefId, f: |DefId|) { - self.iter_impls_of_trait_local(trait_def_id, |x| f(x)); + fn iter_impls_of_trait(&self, trait_def_id: DefId, mut f: |DefId|) { + let f_ptr = &mut f; + self.iter_impls_of_trait_local(trait_def_id, |x| (*f_ptr)(x)); if trait_def_id.krate == LOCAL_CRATE { return; @@ -462,7 +464,7 @@ impl<'a> CoherenceChecker<'a> { csearch::each_implementation_for_trait(crate_store, trait_def_id, |impl_def_id| { // Is this actually necessary? let _ = lookup_item_type(self.crate_context.tcx, impl_def_id); - f(impl_def_id); + (*f_ptr)(impl_def_id); }); } @@ -657,12 +659,13 @@ impl<'a> CoherenceChecker<'a> { // info. fn add_external_crates(&self) { let mut impls_seen = HashSet::new(); + let impls_seen_ptr = &mut impls_seen; let crate_store = &self.crate_context.tcx.sess.cstore; crate_store.iter_crate_data(|crate_number, _crate_metadata| { each_impl(crate_store, crate_number, |def_id| { assert_eq!(crate_number, def_id.krate); - self.add_external_impl(&mut impls_seen, def_id) + self.add_external_impl(impls_seen_ptr, def_id) }) }) } diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 447f8dfa278d6..0a19867de35e7 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -425,10 +425,11 @@ pub fn ensure_supertraits(ccx: &CrateCtxt, // builtin trait, so that the trait's node id appears in the tcx trait_ref // map. This is only needed for metadata; see the similar fixme in encoder.rs. let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty); + let trait_ref_def_id = trait_ref.def_id; if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) { // FIXME(#5527) Could have same trait multiple times - if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref.def_id) { + if ty_trait_refs.iter().any(|other_trait| other_trait.def_id == trait_ref_def_id) { // This means a trait inherited from the same supertrait more // than once. tcx.sess.span_err(sp, "duplicate supertrait in trait declaration"); @@ -708,31 +709,38 @@ pub fn convert_struct(ccx: &CrateCtxt, // Write the type of each of the members and check for duplicate fields. let mut seen_fields: HashMap = HashMap::new(); - let field_tys = struct_def.fields.iter().map(|f| { - let result = convert_field(ccx, &tpt.generics, f, local_def(id)); - - if result.name != special_idents::unnamed_field.name { - let dup = match seen_fields.find(&result.name) { - Some(prev_span) => { - tcx.sess.span_err( - f.span, - format!("field `{}` is already declared", - token::get_name(result.name)).as_slice()); - tcx.sess.span_note(*prev_span, - "previously declared here"); - true - }, - None => false, - }; - // FIXME(#6393) this whole dup thing is just to satisfy - // the borrow checker :-( - if !dup { - seen_fields.insert(result.name, f.span); + let field_tys = { + let seen_fields_ptr = &mut seen_fields; + let tpt_ptr = &tpt; + struct_def.fields.iter().map(|f| { + let result = convert_field(ccx, + &tpt_ptr.generics, + f, + local_def(id)); + + if result.name != special_idents::unnamed_field.name { + let dup = match seen_fields_ptr.find(&result.name) { + Some(prev_span) => { + tcx.sess.span_err( + f.span, + format!("field `{}` is already declared", + token::get_name(result.name)).as_slice()); + tcx.sess.span_note(*prev_span, + "previously declared here"); + true + }, + None => false, + }; + // FIXME(#6393) this whole dup thing is just to satisfy + // the borrow checker :-( + if !dup { + seen_fields_ptr.insert(result.name, f.span); + } } - } - result - }).collect(); + result + }).collect() + }; tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys)); @@ -781,7 +789,8 @@ pub fn convert_struct(ccx: &CrateCtxt, // Enum-like. write_ty_to_tcx(tcx, ctor_id, selfty); - tcx.tcache.borrow_mut().insert(local_def(ctor_id), tpt); + tcx.tcache.borrow_mut().insert(local_def(ctor_id), + tpt.clone()); } else if struct_def.fields.get(0).node.kind.is_unnamed() { // Tuple-like. let inputs: Vec<_> = struct_def.fields.iter().map( @@ -1183,12 +1192,13 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt, let ty_generics_for_fn_or_method = ty_generics_for_fn_or_method(ccx, ast_generics, 0); let rb = BindingRscope::new(def_id.node); + let rb_ptr = &rb; let input_tys = decl.inputs .iter() - .map(|a| ty_of_arg(ccx, &rb, a, None)) + .map(|a| ty_of_arg(ccx, rb_ptr, a, None)) .collect(); - let output_ty = ast_ty_to_ty(ccx, &rb, decl.output); + let output_ty = ast_ty_to_ty(ccx, rb_ptr, decl.output); let t_fn = ty::mk_bare_fn( ccx.tcx, diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index 8ac6b19f657aa..5714bc431ccdc 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -317,8 +317,11 @@ pub fn expected_found( pub fn eq_tys(this: &C, a: ty::t, b: ty::t) -> ures { let suber = this.sub(); + let suber_ptr = &suber; this.infcx().try(|| { - suber.tys(a, b).and_then(|_ok| suber.contratys(a, b)).to_ures() + suber_ptr.tys(a, b) + .and_then(|_ok| suber_ptr.contratys(a, b)) + .to_ures() }) } @@ -328,9 +331,10 @@ pub fn eq_regions(this: &C, a: ty::Region, b: ty::Region) a.repr(this.infcx().tcx), b.repr(this.infcx().tcx)); let sub = this.sub(); + let sub_ptr = ⊂ indent(|| { this.infcx().try(|| { - sub.regions(a, b).and_then(|_r| sub.contraregions(a, b)) + sub_ptr.regions(a, b).and_then(|_r| sub_ptr.contraregions(a, b)) }).or_else(|e| { // substitute a better error, but use the regions // found in the original error diff --git a/src/librustc/middle/typeck/infer/error_reporting.rs b/src/librustc/middle/typeck/infer/error_reporting.rs index d7e70205f5d48..bf7b048136d7e 100644 --- a/src/librustc/middle/typeck/infer/error_reporting.rs +++ b/src/librustc/middle/typeck/infer/error_reporting.rs @@ -1167,14 +1167,15 @@ impl<'a> Rebuilder<'a> { let last_seg = path.segments.last().unwrap(); let mut new_lts = Vec::new(); + let indexes_ptr = &indexes; if last_seg.lifetimes.len() == 0 { // traverse once to see if there's a need to insert lifetime let need_insert = range(0, expected).any(|i| { - indexes.contains(&i) + indexes_ptr.contains(&i) }); if need_insert { for i in range(0, expected) { - if indexes.contains(&i) { + if indexes_ptr.contains(&i) { new_lts.push(lifetime); } else { new_lts.push(self.life_giver.give_lifetime()); @@ -1183,7 +1184,7 @@ impl<'a> Rebuilder<'a> { } } else { for (i, lt) in last_seg.lifetimes.iter().enumerate() { - if indexes.contains(&i) { + if indexes_ptr.contains(&i) { new_lts.push(lifetime); } else { new_lts.push(*lt); diff --git a/src/librustc/middle/typeck/infer/glb.rs b/src/librustc/middle/typeck/infer/glb.rs index 38b2cdcb52810..c69e6077df0fb 100644 --- a/src/librustc/middle/typeck/infer/glb.rs +++ b/src/librustc/middle/typeck/infer/glb.rs @@ -150,6 +150,7 @@ impl<'f> Combine for Glb<'f> { // Generalize the regions appearing in fn_ty0 if possible let new_vars = self.get_ref().infcx.region_vars.vars_created_since_snapshot(snapshot); + let sig0_binder_id = sig0.binder_id; let sig1 = fold_regions_in_sig( self.get_ref().infcx.tcx, @@ -158,7 +159,7 @@ impl<'f> Combine for Glb<'f> { generalize_region(self, snapshot, new_vars.as_slice(), - sig0.binder_id, + sig0_binder_id, &a_map, a_vars.as_slice(), b_vars.as_slice(), diff --git a/src/librustc/middle/typeck/infer/lattice.rs b/src/librustc/middle/typeck/infer/lattice.rs index 41a59dae74083..f113e015dacd5 100644 --- a/src/librustc/middle/typeck/infer/lattice.rs +++ b/src/librustc/middle/typeck/infer/lattice.rs @@ -508,9 +508,10 @@ pub fn lattice_var_and_t Combine for Lub<'f> { // Generalize the regions appearing in sig0 if possible let new_vars = self.get_ref().infcx.region_vars.vars_created_since_snapshot(snapshot); + let sig0_binder_id = sig0.binder_id; let sig1 = fold_regions_in_sig( self.get_ref().infcx.tcx, &sig0, - |r| generalize_region(self, snapshot, new_vars.as_slice(), - sig0.binder_id, &a_map, r)); + |r| { + generalize_region(self, + snapshot, + new_vars.as_slice(), + sig0_binder_id, + &a_map, + r) + }); return Ok(sig1); fn generalize_region(this: &Lub, diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 107c54115b42a..5dc9000e45790 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -302,7 +302,12 @@ pub fn common_supertype(cx: &InferCtxt, values: Types(expected_found(a_is_expected, a, b)) }; - let result = cx.commit(|| cx.lub(a_is_expected, trace.clone()).tys(a, b)); + let result = { + let trace_ptr = &trace; + cx.commit(|| { + cx.lub(a_is_expected, trace_ptr.clone()).tys(a, b) + }) + }; match result { Ok(t) => t, Err(ref err) => { @@ -382,14 +387,20 @@ pub fn mk_sub_trait_refs(cx: &InferCtxt, { debug!("mk_sub_trait_refs({} <: {})", a.inf_str(cx), b.inf_str(cx)); + let new_a = a.clone(); + let new_b = b.clone(); indent(|| { + let new_a = new_a.clone(); + let new_b = new_b.clone(); cx.commit(|| { let trace = TypeTrace { origin: origin, - values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone())) + values: TraitRefs(expected_found(a_is_expected, + new_a.clone(), + new_b.clone())) }; let suber = cx.sub(a_is_expected, trace); - suber.trait_refs(&*a, &*b) + suber.trait_refs(&*new_a, &*new_b) }) }).to_ures() } @@ -539,12 +550,14 @@ impl<'a> InferCtxt<'a> { } /// Execute `f` and commit the bindings if successful - pub fn commit(&self, f: || -> Result) -> Result { + pub fn commit(&self, mut f: || -> Result) -> Result { assert!(!self.in_snapshot()); debug!("commit()"); + + let f_ptr = &mut f; indent(|| { - let r = self.try(|| f()); + let r = self.try(|| (*f_ptr)()); self.ty_var_bindings.borrow_mut().bindings.truncate(0); self.int_var_bindings.borrow_mut().bindings.truncate(0); diff --git a/src/librustc/middle/typeck/infer/region_inference/mod.rs b/src/librustc/middle/typeck/infer/region_inference/mod.rs index 396dd476e8950..f94e3654a5a12 100644 --- a/src/librustc/middle/typeck/infer/region_inference/mod.rs +++ b/src/librustc/middle/typeck/infer/region_inference/mod.rs @@ -800,18 +800,19 @@ impl<'a> RegionVarBindings<'a> { }) } - fn expansion(&self, var_data: &mut [VarData]) { + fn expansion(&self, mut var_data: &mut [VarData]) { + let var_data = &mut var_data; self.iterate_until_fixed_point("Expansion", |constraint| { match *constraint { ConstrainRegSubVar(a_region, b_vid) => { - let b_data = &mut var_data[b_vid.to_uint()]; + let b_data = &mut (*var_data)[b_vid.to_uint()]; self.expand_node(a_region, b_vid, b_data) } ConstrainVarSubVar(a_vid, b_vid) => { - match var_data[a_vid.to_uint()].value { + match (*var_data)[a_vid.to_uint()].value { NoValue | ErrorValue => false, Value(a_region) => { - let b_node = &mut var_data[b_vid.to_uint()]; + let b_node = &mut (*var_data)[b_vid.to_uint()]; self.expand_node(a_region, b_vid, b_node) } } @@ -865,7 +866,8 @@ impl<'a> RegionVarBindings<'a> { } fn contraction(&self, - var_data: &mut [VarData]) { + mut var_data: &mut [VarData]) { + let var_data = &mut var_data; self.iterate_until_fixed_point("Contraction", |constraint| { match *constraint { ConstrainRegSubVar(..) => { @@ -873,16 +875,16 @@ impl<'a> RegionVarBindings<'a> { false } ConstrainVarSubVar(a_vid, b_vid) => { - match var_data[b_vid.to_uint()].value { + match (*var_data)[b_vid.to_uint()].value { NoValue | ErrorValue => false, Value(b_region) => { - let a_data = &mut var_data[a_vid.to_uint()]; + let a_data = &mut (*var_data)[a_vid.to_uint()]; self.contract_node(a_vid, a_data, b_region) } } } ConstrainVarSubReg(a_vid, b_region) => { - let a_data = &mut var_data[a_vid.to_uint()]; + let a_data = &mut (*var_data)[a_vid.to_uint()]; self.contract_node(a_vid, a_data, b_region) } ConstrainRegSubReg(..) => { @@ -966,9 +968,8 @@ impl<'a> RegionVarBindings<'a> { } fn collect_concrete_region_errors( - &self, - errors: &mut Vec) - { + &self, + errors: &mut Vec) { for (constraint, _) in self.constraints.borrow().iter() { let (sub, sup) = match *constraint { ConstrainVarSubVar(..) | diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index 995ce56078dba..d34fe5057a232 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -65,7 +65,7 @@ use driver::config; use middle::resolve; use middle::ty; -use util::common::time; +use util::common::Timer; use util::ppaux::Repr; use util::ppaux; use util::nodemap::{DefIdMap, FnvHashMap}; @@ -298,10 +298,18 @@ pub fn require_same_types(tcx: &ty::ctxt, let result = match maybe_infcx { None => { let infcx = infer::new_infer_ctxt(tcx); - infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2) + infer::mk_eqty(&infcx, + t1_is_expected, + infer::Misc(span), + t1, + t2) } Some(infcx) => { - infer::mk_eqty(infcx, t1_is_expected, infer::Misc(span), t1, t2) + infer::mk_eqty(infcx, + t1_is_expected, + infer::Misc(span), + t1, + t2) } }; @@ -444,21 +452,29 @@ pub fn check_crate(tcx: &ty::ctxt, tcx: tcx }; - time(time_passes, "type collecting", (), |_| - collect::collect_item_types(&ccx, krate)); + { + let _timer = Timer::new(time_passes, "type collecting"); + collect::collect_item_types(&ccx, krate); + } // this ensures that later parts of type checking can assume that items // have valid types and not error tcx.sess.abort_if_errors(); - time(time_passes, "variance inference", (), |_| - variance::infer_variance(tcx, krate)); + { + let _timer = Timer::new(time_passes, "variance inference"); + variance::infer_variance(tcx, krate); + } - time(time_passes, "coherence checking", (), |_| - coherence::check_coherence(&ccx, krate)); + { + let _timer = Timer::new(time_passes, "coherence checking"); + coherence::check_coherence(&ccx, krate); + } - time(time_passes, "type checking", (), |_| - check::check_item_types(&ccx, krate)); + { + let _timer = Timer::new(time_passes, "typechecking"); + check::check_item_types(&ccx, krate); + } check_for_entry_fn(&ccx); tcx.sess.abort_if_errors(); diff --git a/src/librustc/middle/typeck/rscope.rs b/src/librustc/middle/typeck/rscope.rs index 2abbd916d7627..595e5f3d27825 100644 --- a/src/librustc/middle/typeck/rscope.rs +++ b/src/librustc/middle/typeck/rscope.rs @@ -12,6 +12,7 @@ use middle::ty; use std::cell::Cell; +use std::kinds::marker::NoCopy; use syntax::ast; use syntax::codemap::Span; @@ -49,6 +50,7 @@ impl RegionScope for ExplicitRscope { pub struct BindingRscope { binder_id: ast::NodeId, anon_bindings: Cell, + noncopyable: NoCopy, } impl BindingRscope { @@ -56,6 +58,7 @@ impl BindingRscope { BindingRscope { binder_id: binder_id, anon_bindings: Cell::new(0), + noncopyable: NoCopy, } } } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index 19233f0a59fe5..49965580e25aa 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -76,14 +76,16 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { if !needs_check { return } let mut missing = HashSet::new(); + let missing_ptr = &mut missing; sess.cstore.iter_crate_data(|cnum, _| { for item in csearch::get_missing_lang_items(&sess.cstore, cnum).iter() { - missing.insert(*item); + missing_ptr.insert(*item); } }); $( - if missing.contains(&lang_items::$item) && items.$name().is_none() { + if missing_ptr.contains(&lang_items::$item) && + items.$name().is_none() { sess.err(format!("language item required, but not found: `{}`", stringify!($name)).as_slice()); diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 5ddae0c1bfef6..02de185014e7d 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -16,21 +16,40 @@ use syntax::visit::Visitor; use time; -pub fn time(do_it: bool, what: &str, u: U, f: |U| -> T) -> T { - local_data_key!(depth: uint); - if !do_it { return f(u); } +pub struct Timer { + start: f64, + what: &'static str, + enabled: bool, + old_depth: uint, +} - let old = depth.get().map(|d| *d).unwrap_or(0); - depth.replace(Some(old + 1)); +local_data_key!(depth: uint) - let start = time::precise_time_s(); - let rv = f(u); - let end = time::precise_time_s(); +impl Timer { + pub fn new(enabled: bool, what: &'static str) -> Timer { + let old_depth = depth.get().map(|d| *d).unwrap_or(0); + depth.replace(Some(old_depth + 1)); - println!("{}time: {:3.3f} s\t{}", " ".repeat(old), end - start, what); - depth.replace(Some(old)); + Timer { + start: if enabled { time::precise_time_s() } else { 0f64 }, + what: what, + enabled: enabled, + old_depth: old_depth, + } + } +} - rv +impl Drop for Timer { + fn drop(&mut self) { + depth.replace(Some(self.old_depth)); + if self.enabled { + let end = time::precise_time_s(); + println!("{}time: {:3.3f} s\t{}", + " ".repeat(self.old_depth), + end - self.start, + self.what); + } + } } pub fn indent(op: || -> R) -> R { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 7b8c62fbf88f1..1c1450b7e341e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -460,10 +460,11 @@ pub fn parameterized(cx: &ctxt, regions: regions.clone(), self_ty: None }; + let substs_ptr = &mut substs; ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| { - substs.tps.pop(); + substs_ptr.tps.pop(); match def.default { - Some(default) => ty::subst(cx, &substs, default) == actual, + Some(default) => ty::subst(cx, substs_ptr, default) == actual, None => false } }).len() @@ -1001,8 +1002,6 @@ impl Repr for ty::BorrowKind { impl Repr for ty::UpvarBorrow { fn repr(&self, tcx: &ctxt) -> String { - format_strbuf!("UpvarBorrow({}, {})", - self.kind.repr(tcx), - self.region.repr(tcx)) + format_strbuf!("UpvarBorrow({})", self.reborrowed_type.repr(tcx)) } } diff --git a/src/librustc/util/sha2.rs b/src/librustc/util/sha2.rs index f0d691823256d..98900b41e3ede 100644 --- a/src/librustc/util/sha2.rs +++ b/src/librustc/util/sha2.rs @@ -652,8 +652,9 @@ mod bench { pub fn sha256_10(b: &mut Bencher) { let mut sh = Sha256::new(); let bytes = [1u8, ..10]; + let sh_ptr = &mut sh; b.iter(|| { - sh.input(bytes); + sh_ptr.input(bytes); }); b.bytes = bytes.len() as u64; } @@ -662,8 +663,9 @@ mod bench { pub fn sha256_1k(b: &mut Bencher) { let mut sh = Sha256::new(); let bytes = [1u8, ..1024]; + let sh_ptr = &mut sh; b.iter(|| { - sh.input(bytes); + sh_ptr.input(bytes); }); b.bytes = bytes.len() as u64; } @@ -672,8 +674,9 @@ mod bench { pub fn sha256_64k(b: &mut Bencher) { let mut sh = Sha256::new(); let bytes = [1u8, ..65536]; + let sh_ptr = &mut sh; b.iter(|| { - sh.input(bytes); + sh_ptr.input(bytes); }); b.bytes = bytes.len() as u64; } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2f096346c9bef..1a64e3911d791 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -99,18 +99,21 @@ fn try_inline_def(cx: &core::DocContext, pub fn load_attrs(tcx: &ty::ctxt, did: ast::DefId) -> Vec { let mut attrs = Vec::new(); - csearch::get_item_attrs(&tcx.sess.cstore, did, |v| { - attrs.extend(v.move_iter().map(|mut a| { - // FIXME this isn't quite always true, it's just true about 99% of - // the time when dealing with documentation. For example, - // this would treat doc comments of the form `#[doc = "foo"]` - // incorrectly. - if a.name().get() == "doc" && a.value_str().is_some() { - a.node.is_sugared_doc = true; - } - a.clean() - })); - }); + { + let attrs_ptr = &mut attrs; + csearch::get_item_attrs(&tcx.sess.cstore, did, |v| { + attrs_ptr.extend(v.move_iter().map(|mut a| { + // FIXME this isn't quite always true, it's just true about + // 99% of the time when dealing with documentation. For + // example, this would treat doc comments of the form + // `#[doc = "foo"]` incorrectly. + if a.name().get() == "doc" && a.value_str().is_some() { + a.node.is_sugared_doc = true; + } + a.clean() + })); + }); + } attrs } @@ -259,18 +262,21 @@ fn build_module(cx: &core::DocContext, tcx: &ty::ctxt, // FIXME: this doesn't handle reexports inside the module itself. // Should they be handled? - csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| { - match def { - decoder::DlDef(def) => { - match try_inline_def(cx, tcx, def) { - Some(i) => items.extend(i.move_iter()), - None => {} + { + let items_ptr = &mut items; + csearch::each_child_of_item(&tcx.sess.cstore, did, |def, _, _| { + match def { + decoder::DlDef(def) => { + match try_inline_def(cx, tcx, def) { + Some(i) => items_ptr.extend(i.move_iter()), + None => {} + } } + decoder::DlImpl(did) => items_ptr.push(build_impl(tcx, did)), + decoder::DlField => fail!("unimplemented field"), } - decoder::DlImpl(did) => items.push(build_impl(tcx, did)), - decoder::DlField => fail!("unimplemented field"), - } - }); + }); + } clean::Module { items: items, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 48e390b35fb10..7a0952701b545 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -88,9 +88,12 @@ impl<'a> Clean for visit_ast::RustdocVisitor<'a> { let cx = super::ctxtkey.get().unwrap(); let mut externs = Vec::new(); - cx.sess().cstore.iter_crate_data(|n, meta| { - externs.push((n, meta.clean())); - }); + { + let externs_ptr = &mut externs; + cx.sess().cstore.iter_crate_data(|n, meta| { + externs_ptr.push((n, meta.clean())); + }); + } let input = driver::FileInput(cx.src.clone()); let t_outputs = driver::build_output_filenames(&input, @@ -740,6 +743,7 @@ impl<'a> Clean for (ast::DefId, &'a ty::FnSig) { if names.peek().map(|s| s.as_slice()) == Some("self") { let _ = names.next(); } + let names_ptr = &mut names; FnDecl { output: sig.output.clean(), cf: Return, @@ -749,7 +753,7 @@ impl<'a> Clean for (ast::DefId, &'a ty::FnSig) { Argument { type_: t.clean(), id: 0, - name: names.next().unwrap_or("".to_string()), + name: names_ptr.next().unwrap_or("".to_string()), } }).collect(), }, @@ -1532,39 +1536,48 @@ impl Clean> for ast::ViewItem { } }; let mut ret = Vec::new(); - match self.node { - ast::ViewItemUse(ref path) if !denied => { - match path.node { - ast::ViewPathGlob(..) => ret.push(convert(&self.node)), - ast::ViewPathList(ref a, ref list, ref b) => { - // Attempt to inline all reexported items, but be sure - // to keep any non-inlineable reexports so they can be - // listed in the documentation. - let remaining = list.iter().filter(|path| { - match inline::try_inline(path.node.id) { - Some(items) => { - ret.extend(items.move_iter()); false + { + let ret_ptr = &mut ret; + match self.node { + ast::ViewItemUse(ref path) if !denied => { + match path.node { + ast::ViewPathGlob(..) => { + ret_ptr.push(convert(&self.node)) + } + ast::ViewPathList(ref a, ref list, ref b) => { + // Attempt to inline all reexported items, but be sure + // to keep any non-inlineable reexports so they can be + // listed in the documentation. + let remaining = list.iter().filter(|path| { + match inline::try_inline(path.node.id) { + Some(items) => { + ret_ptr.extend(items.move_iter()); + false + } + None => true, } - None => true, + }).map(|a| a.clone()).collect::>(); + if remaining.len() > 0 { + let path = ast::ViewPathList(a.clone(), + remaining, + b.clone()); + let path = syntax::codemap::dummy_spanned(path); + ret_ptr.push(convert( + &ast::ViewItemUse(@path))); } - }).map(|a| a.clone()).collect::>(); - if remaining.len() > 0 { - let path = ast::ViewPathList(a.clone(), - remaining, - b.clone()); - let path = syntax::codemap::dummy_spanned(path); - ret.push(convert(&ast::ViewItemUse(@path))); } - } - ast::ViewPathSimple(_, _, id) => { - match inline::try_inline(id) { - Some(items) => ret.extend(items.move_iter()), - None => ret.push(convert(&self.node)), + ast::ViewPathSimple(_, _, id) => { + match inline::try_inline(id) { + Some(items) => { + ret_ptr.extend(items.move_iter()) + } + None => ret_ptr.push(convert(&self.node)), + } } } } + ref n => ret_ptr.push(convert(n)), } - ref n => ret.push(convert(n)), } return ret; } @@ -1808,7 +1821,10 @@ fn resolve_def(id: ast::NodeId) -> Option { let cx = super::ctxtkey.get().unwrap(); match cx.maybe_typed { core::Typed(ref tcx) => { - tcx.def_map.borrow().find(&id).map(|&def| register_def(&**cx, def)) + let cx_ptr = &**cx; + tcx.def_map + .borrow() + .find(&id).map(|&def| register_def(cx_ptr, def)) } core::NotTyped(_) => None } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d0974c25e9531..bdcc1ad01c2ee 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -651,11 +651,15 @@ impl<'a> SourceCollector<'a> { // Create the intermediate directories let mut cur = self.dst.clone(); let mut root_path = String::from_str("../../"); - clean_srcpath(p.dirname(), |component| { - cur.push(component); - mkdir(&cur).unwrap(); - root_path.push_str("../"); - }); + { + let cur_ptr = &mut cur; + let root_path_ptr = &mut root_path; + clean_srcpath(p.dirname(), |component| { + cur_ptr.push(component); + mkdir(cur_ptr).unwrap(); + root_path_ptr.push_str("../"); + }); + } cur.push(Vec::from_slice(p.filename().expect("source has no filename")) .append(bytes!(".html"))); @@ -952,10 +956,11 @@ impl Context { cache_key.replace(Some(Arc::new(cache))); let mut work = vec!((self, item)); + let work_ptr = &mut work; loop { - match work.pop() { + match work_ptr.pop() { Some((mut cx, item)) => try!(cx.item(item, |cx, item| { - work.push((cx.clone(), item)); + work_ptr.push((cx.clone(), item)); })), None => break, } @@ -1009,8 +1014,9 @@ impl Context { clean::ModuleItem(..) => { let name = item.name.get_ref().to_string(); let mut item = Some(item); + let item_ptr = &mut item; self.recurse(name, |this| { - let item = item.take_unwrap(); + let item = (*item_ptr).take_unwrap(); let dst = this.dst.join("index.html"); let dst = try!(File::create(&dst)); try!(render(dst, this, &item, false)); @@ -1021,7 +1027,7 @@ impl Context { }; this.sidebar = build_sidebar(&m); for item in m.items.move_iter() { - f(this,item); + f(this, item); } Ok(()) }) @@ -1062,9 +1068,13 @@ impl<'a> Item<'a> { // has anchors for the line numbers that we're linking to. if ast_util::is_local(self.item.def_id) { let mut path = Vec::new(); - clean_srcpath(self.item.source.filename.as_bytes(), |component| { - path.push(component.to_string()); - }); + { + let path_ptr = &mut path; + clean_srcpath(self.item.source.filename.as_bytes(), + |component| { + path_ptr.push(component.to_string()); + }); + } let href = if self.item.source.loline == self.item.source.hiline { format!("{}", self.item.source.loline) } else { diff --git a/src/librustdoc/html/toc.rs b/src/librustdoc/html/toc.rs index 212fe006aa1be..88d290dd8e538 100644 --- a/src/librustdoc/html/toc.rs +++ b/src/librustdoc/html/toc.rs @@ -104,7 +104,10 @@ impl TocBuilder { loop { match self.chain.pop() { Some(mut next) => { - this.map(|e| next.children.entries.push(e)); + { + let next_ptr = &mut next; + this.map(|e| next_ptr.children.entries.push(e)); + } if next.level < level { // this is the parent we want, so return it to // its rightful place. diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index efb0689404a5d..293ae957ca621 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -284,6 +284,8 @@ pub fn unindent(s: &str) -> String { let lines = s.lines_any().collect:: >(); let mut saw_first_line = false; let mut saw_second_line = false; + let saw_first_line_ptr = &mut saw_first_line; + let saw_second_line_ptr = &mut saw_second_line; let min_indent = lines.iter().fold(uint::MAX, |min_indent, line| { // After we see the first non-whitespace line, look at @@ -291,8 +293,8 @@ pub fn unindent(s: &str) -> String { // part of the first paragraph, then ignore the indentation // level of the first line let ignore_previous_indents = - saw_first_line && - !saw_second_line && + *saw_first_line_ptr && + !*saw_second_line_ptr && !line.is_whitespace(); let min_indent = if ignore_previous_indents { @@ -301,26 +303,27 @@ pub fn unindent(s: &str) -> String { min_indent }; - if saw_first_line { - saw_second_line = true; + if *saw_first_line_ptr { + *saw_second_line_ptr = true; } if line.is_whitespace() { min_indent } else { - saw_first_line = true; + *saw_first_line_ptr = true; let mut spaces = 0; + let spaces_ptr = &mut spaces; line.chars().all(|char| { // Only comparing against space because I wouldn't // know what to do with mixed whitespace chars if char == ' ' { - spaces += 1; + *spaces_ptr += 1; true } else { false } }); - cmp::min(min_indent, spaces) + cmp::min(min_indent, *spaces_ptr) } }); diff --git a/src/librustuv/addrinfo.rs b/src/librustuv/addrinfo.rs index 1e18f2ea9ec25..4d12df1706190 100644 --- a/src/librustuv/addrinfo.rs +++ b/src/librustuv/addrinfo.rs @@ -55,16 +55,17 @@ impl GetAddrInfoRequest { let hint = hints.map(|hint| { let mut flags = 0; + let flags_ref = &mut flags; each_ai_flag(|cval, aival| { if hint.flags & (aival as uint) != 0 { - flags |= cval as i32; + *flags_ref |= cval as i32; } }); let socktype = 0; let protocol = 0; libc::addrinfo { - ai_flags: flags, + ai_flags: *flags_ref, ai_family: hint.family as c_int, ai_socktype: socktype, ai_protocol: protocol, @@ -86,9 +87,12 @@ impl GetAddrInfoRequest { req.defuse(); // uv callback now owns this request let mut cx = Ctx { slot: None, status: 0, addrinfo: None }; - wait_until_woken_after(&mut cx.slot, loop_, || { - req.set_data(&cx); - }); + { + let cx_ref = &mut cx; + wait_until_woken_after(&mut cx_ref.slot, loop_, || { + req.set_data(cx_ref as *mut Ctx as *Ctx); + }); + } match cx.status { 0 => Ok(accum_addrinfo(cx.addrinfo.get_ref())), @@ -144,9 +148,10 @@ pub fn accum_addrinfo(addr: &Addrinfo) -> Vec { (*addr).ai_addrlen as uint); let mut flags = 0; + let flags_ref = &mut flags; each_ai_flag(|cval, aival| { if (*addr).ai_flags & cval != 0 { - flags |= aival as uint; + *flags_ref |= aival as uint; } }); @@ -171,7 +176,7 @@ pub fn accum_addrinfo(addr: &Addrinfo) -> Vec { family: (*addr).ai_family as uint, socktype: socktype, protocol: protocol, - flags: flags, + flags: *flags_ref, }); if (*addr).ai_next.is_not_null() { addr = (*addr).ai_next; diff --git a/src/librustuv/async.rs b/src/librustuv/async.rs index 7a16baaa9f2a6..156cadd10c8b2 100644 --- a/src/librustuv/async.rs +++ b/src/librustuv/async.rs @@ -109,13 +109,14 @@ impl RemoteCallback for AsyncWatcher { impl Drop for AsyncWatcher { fn drop(&mut self) { unsafe { + let self_handle = self.handle; self.exit_flag.with(|should_exit| { // NB: These two things need to happen atomically. Otherwise // the event handler could wake up due to a *previous* // signal and see the exit flag, destroying the handle // before the final send. *should_exit = true; - uvll::uv_async_send(self.handle) + uvll::uv_async_send(self_handle) }) } } diff --git a/src/librustuv/file.rs b/src/librustuv/file.rs index 12636a3c490ad..640e8022a1c11 100644 --- a/src/librustuv/file.rs +++ b/src/librustuv/file.rs @@ -106,12 +106,13 @@ impl FsRequest { } pub fn read(loop_: &Loop, fd: c_int, buf: &mut [u8], offset: i64) - -> Result - { + -> Result { + let buf_ptr = buf.as_ptr(); + let buf_len = buf.len(); execute(|req, cb| unsafe { let uvbuf = uvll::uv_buf_t { - base: buf.as_ptr(), - len: buf.len() as uvll::uv_buf_len_t, + base: buf_ptr, + len: buf_len as uvll::uv_buf_len_t, }; uvll::uv_fs_read(loop_.handle, req, fd, &uvbuf, 1, offset, cb) }).map(|req| { @@ -166,12 +167,15 @@ impl FsRequest { let mut paths = vec!(); let path = CString::new(path.with_ref(|p| p), false); let parent = Path::new(path); - let _ = c_str::from_c_multistring(req.get_ptr() as *libc::c_char, - Some(req.get_result() as uint), - |rel| { - let p = rel.as_bytes(); - paths.push(parent.join(p.slice_to(rel.len()))); - }); + let _ = { + let paths_ref = &mut paths; + c_str::from_c_multistring(req.get_ptr() as *libc::c_char, + Some(req.get_result() as uint), + |rel| { + let p = rel.as_bytes(); + paths_ref.push(parent.join(p.slice_to(rel.len()))); + }) + }; paths }) } @@ -327,10 +331,21 @@ fn execute(f: |*uvll::uv_fs_t, uvll::uv_fs_cb| -> c_int) 0 => { req.fired = true; let mut slot = None; - let loop_ = unsafe { uvll::get_loop_from_fs_req(req.req) }; - wait_until_woken_after(&mut slot, &Loop::wrap(loop_), || { - unsafe { uvll::set_data_for_req(req.req, &slot) } - }); + let loop_ = unsafe { + uvll::get_loop_from_fs_req(req.req) + }; + { + let req_ptr = &mut req; + let slot_ptr = &mut slot; + wait_until_woken_after(slot_ptr, &Loop::wrap(loop_), || { + unsafe { + uvll::set_data_for_req( + req_ptr.req, + slot_ptr as *mut Option + as *Option) + } + }); + } match req.get_result() { n if n < 0 => Err(UvError(n as i32)), _ => Ok(req), diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs index 20893b9e84c88..3fc2ece8ba104 100644 --- a/src/librustuv/lib.rs +++ b/src/librustuv/lib.rs @@ -180,8 +180,12 @@ pub trait UvHandle { uvll::uv_close(self.uv_handle() as *uvll::uv_handle_t, close_cb); uvll::set_data_for_uv_handle(self.uv_handle(), ptr::null::<()>()); - wait_until_woken_after(&mut slot, &self.uv_loop(), || { - uvll::set_data_for_uv_handle(self.uv_handle(), &slot); + let slot_ptr = &mut slot; + wait_until_woken_after(slot_ptr, &self.uv_loop(), || { + uvll::set_data_for_uv_handle( + self.uv_handle(), + slot_ptr as *mut Option + as *Option); }) } diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 2f35e48b8476b..7f94f9e4e45f3 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -560,9 +560,16 @@ impl rtio::RtioUdpSocket for UdpWatcher { result: None, }; let handle = self.handle; - wait_until_woken_after(&mut cx.task, &loop_, || { - unsafe { uvll::set_data_for_uv_handle(handle, &cx) } - }); + { + let cx_ptr = &mut cx; + wait_until_woken_after(&mut cx_ptr.task, &loop_, || { + unsafe { + uvll::set_data_for_uv_handle( + handle, + cx_ptr as *mut UdpRecvCtx as *UdpRecvCtx) + } + }); + } match cx.result.take_unwrap() { (n, _) if n < 0 => Err(uv_error_to_io_error(UvError(n as c_int))), @@ -635,9 +642,16 @@ impl rtio::RtioUdpSocket for UdpWatcher { let mut cx = UdpSendCtx { result: uvll::ECANCELED, data: data, udp: self as *mut _ }; - wait_until_woken_after(&mut self.blocked_sender, &loop_, || { - req.set_data(&cx); - }); + { + let cx_ptr = &mut cx; + let req_ptr = &mut req; + wait_until_woken_after(&mut self.blocked_sender, + &loop_, + || { + req_ptr.set_data(cx_ptr as *mut UdpSendCtx + as *UdpSendCtx); + }); + } if cx.result != uvll::ECANCELED { return match cx.result { @@ -819,13 +833,18 @@ pub fn shutdown(handle: *uvll::uv_stream_t, loop_: &Loop) -> Result<(), IoError> return match unsafe { uvll::uv_shutdown(req.handle, handle, shutdown_cb) } { 0 => { req.defuse(); // uv callback now owns this request - let mut cx = Ctx { slot: None, status: 0 }; + let mut cx = Ctx { + slot: None, + status: 0 + }; + + let cx_ptr = &mut cx; - wait_until_woken_after(&mut cx.slot, loop_, || { - req.set_data(&cx); + wait_until_woken_after(&mut cx_ptr.slot, loop_, || { + req.set_data(cx_ptr as *mut Ctx as *Ctx); }); - status_to_io_result(cx.status) + status_to_io_result(cx_ptr.status) } n => Err(uv_error_to_io_error(UvError(n))) }; diff --git a/src/librustuv/process.rs b/src/librustuv/process.rs index f6fcf3e48162f..5d0cd79ac227f 100644 --- a/src/librustuv/process.rs +++ b/src/librustuv/process.rs @@ -68,16 +68,24 @@ impl Process { } } + let cfg_env = &cfg.env; + let cfg_uid = &cfg.uid; + let cfg_gid = &cfg.gid; + let cfg_detach = cfg.detach; + let cfg_cwd = &cfg.cwd; + let stdio_ptr = stdio.as_ptr(); + let stdio_len = stdio.len(); + let ret = with_argv(cfg.program, cfg.args, |argv| { - with_env(cfg.env, |envp| { + with_env(*cfg_env, |envp| { let mut flags = 0; - if cfg.uid.is_some() { + if cfg_uid.is_some() { flags |= uvll::PROCESS_SETUID; } - if cfg.gid.is_some() { + if cfg_gid.is_some() { flags |= uvll::PROCESS_SETGID; } - if cfg.detach { + if cfg_detach { flags |= uvll::PROCESS_DETACHED; } let options = uvll::uv_process_options_t { @@ -85,15 +93,15 @@ impl Process { file: unsafe { *argv }, args: argv, env: envp, - cwd: match cfg.cwd { - Some(cwd) => cwd.with_ref(|p| p), + cwd: match *cfg_cwd { + Some(ref cwd) => cwd.with_ref(|p| p), None => ptr::null(), }, flags: flags as libc::c_uint, - stdio_count: stdio.len() as libc::c_int, - stdio: stdio.as_ptr(), - uid: cfg.uid.unwrap_or(0) as uvll::uv_uid_t, - gid: cfg.gid.unwrap_or(0) as uvll::uv_gid_t, + stdio_count: stdio_len as libc::c_int, + stdio: stdio_ptr, + uid: cfg_uid.unwrap_or(0) as uvll::uv_uid_t, + gid: cfg_gid.unwrap_or(0) as uvll::uv_gid_t, }; let handle = UvHandle::alloc(None::, uvll::UV_PROCESS); diff --git a/src/librustuv/stream.rs b/src/librustuv/stream.rs index 8ce985eb76d65..9630a26169669 100644 --- a/src/librustuv/stream.rs +++ b/src/librustuv/stream.rs @@ -177,11 +177,17 @@ impl StreamWatcher { }; req.defuse(); // uv callback now owns this request - let loop_ = unsafe { uvll::get_loop_for_uv_handle(self.handle) }; - wait_until_woken_after(&mut self.blocked_writer, - &Loop::wrap(loop_), || { - req.set_data(&wcx); - }); + let loop_ = unsafe { + uvll::get_loop_for_uv_handle(self.handle) + }; + { + let wcx_ptr = &wcx; + let req_ptr = &mut req; + wait_until_woken_after(&mut self.blocked_writer, + &Loop::wrap(loop_), || { + req_ptr.set_data(wcx_ptr); + }); + } if wcx.result != uvll::ECANCELED { self.last_write_req = Some(Request::wrap(req.handle)); diff --git a/src/librustuv/timeout.rs b/src/librustuv/timeout.rs index a67b2b481e4ca..02fb2f93057d2 100644 --- a/src/librustuv/timeout.rs +++ b/src/librustuv/timeout.rs @@ -239,14 +239,22 @@ impl ConnectCtx { } None => {} } - wait_until_woken_after(&mut self.task, &io.loop_, || { - let data = &self as *_; - match self.timer { - Some(ref mut timer) => unsafe { timer.set_data(data) }, - None => {} - } - req.set_data(data); - }); + { + let req_ptr = &mut req; + let this = &mut self; + wait_until_woken_after(&mut this.task, &io.loop_, || { + let data = this as *mut ConnectCtx as *ConnectCtx; + match this.timer { + Some(ref mut timer) => { + unsafe { + timer.set_data(data) + } + } + None => {} + } + req_ptr.set_data(data); + }); + } // Make sure an erroneously fired callback doesn't have access // to the context any more. req.set_data(0 as *int); diff --git a/src/libserialize/base64.rs b/src/libserialize/base64.rs index 5d2f229beb675..0800907eba52e 100644 --- a/src/libserialize/base64.rs +++ b/src/libserialize/base64.rs @@ -365,9 +365,12 @@ mod tests { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; let sb = s.as_bytes().to_base64(STANDARD); - b.iter(|| { - sb.as_slice().from_base64().unwrap(); - }); + { + let sb_ptr = &sb; + b.iter(|| { + sb_ptr.as_slice().from_base64().unwrap(); + }); + } b.bytes = sb.len() as u64; } diff --git a/src/libserialize/ebml.rs b/src/libserialize/ebml.rs index a127c11f50932..d71e44d761562 100644 --- a/src/libserialize/ebml.rs +++ b/src/libserialize/ebml.rs @@ -573,14 +573,17 @@ pub mod reader { self.read_tuple_arg(idx, f) } - fn read_option(&mut self, - f: |&mut Decoder<'doc>, bool| -> DecodeResult) -> DecodeResult { + fn read_option( + &mut self, + mut f: |&mut Decoder<'doc>, bool| -> DecodeResult) + -> DecodeResult { debug!("read_option()"); + let f_ptr = &mut f; self.read_enum("Option", |this| { this.read_enum_variant(["None", "Some"], |this, idx| { match idx { - 0 => f(this, false), - 1 => f(this, true), + 0 => (*f_ptr)(this, false), + 1 => (*f_ptr)(this, true), _ => { Err(Expected(format_strbuf!("Expected None or \ Some"))) @@ -1120,13 +1123,17 @@ mod bench { } }); let mut sum = 0u; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += reader::vuint_at(data.as_slice(), i).unwrap().val; - i += 4; - } - }); + { + let sum_ptr = &mut sum; + b.iter(|| { + let mut i = 0; + while i < data.len() { + *sum_ptr += reader::vuint_at(data.as_slice(), i).unwrap() + .val; + i += 4; + } + }); + } } #[bench] @@ -1138,13 +1145,17 @@ mod bench { } }); let mut sum = 0u; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += reader::vuint_at(data.as_slice(), i).unwrap().val; - i += 4; - } - }); + { + let sum_ptr = &mut sum; + b.iter(|| { + let mut i = 1; + while i < data.len() { + *sum_ptr += reader::vuint_at(data.as_slice(), i).unwrap() + .val; + i += 4; + } + }); + } } #[bench] @@ -1157,13 +1168,17 @@ mod bench { } }); let mut sum = 0u; - b.iter(|| { - let mut i = 0; - while i < data.len() { - sum += reader::vuint_at(data.as_slice(), i).unwrap().val; - i += 4; - } - }); + { + let sum_ptr = &mut sum; + b.iter(|| { + let mut i = 0; + while i < data.len() { + *sum_ptr += reader::vuint_at(data.as_slice(), i).unwrap() + .val; + i += 4; + } + }); + } } #[bench] @@ -1176,12 +1191,16 @@ mod bench { } }); let mut sum = 0u; - b.iter(|| { - let mut i = 1; - while i < data.len() { - sum += reader::vuint_at(data.as_slice(), i).unwrap().val; - i += 4; - } - }); + { + let sum_ptr = &mut sum; + b.iter(|| { + let mut i = 1; + while i < data.len() { + *sum_ptr += reader::vuint_at(data.as_slice(), i).unwrap() + .val; + i += 4; + } + }); + } } } diff --git a/src/libserialize/hex.rs b/src/libserialize/hex.rs index 373bff8b0cc61..dec291a5d5134 100644 --- a/src/libserialize/hex.rs +++ b/src/libserialize/hex.rs @@ -210,9 +210,12 @@ mod tests { let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \ ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン"; let sb = s.as_bytes().to_hex(); - b.iter(|| { - sb.as_slice().from_hex().unwrap(); - }); + { + let sb_ptr = &sb; + b.iter(|| { + sb_ptr.as_slice().from_hex().unwrap(); + }); + } b.bytes = sb.len() as u64; } } diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 08ac66959bc3c..8316dcc36b10e 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1941,12 +1941,11 @@ impl ::Decoder for Decoder { format_strbuf!("{}", json))) } }; + let name_slice = name.as_slice(); let idx = match names.iter() - .position(|n| { - str::eq_slice(*n, name.as_slice()) - }) { + .position(|n| str::eq_slice(*n, name_slice)) { Some(idx) => idx, - None => return Err(UnknownVariantError(name)) + None => return Err(UnknownVariantError(name.to_string())) }; f(self, idx) } @@ -2470,33 +2469,35 @@ mod tests { #[test] fn test_write_enum() { let animal = Dog; + let animal_ptr = &animal; assert_eq!( with_str_writer(|wr| { let mut encoder = Encoder::new(wr); - animal.encode(&mut encoder).unwrap(); + animal_ptr.encode(&mut encoder).unwrap(); }), "\"Dog\"".to_string() ); assert_eq!( with_str_writer(|wr| { let mut encoder = PrettyEncoder::new(wr); - animal.encode(&mut encoder).unwrap(); + animal_ptr.encode(&mut encoder).unwrap(); }), "\"Dog\"".to_string() ); let animal = Frog("Henry".to_string(), 349); + let animal_ptr = &animal; assert_eq!( with_str_writer(|wr| { let mut encoder = Encoder::new(wr); - animal.encode(&mut encoder).unwrap(); + animal_ptr.encode(&mut encoder).unwrap(); }), "{\"variant\":\"Frog\",\"fields\":[\"Henry\",349]}".to_string() ); assert_eq!( with_str_writer(|wr| { let mut encoder = PrettyEncoder::new(wr); - animal.encode(&mut encoder).unwrap(); + animal_ptr.encode(&mut encoder).unwrap(); }), "\ [\n \ @@ -2510,16 +2511,18 @@ mod tests { #[test] fn test_write_some() { let value = Some("jodhpurs".to_string()); + let value_ptr = &value; let s = with_str_writer(|wr| { let mut encoder = Encoder::new(wr); - value.encode(&mut encoder).unwrap(); + value_ptr.encode(&mut encoder).unwrap(); }); assert_eq!(s, "\"jodhpurs\"".to_string()); let value = Some("jodhpurs".to_string()); + let value_ptr = &value; let s = with_str_writer(|wr| { let mut encoder = PrettyEncoder::new(wr); - value.encode(&mut encoder).unwrap(); + value_ptr.encode(&mut encoder).unwrap(); }); assert_eq!(s, "\"jodhpurs\"".to_string()); } @@ -2527,11 +2530,14 @@ mod tests { #[test] fn test_write_none() { let value: Option = None; - let s = with_str_writer(|wr| { - let mut encoder = Encoder::new(wr); - value.encode(&mut encoder).unwrap(); - }); - assert_eq!(s, "null".to_string()); + { + let value_ptr = &value; + let s = with_str_writer(|wr| { + let mut encoder = Encoder::new(wr); + value_ptr.encode(&mut encoder).unwrap(); + }); + assert_eq!(s, "null".to_string()); + } let s = with_str_writer(|wr| { let mut encoder = Encoder::new(wr); diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 9252ac55d24e5..db9cbb0ce67dd 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -573,11 +573,16 @@ pub trait EncoderHelpers { } impl> EncoderHelpers for S { - fn emit_from_vec(&mut self, v: &[T], f: |&mut S, &T| -> Result<(), E>) -> Result<(), E> { + fn emit_from_vec( + &mut self, + v: &[T], + mut f: |&mut S, &T| -> Result<(), E>) + -> Result<(), E> { + let f_ptr = &mut f; self.emit_seq(v.len(), |this| { for (i, e) in v.iter().enumerate() { try!(this.emit_seq_elt(i, |this| { - f(this, e) + (*f_ptr)(this, e) })); } Ok(()) @@ -590,11 +595,12 @@ pub trait DecoderHelpers { } impl> DecoderHelpers for D { - fn read_to_vec(&mut self, f: |&mut D| -> Result) -> Result, E> { + fn read_to_vec(&mut self, mut f: |&mut D| -> Result) -> Result, E> { + let f_ptr = &mut f; self.read_seq(|this, len| { let mut v = Vec::with_capacity(len); for i in range(0, len) { - v.push(try!(this.read_seq_elt(i, |this| f(this)))); + v.push(try!(this.read_seq_elt(i, |this| (*f_ptr)(this)))); } Ok(v) }) diff --git a/src/libstd/c_str.rs b/src/libstd/c_str.rs index 983d76a08442b..3e9be0de7c2b6 100644 --- a/src/libstd/c_str.rs +++ b/src/libstd/c_str.rs @@ -467,12 +467,13 @@ mod tests { let ptr = input.as_ptr(); let expected = ["zero", "one"]; let mut it = expected.iter(); + let it_ptr = &mut it; let result = from_c_multistring(ptr as *libc::c_char, None, |c| { let cbytes = c.as_bytes_no_nul(); - assert_eq!(cbytes, it.next().unwrap().as_bytes()); + assert_eq!(cbytes, it_ptr.next().unwrap().as_bytes()); }); assert_eq!(result, 2); - assert!(it.next().is_none()); + assert!(it_ptr.next().is_none()); } } @@ -679,12 +680,15 @@ mod tests { } let mut c_: Option = None; - foo(|c| { - c_ = Some(c.clone()); - c.clone(); - // force a copy, reading the memory - c.as_bytes().to_owned(); - }); + { + let c_ptr = &mut c_; + foo(|c| { + *c_ptr = Some(c.clone()); + c.clone(); + // force a copy, reading the memory + c.as_bytes().to_owned(); + }); + } let c_ = c_.unwrap(); // force a copy, reading the memory c_.as_bytes().to_owned(); diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs index 2e51931f15a13..9274c803d734e 100644 --- a/src/libstd/cleanup.rs +++ b/src/libstd/cleanup.rs @@ -66,11 +66,14 @@ pub unsafe fn annihilate() { // // In this pass, nothing gets freed, so it does not matter whether // we read the next field before or after the callback. - each_live_alloc(true, |alloc| { - n_total_boxes += 1; - (*alloc).ref_count = RC_IMMORTAL; - true - }); + { + let n_total_boxes_ptr = &mut n_total_boxes; + each_live_alloc(true, |alloc| { + *n_total_boxes_ptr += 1; + (*alloc).ref_count = RC_IMMORTAL; + true + }); + } // Pass 2: Drop all boxes. // diff --git a/src/libstd/comm/select.rs b/src/libstd/comm/select.rs index ed884647fb6ff..42f2a5ec0f105 100644 --- a/src/libstd/comm/select.rs +++ b/src/libstd/comm/select.rs @@ -178,18 +178,23 @@ impl Select { // sequentially until one fails. If one fails, then abort // immediately so we can go unblock on all the other receivers. let task: Box = Local::take(); - task.deschedule(amt, |task| { - // Prepare for the block - let (i, handle) = iter.next().unwrap(); - match (*handle).packet.start_selection(task) { - Ok(()) => Ok(()), - Err(task) => { - ready_index = i; - ready_id = (*handle).id; - Err(task) + { + let iter_ptr = &mut iter; + let ready_index_ptr = &mut ready_index; + let ready_id_ptr = &mut ready_id; + task.deschedule(amt, |task| { + // Prepare for the block + let (i, handle) = iter_ptr.next().unwrap(); + match (*handle).packet.start_selection(task) { + Ok(()) => Ok(()), + Err(task) => { + *ready_index_ptr = i; + *ready_id_ptr = (*handle).id; + Err(task) + } } - } - }); + }); + } // Abort the selection process on each receiver. If the abort // process returns `true`, then that means that the receiver is diff --git a/src/libstd/comm/sync.rs b/src/libstd/comm/sync.rs index 819e885526cbf..3bc4d24202b5e 100644 --- a/src/libstd/comm/sync.rs +++ b/src/libstd/comm/sync.rs @@ -450,20 +450,25 @@ impl Queue { task: None, next: 0 as *mut Node, }; - task.deschedule(1, |task| { - node.task = Some(task); - if self.tail.is_null() { - self.head = &mut node as *mut Node; - self.tail = &mut node as *mut Node; - } else { - unsafe { - (*self.tail).next = &mut node as *mut Node; - self.tail = &mut node as *mut Node; + + { + let node_ptr = &mut node; + task.deschedule(1, |task| { + node_ptr.task = Some(task); + if self.tail.is_null() { + self.head = node_ptr as *mut Node; + self.tail = node_ptr as *mut Node; + } else { + unsafe { + (*self.tail).next = node_ptr as *mut Node; + self.tail = node_ptr as *mut Node; + } } - } - unsafe { lock.unlock_noguard(); } - Ok(()) - }); + unsafe { lock.unlock_noguard(); } + Ok(()) + }); + } + unsafe { lock.lock_noguard(); } assert!(node.next.is_null()); } diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs index 29afd2b1d9b2b..d931ee15a481b 100644 --- a/src/libstd/io/extensions.rs +++ b/src/libstd/io/extensions.rs @@ -515,10 +515,11 @@ mod bench { let data = Vec::from_fn($stride*100+$start_index, |i| i as u8); let mut sum = 0u64; + let sum_ptr = &mut sum; b.iter(|| { let mut i = $start_index; while i < data.len() { - sum += u64_from_be_bytes(data.as_slice(), i, $size); + *sum_ptr += u64_from_be_bytes(data.as_slice(), i, $size); i += $stride; } }); diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs index d3e250be9a323..0c0b3fd0ac20c 100644 --- a/src/libstd/io/fs.rs +++ b/src/libstd/io/fs.rs @@ -463,14 +463,15 @@ pub fn rmdir(path: &Path) -> IoResult<()> { /// use std::io::fs; /// /// // one possible implementation of fs::walk_dir only visiting files -/// fn visit_dirs(dir: &Path, cb: |&Path|) -> io::IoResult<()> { +/// fn visit_dirs(dir: &Path, mut cb: |&Path|) -> io::IoResult<()> { +/// let cb_ptr = &mut cb; /// if dir.is_dir() { /// let contents = try!(fs::readdir(dir)); /// for entry in contents.iter() { /// if entry.is_dir() { -/// try!(visit_dirs(entry, |p| cb(p))); +/// try!(visit_dirs(entry, |p| (*cb_ptr)(p))); /// } else { -/// cb(entry); +/// (*cb_ptr)(entry); /// } /// } /// Ok(()) diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs index 879c66e0769d8..6920ff74bbd09 100644 --- a/src/libstd/io/net/addrinfo.rs +++ b/src/libstd/io/net/addrinfo.rs @@ -91,7 +91,11 @@ pub fn get_host_addresses(host: &str) -> IoResult> { /// consumption just yet. fn lookup(hostname: Option<&str>, servname: Option<&str>, hint: Option) -> IoResult> { - LocalIo::maybe_raise(|io| io.get_host_addresses(hostname, servname, hint)) + LocalIo::maybe_raise(|io| { + unsafe { + io.get_host_addresses(::mem::transmute(hostname), servname, hint) + } + }) } // Ignored on android since we cannot give tcp/ip diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs index 875dd01be823b..f8436b40b6280 100644 --- a/src/libstd/io/net/udp.rs +++ b/src/libstd/io/net/udp.rs @@ -206,11 +206,13 @@ impl UdpStream { } impl Reader for UdpStream { - fn read(&mut self, buf: &mut [u8]) -> IoResult { - let peer = self.connected_to; + fn read(&mut self, mut buf: &mut [u8]) -> IoResult { + let mut peer = self.connected_to; + let peer = &mut peer; + let buf_ptr = &mut buf; self.as_socket(|sock| { - match sock.recvfrom(buf) { - Ok((_nread, src)) if src != peer => Ok(0), + match sock.recvfrom(*buf_ptr) { + Ok((_nread, src)) if src != *peer => Ok(0), Ok((nread, _src)) => Ok(nread), Err(e) => Err(e), } diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 05d5f19eeffad..d79d249a39e2b 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -209,9 +209,10 @@ impl TeeReader { } impl Reader for TeeReader { - fn read(&mut self, buf: &mut [u8]) -> io::IoResult { - self.reader.read(buf).and_then(|len| { - self.writer.write(buf.slice_to(len)).map(|()| len) + fn read(&mut self, mut buf: &mut [u8]) -> io::IoResult { + let buf_ptr = &mut buf; + self.reader.read(*buf_ptr).and_then(|len| { + self.writer.write(buf_ptr.slice_to(len)).map(|()| len) }) } } diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index 1efe83217f48d..8542876c01450 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -480,7 +480,8 @@ pub fn float_to_str_bytes_common unreachable!() } as u8); - int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c)); + let bufptr = &mut buf; + int_to_str_bytes_common(exp, 10, sign, |c| bufptr.push(c)); } } @@ -825,31 +826,36 @@ mod bench { #[bench] fn to_str_bin(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(2); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(2); }) } #[bench] fn to_str_oct(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(8); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(8); }) } #[bench] fn to_str_dec(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(10); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(10); }) } #[bench] fn to_str_hex(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(16); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(16); }) } #[bench] fn to_str_base_36(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(36); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(36); }) } } @@ -861,31 +867,36 @@ mod bench { #[bench] fn to_str_bin(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(2); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(2); }) } #[bench] fn to_str_oct(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(8); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(8); }) } #[bench] fn to_str_dec(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(10); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(10); }) } #[bench] fn to_str_hex(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(16); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(16); }) } #[bench] fn to_str_base_36(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { rng.gen::().to_str_radix(36); }) + let rng_ptr = &mut rng; + b.iter(|| { rng_ptr.gen::().to_str_radix(36); }) } } @@ -897,7 +908,8 @@ mod bench { #[bench] fn float_to_str(b: &mut Bencher) { let mut rng = XorShiftRng::new().unwrap(); - b.iter(|| { f64::to_str(rng.gen()); }) + let rng_ptr = &mut rng; + b.iter(|| { f64::to_str(rng_ptr.gen()); }) } } } diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 7d3758d621d32..10c064f6be14e 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -241,11 +241,14 @@ pub fn env_as_bytes() -> Vec<(Vec,Vec)> { os::last_os_error()); } let mut result = Vec::new(); - ptr::array_each(environ, |e| { - let env_pair = - Vec::from_slice(CString::new(e, false).as_bytes_no_nul()); - result.push(env_pair); - }); + { + let result_ptr = &mut result; + ptr::array_each(environ, |e| { + let env_pair = Vec::from_slice( + CString::new(e, false).as_bytes_no_nul()); + result_ptr.push(env_pair); + }); + } result } diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index c0c7a042f11c9..e3ce756db9f2b 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -1287,32 +1287,36 @@ mod bench { #[bench] fn push_home_dir(b: &mut Bencher) { let mut posix_path = Path::new("/"); + let posix_path_ptr = &mut posix_path; b.iter(|| { - posix_path.push("home"); + posix_path_ptr.push("home"); }); } #[bench] fn push_abs_path_home_dir(b: &mut Bencher) { let mut posix_path = Path::new("/"); + let posix_path_ptr = &mut posix_path; b.iter(|| { - posix_path.push("/home"); + posix_path_ptr.push("/home"); }); } #[bench] fn push_many_home_dir(b: &mut Bencher) { let mut posix_path = Path::new("/"); + let posix_path_ptr = &mut posix_path; b.iter(|| { - posix_path.push_many(&["home"]); + posix_path_ptr.push_many(&["home"]); }); } #[bench] fn push_many_abs_path_home_dir(b: &mut Bencher) { let mut posix_path = Path::new("/"); + let posix_path_ptr = &mut posix_path; b.iter(|| { - posix_path.push_many(&["/home"]); + posix_path_ptr.push_many(&["/home"]); }); } diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 1fc2fa1d221dc..d66d64f34645a 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -1022,14 +1022,15 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option { } return None; - fn parse_two_comps<'a>(mut path: &'a str, f: |char| -> bool) + fn parse_two_comps<'a>(mut path: &'a str, mut f: |char| -> bool) -> Option<(uint, uint)> { - let idx_a = match path.find(|x| f(x)) { + let f_ptr = &mut f; + let idx_a = match path.find(|x| (*f_ptr)(x)) { None => return None, Some(x) => x }; path = path.slice_from(idx_a+1); - let idx_b = path.find(f).unwrap_or(path.len()); + let idx_b = path.find(|x| (*f_ptr)(x)).unwrap_or(path.len()); Some((idx_a, idx_b)) } } diff --git a/src/libstd/rt/at_exit_imp.rs b/src/libstd/rt/at_exit_imp.rs index c892a73d93484..f3fa67d087392 100644 --- a/src/libstd/rt/at_exit_imp.rs +++ b/src/libstd/rt/at_exit_imp.rs @@ -47,8 +47,9 @@ pub fn push(f: proc():Send) { rtassert!(!QUEUE.is_null()); let state: &mut Queue = mem::transmute(QUEUE); let mut f = Some(f); - state.with(|arr| { - arr.push(f.take_unwrap()); + let f_ref = &mut f; + state.with(|arr| { + arr.push((*f_ref).take_unwrap()); }); } } @@ -61,9 +62,12 @@ pub fn run() { let state: Box = mem::transmute(QUEUE); QUEUE = 0 as *mut Queue; let mut vec = None; - state.with(|arr| { - vec = Some(mem::replace(arr, vec!())); - }); + { + let vec_ptr = &mut vec; + state.with(|arr| { + *vec_ptr = Some(mem::replace(arr, vec!())); + }); + } vec.take_unwrap() }; diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 7f492a00b80db..f25c5320436cf 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -122,10 +122,11 @@ impl Task { // The only try/catch block in the world. Attempt to run the task's // client-specified code and catch any failures. + let f_ref = &mut f; let try_block = || { // Run the task main function, then do some cleanup. - f.finally(|| { + (*f_ref).finally(|| { #[allow(unused_must_use)] fn close_outputs() { let mut task = Local::borrow(None::); diff --git a/src/libstd/slice.rs b/src/libstd/slice.rs index e5c0cc3babd03..3df5513c753af 100644 --- a/src/libstd/slice.rs +++ b/src/libstd/slice.rs @@ -203,11 +203,14 @@ impl Iterator<(uint, uint)> for ElementSwaps { // Find the index of the largest mobile element: // The direction should point into the vector, and the // swap should be with a smaller `size` element. - let max = self.sdir.iter().map(|&x| x).enumerate() - .filter(|&(i, sd)| - new_pos(i, sd.dir) < self.sdir.len() && - self.sdir.get(new_pos(i, sd.dir)).size < sd.size) - .max_by(|&(_, sd)| sd.size); + let max = { + let sdir = self.sdir.as_slice(); + sdir.iter().map(|&x| x).enumerate() + .filter(|&(i, sd)| { + new_pos(i, sd.dir) < sdir.len() && + sdir[new_pos(i, sd.dir)].size < sd.size + }).max_by(|&(_, sd)| sd.size) + }; match max { Some((i, sd)) => { let j = new_pos(i, sd.dir); @@ -1331,6 +1334,7 @@ mod tests { for len in range(4, 25) { for _ in range(0 , 10) { let mut counts = [0, .. 10]; + let counts_ptr = &mut counts; // create a vector like [(6, 1), (5, 1), (6, 2), ...], // where the first item of each tuple is random, but @@ -1339,8 +1343,8 @@ mod tests { // will occur in sorted order. let mut v = range(0, len).map(|_| { let n = task_rng().gen::() % 10; - counts[n] += 1; - (n, counts[n]) + (*counts_ptr)[n] += 1; + (n, (*counts_ptr)[n]) }).collect::>(); // only sort on the first element, so an unstable sort @@ -2144,10 +2148,11 @@ mod bench { #[bench] fn mut_iterator(b: &mut Bencher) { let mut v = Vec::from_elem(100, 0); + let v_ptr = &mut v; b.iter(|| { let mut i = 0; - for x in v.mut_iter() { + for x in v_ptr.mut_iter() { *x = i; i += 1; } @@ -2173,9 +2178,10 @@ mod bench { #[bench] fn push(b: &mut Bencher) { let mut vec: Vec = vec![]; + let vec_ptr = &mut vec; b.iter(|| { - vec.push(0); - &vec + (*vec_ptr).push(0); + &mut *vec_ptr }) } @@ -2296,23 +2302,27 @@ mod bench { #[bench] fn random_inserts(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { let mut v = Vec::from_elem(30, (0u, 0u)); + let v_ptr = &mut v; for _ in range(0, 100) { - let l = v.len(); - v.insert(rng.gen::() % (l + 1), - (1, 1)); + let l = v_ptr.len(); + v_ptr.insert(rng_ptr.gen::() % (l + 1), + (1, 1)); } }) } #[bench] fn random_removes(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { let mut v = Vec::from_elem(130, (0u, 0u)); + let v_ptr = &mut v; for _ in range(0, 100) { - let l = v.len(); - v.remove(rng.gen::() % l); + let l = v_ptr.len(); + v_ptr.remove(rng_ptr.gen::() % l); } }) } @@ -2320,8 +2330,9 @@ mod bench { #[bench] fn sort_random_small(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(5); + let mut v = rng_ptr.gen_vec::(5); v.as_mut_slice().sort(); }); b.bytes = 5 * mem::size_of::() as u64; @@ -2330,8 +2341,9 @@ mod bench { #[bench] fn sort_random_medium(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(100); + let mut v = rng_ptr.gen_vec::(100); v.as_mut_slice().sort(); }); b.bytes = 100 * mem::size_of::() as u64; @@ -2340,8 +2352,9 @@ mod bench { #[bench] fn sort_random_large(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(10000); + let mut v = rng_ptr.gen_vec::(10000); v.as_mut_slice().sort(); }); b.bytes = 10000 * mem::size_of::() as u64; @@ -2350,10 +2363,11 @@ mod bench { #[bench] fn sort_sorted(b: &mut Bencher) { let mut v = Vec::from_fn(10000, |i| i); + let v_ptr = &mut v; b.iter(|| { - v.sort(); + v_ptr.sort(); }); - b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64; + b.bytes = (v_ptr.len() * mem::size_of_val(v_ptr.get(0))) as u64; } type BigSortable = (u64,u64,u64,u64); @@ -2361,8 +2375,9 @@ mod bench { #[bench] fn sort_big_random_small(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(5); + let mut v = rng_ptr.gen_vec::(5); v.sort(); }); b.bytes = 5 * mem::size_of::() as u64; @@ -2371,8 +2386,9 @@ mod bench { #[bench] fn sort_big_random_medium(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(100); + let mut v = rng_ptr.gen_vec::(100); v.sort(); }); b.bytes = 100 * mem::size_of::() as u64; @@ -2381,8 +2397,9 @@ mod bench { #[bench] fn sort_big_random_large(b: &mut Bencher) { let mut rng = weak_rng(); + let rng_ptr = &mut rng; b.iter(|| { - let mut v = rng.gen_vec::(10000); + let mut v = rng_ptr.gen_vec::(10000); v.sort(); }); b.bytes = 10000 * mem::size_of::() as u64; @@ -2391,9 +2408,10 @@ mod bench { #[bench] fn sort_big_sorted(b: &mut Bencher) { let mut v = Vec::from_fn(10000u, |i| (i, i, i, i)); + let v_ptr = &mut v; b.iter(|| { - v.sort(); + v_ptr.sort(); }); - b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64; + b.bytes = (v_ptr.len() * mem::size_of_val(v_ptr.get(0))) as u64; } } diff --git a/src/libstd/str.rs b/src/libstd/str.rs index eb97f0f6a2808..fe964645c0968 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -741,8 +741,11 @@ pub trait StrAllocating: Str { fn escape_default(&self) -> String { let me = self.as_slice(); let mut out = String::with_capacity(me.len()); - for c in me.chars() { - c.escape_default(|c| out.push_char(c)); + { + let outptr = &mut out; + for c in me.chars() { + c.escape_default(|c| outptr.push_char(c)); + } } out } @@ -751,8 +754,11 @@ pub trait StrAllocating: Str { fn escape_unicode(&self) -> String { let me = self.as_slice(); let mut out = String::with_capacity(me.len()); - for c in me.chars() { - c.escape_unicode(|c| out.push_char(c)); + { + let outptr = &mut out; + for c in me.chars() { + c.escape_unicode(|c| outptr.push_char(c)); + } } out } diff --git a/src/libstd/sync/deque.rs b/src/libstd/sync/deque.rs index 46d6129ded8b8..6b674f48bd96c 100644 --- a/src/libstd/sync/deque.rs +++ b/src/libstd/sync/deque.rs @@ -174,9 +174,11 @@ impl BufferPool { fn free(&self, buf: Box>) { unsafe { let mut buf = Some(buf); + let buf_ptr = &mut buf; self.pool.with(|pool| { - let buf = buf.take_unwrap(); - match pool.iter().position(|v| v.size() > buf.size()) { + let buf = buf_ptr.take_unwrap(); + let buf_size = buf.size(); + match pool.iter().position(|v| v.size() > buf_size) { Some(i) => pool.insert(i, buf), None => pool.push(buf), } @@ -531,9 +533,10 @@ mod tests { #[test] fn many_stampede() { static AMT: uint = 4; - let pool = BufferPool::>::new(); + let mut pool = BufferPool::>::new(); + let pool_ptr = &mut pool; let threads = range(0, AMT).map(|_| { - let (w, s) = pool.deque(); + let (w, s) = pool_ptr.deque(); Thread::start(proc() { stampede(w, s, 4, 10000); }) diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 81eb51107ba06..3f5b7d3fb560f 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -60,8 +60,9 @@ impl DynamicLibrary { -> Result { unsafe { let mut filename = filename; + let filename_ptr = &mut filename; let maybe_library = dl::check_for_errors_in(|| { - match filename.take() { + match (*filename_ptr).take() { Some(name) => dl::open_external(name), None => dl::open_internal() } diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index f0f7e40ce09b8..8e91f9be2bac9 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -92,14 +92,17 @@ impl Exclusive { } #[inline] - pub unsafe fn hold_and_wait(&self, f: |x: &T| -> bool) { + pub unsafe fn hold_and_wait( + &self, + f: |x: &T, cookie: U| -> bool, + cookie: U) { let rec = self.x.get(); let l = (*rec).lock.lock(); if (*rec).failed { fail!("Poisoned Exclusive::new - another task failed inside!"); } (*rec).failed = true; - let result = f(&(*rec).data); + let result = f(&(*rec).data, cookie); (*rec).failed = false; if result { l.wait(); diff --git a/src/libsync/mutex.rs b/src/libsync/mutex.rs index 54c3a9c77f816..0444f17cef8b2 100644 --- a/src/libsync/mutex.rs +++ b/src/libsync/mutex.rs @@ -238,6 +238,7 @@ impl StaticMutex { } old => old, }; + let old_ptr = &mut old; // Alright, everything else failed. We need to deschedule ourselves and // flag ourselves as waiting. Note that this case should only happen @@ -258,24 +259,26 @@ impl StaticMutex { assert_eq!(prev, 0); loop { - assert_eq!(old & native_bit, 0); + assert_eq!(*old_ptr & native_bit, 0); // If the old state was locked, then we need to flag ourselves // as blocking in the state. If the old state was unlocked, then // we attempt to acquire the mutex. Everything here is a CAS // loop that'll eventually make progress. - if old & LOCKED != 0 { - old = match self.state.compare_and_swap(old, - old | native_bit, - atomics::SeqCst) { - n if n == old => return Ok(()), + if *old_ptr & LOCKED != 0 { + *old_ptr = match self.state.compare_and_swap( + *old_ptr, + *old_ptr | native_bit, + atomics::SeqCst) { + n if n == *old_ptr => return Ok(()), n => n }; } else { - assert_eq!(old, 0); - old = match self.state.compare_and_swap(old, - old | LOCKED, - atomics::SeqCst) { - n if n == old => { + assert_eq!(*old_ptr, 0); + *old_ptr = match self.state.compare_and_swap( + *old_ptr, + *old_ptr | LOCKED, + atomics::SeqCst) { + n if n == *old_ptr => { // After acquiring the lock, we have access to the // flavor field, and we've regained access to our // respective native/green blocker field. @@ -330,10 +333,11 @@ impl StaticMutex { } let mut node = q::Node::new(0); + let node_ptr = &mut node; t.deschedule(1, |task| { unsafe { - node.data = task.cast_to_uint(); - self.q.push(&mut node); + node_ptr.data = task.cast_to_uint(); + self.q.push(node_ptr); } Ok(()) }); diff --git a/src/libsync/one.rs b/src/libsync/one.rs index eb91919870809..43d1bbfeeaff9 100644 --- a/src/libsync/one.rs +++ b/src/libsync/one.rs @@ -131,9 +131,15 @@ mod test { fn smoke_once() { static mut o: Once = ONCE_INIT; let mut a = 0; - unsafe { o.doit(|| a += 1); } + { + let a_ptr = &mut a; + unsafe { o.doit(|| *a_ptr += 1); } + } assert_eq!(a, 1); - unsafe { o.doit(|| a += 1); } + { + let a_ptr = &mut a; + unsafe { o.doit(|| *a_ptr += 1); } + } assert_eq!(a, 1); } diff --git a/src/libsync/raw.rs b/src/libsync/raw.rs index aae790f887a61..57ea11c580ef4 100644 --- a/src/libsync/raw.rs +++ b/src/libsync/raw.rs @@ -128,14 +128,17 @@ impl Sem { pub fn acquire(&self) { unsafe { let mut waiter_nobe = None; - self.with(|state| { - state.count -= 1; - if state.count < 0 { - // Create waiter nobe, enqueue ourself, and tell - // outer scope we need to block. - waiter_nobe = Some(state.waiters.wait_end()); - } - }); + { + let waiter_nobe_ptr = &mut waiter_nobe; + self.with(|state| { + state.count -= 1; + if state.count < 0 { + // Create waiter nobe, enqueue ourself, and tell + // outer scope we need to block. + *waiter_nobe_ptr = Some(state.waiters.wait_end()); + } + }); + } // Uncomment if you wish to test for sem races. Not // valgrind-friendly. /* for _ in range(0, 1000) { task::deschedule(); } */ @@ -241,7 +244,9 @@ impl<'a> Condvar<'a> { /// wait() is equivalent to wait_on(0). pub fn wait_on(&self, condvar_id: uint) { let mut wait_end = None; + let wait_end_ptr = &mut wait_end; let mut out_of_bounds = None; + let out_of_bounds_ptr = &mut out_of_bounds; // Release lock, 'atomically' enqueuing ourselves in so doing. unsafe { self.sem.with(|state| { @@ -253,21 +258,24 @@ impl<'a> Condvar<'a> { } // Create waiter nobe, and enqueue ourself to // be woken up by a signaller. - wait_end = Some(state.blocked.get(condvar_id).wait_end()); + *wait_end_ptr = + Some(state.blocked.get(condvar_id).wait_end()); } else { - out_of_bounds = Some(state.blocked.len()); + *out_of_bounds_ptr = Some(state.blocked.len()); } }) } // If deschedule checks start getting inserted anywhere, we can be // killed before or after enqueueing. - check_cvar_bounds(out_of_bounds, condvar_id, "cond.wait_on()", || { + check_cvar_bounds(*out_of_bounds_ptr, + condvar_id, + "cond.wait_on()", || { // Unconditionally "block". (Might not actually block if a // signaller already sent -- I mean 'unconditionally' in contrast // with acquire().) (|| { - let _ = wait_end.take_unwrap().recv(); + let _ = wait_end_ptr.take_unwrap().recv(); }).finally(|| { // Reacquire the condvar. match self.order { @@ -289,17 +297,19 @@ impl<'a> Condvar<'a> { unsafe { let mut out_of_bounds = None; let mut result = false; + let result_ptr = &mut result; + let out_of_bounds_ptr = &mut out_of_bounds; self.sem.with(|state| { if condvar_id < state.blocked.len() { - result = state.blocked.get(condvar_id).signal(); + *result_ptr = state.blocked.get(condvar_id).signal(); } else { - out_of_bounds = Some(state.blocked.len()); + *out_of_bounds_ptr = Some(state.blocked.len()); } }); - check_cvar_bounds(out_of_bounds, + check_cvar_bounds(*out_of_bounds_ptr, condvar_id, "cond.signal_on()", - || result) + || *result_ptr) } } @@ -310,23 +320,26 @@ impl<'a> Condvar<'a> { pub fn broadcast_on(&self, condvar_id: uint) -> uint { let mut out_of_bounds = None; let mut queue = None; + let queue_ptr = &mut queue; + let out_of_bounds_ptr = &mut out_of_bounds; unsafe { self.sem.with(|state| { if condvar_id < state.blocked.len() { // To avoid :broadcast_heavy, we make a new waitqueue, // swap it out with the old one, and broadcast on the // old one outside of the little-lock. - queue = Some(mem::replace(state.blocked.get_mut(condvar_id), - WaitQueue::new())); + *queue_ptr = + Some(mem::replace(state.blocked.get_mut(condvar_id), + WaitQueue::new())); } else { - out_of_bounds = Some(state.blocked.len()); + *out_of_bounds_ptr = Some(state.blocked.len()); } }); - check_cvar_bounds(out_of_bounds, + check_cvar_bounds(*out_of_bounds_ptr, condvar_id, "cond.signal_on()", || { - queue.take_unwrap().broadcast() + queue_ptr.take_unwrap().broadcast() }) } } diff --git a/src/libsyntax/abi.rs b/src/libsyntax/abi.rs index bc53d2bec8d6e..245a10a0c239a 100644 --- a/src/libsyntax/abi.rs +++ b/src/libsyntax/abi.rs @@ -99,16 +99,16 @@ pub fn lookup(name: &str) -> Option { */ let mut res = None; - + let res_ptr = &mut res; each_abi(|abi| { if name == abi.data().name { - res = Some(abi); + *res_ptr = Some(abi); false } else { true } }); - res + *res_ptr } pub fn all_names() -> Vec<&'static str> { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 5b61cd45483ac..36a15d3c01e22 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -644,26 +644,27 @@ pub fn is_item_impl(item: @ast::Item) -> bool { } } -pub fn walk_pat(pat: &Pat, it: |&Pat| -> bool) -> bool { +pub fn walk_pat(pat: &Pat, mut it: |&Pat| -> bool) -> bool { if !it(pat) { return false; } + let it_ptr = &mut it; match pat.node { - PatIdent(_, _, Some(p)) => walk_pat(p, it), + PatIdent(_, _, Some(p)) => walk_pat(p, |p| (*it_ptr)(p)), PatStruct(_, ref fields, _) => { - fields.iter().advance(|f| walk_pat(f.pat, |p| it(p))) + fields.iter().advance(|f| walk_pat(f.pat, |p| (*it_ptr)(p))) } PatEnum(_, Some(ref s)) | PatTup(ref s) => { - s.iter().advance(|&p| walk_pat(p, |p| it(p))) + s.iter().advance(|&p| walk_pat(p, |p| (*it_ptr)(p))) } PatUniq(s) | PatRegion(s) => { - walk_pat(s, it) + walk_pat(s, |p| (*it_ptr)(p)) } PatVec(ref before, ref slice, ref after) => { - before.iter().advance(|&p| walk_pat(p, |p| it(p))) && - slice.iter().advance(|&p| walk_pat(p, |p| it(p))) && - after.iter().advance(|&p| walk_pat(p, |p| it(p))) + before.iter().advance(|&p| walk_pat(p, |p| (*it_ptr)(p))) && + slice.iter().advance(|&p| walk_pat(p, |p| (*it_ptr)(p))) && + after.iter().advance(|&p| walk_pat(p, |p| (*it_ptr)(p))) } PatMac(_) => fail!("attempted to analyze unexpanded pattern"), PatWild | PatWildMulti | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) | diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 527e851ae35ac..84a4a959a001c 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -349,6 +349,7 @@ pub fn test_cfg> (cfg: &[@MetaItem], mut metas: It) -> bool { // having no #[cfg(...)] attributes counts as matching. let mut no_cfgs = true; + let no_cfgs_ptr = &mut no_cfgs; // this would be much nicer as a chain of iterator adaptors, but // this doesn't work. @@ -356,7 +357,7 @@ pub fn test_cfg> debug!("testing name: {}", mi.name()); let this_matches = if mi.check_name("cfg") { // it is a #[cfg()] attribute debug!("is cfg"); - no_cfgs = false; + *no_cfgs_ptr = false; // only #[cfg(...)] ones are understood. match mi.meta_item_list() { Some(cfg_meta) => { @@ -385,8 +386,10 @@ pub fn test_cfg> }; matches || this_matches }); - debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", no_cfgs, some_cfg_matches); - no_cfgs || some_cfg_matches + debug!("test_cfg (no_cfgs={}, some_cfg_matches={})", + *no_cfgs_ptr, + some_cfg_matches); + *no_cfgs_ptr || some_cfg_matches } /// Represents the #[deprecated="foo"] and friends attributes. diff --git a/src/libsyntax/ext/deriving/clone.rs b/src/libsyntax/ext/deriving/clone.rs index 89c94891b3380..3d549f92ea60d 100644 --- a/src/libsyntax/ext/deriving/clone.rs +++ b/src/libsyntax/ext/deriving/clone.rs @@ -54,8 +54,6 @@ fn cs_clone( let clone_ident = substr.method_ident; let ctor_ident; let all_fields; - let subcall = |field: &FieldInfo| - cx.expr_method_call(field.span, field.self_, clone_ident, Vec::new()); match *substr.fields { Struct(ref af) => { @@ -81,7 +79,15 @@ fn cs_clone( if all_fields.len() >= 1 && all_fields.get(0).name.is_none() { // enum-like - let subcalls = all_fields.iter().map(subcall).collect(); + let subcalls = { + let subcall = |field: &FieldInfo| { + cx.expr_method_call(field.span, + field.self_, + clone_ident, + Vec::new()) + }; + all_fields.iter().map(subcall).collect() + }; cx.expr_call_ident(trait_span, ctor_ident, subcalls) } else { // struct-like @@ -95,6 +101,12 @@ fn cs_clone( name).as_slice()) } }; + let subcall = |field: &FieldInfo| { + cx.expr_method_call(field.span, + field.self_, + clone_ident, + Vec::new()) + }; cx.field_imm(field.span, ident, subcall(field)) }).collect::>(); diff --git a/src/libsyntax/ext/deriving/cmp/totalord.rs b/src/libsyntax/ext/deriving/cmp/totalord.rs index 3ca4f9e286263..c098c318e20b1 100644 --- a/src/libsyntax/ext/deriving/cmp/totalord.rs +++ b/src/libsyntax/ext/deriving/cmp/totalord.rs @@ -67,6 +67,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> @Expr { let test_id = cx.ident_of("__test"); let equals_path = ordering_const(cx, span, Equal); + let equals_path_2 = equals_path.clone(); /* Builds: @@ -107,7 +108,7 @@ pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, old, Some(cx.expr_ident(span, test_id))); cx.expr_block(cx.block(span, vec!(assign), Some(if_))) }, - cx.expr_path(equals_path.clone()), + cx.expr_path(equals_path_2), |cx, span, list, _| { match list { // an earlier nonmatching variant is Less than a diff --git a/src/libsyntax/ext/deriving/default.rs b/src/libsyntax/ext/deriving/default.rs index c225906ed2bab..e185a066c310e 100644 --- a/src/libsyntax/ext/deriving/default.rs +++ b/src/libsyntax/ext/deriving/default.rs @@ -45,14 +45,16 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } -fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn default_substructure(cx: &mut ExtCtxt, + trait_span: Span, + substr: &Substructure) + -> @Expr { let default_ident = vec!( cx.ident_of("std"), cx.ident_of("default"), cx.ident_of("Default"), cx.ident_of("default") ); - let default_call = |span| cx.expr_call_global(span, default_ident.clone(), Vec::new()); return match *substr.fields { StaticStruct(_, ref summary) => { @@ -61,14 +63,35 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur if fields.is_empty() { cx.expr_ident(trait_span, substr.type_ident) } else { - let exprs = fields.iter().map(|sp| default_call(*sp)).collect(); - cx.expr_call_ident(trait_span, substr.type_ident, exprs) + let exprs = { + let default_call = |span| { + cx.expr_call_global(span, + default_ident.clone(), + Vec::new()) + }; + fields.iter() + .map(|sp| default_call(*sp)) + .collect() + }; + cx.expr_call_ident(trait_span, + substr.type_ident, + exprs) } } Named(ref fields) => { - let default_fields = fields.iter().map(|&(ident, span)| { - cx.field_imm(span, ident, default_call(span)) - }).collect(); + let default_fields = { + let cx: &ExtCtxt = cx; + let default_ident_ref = &default_ident; + fields.iter().map(|&(ident, span)| { + let default_call = |span| { + cx.expr_call_global( + span, + (*default_ident_ref).clone(), + Vec::new()) + }; + cx.field_imm(span, ident, default_call(span)) + }).collect() + }; cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) } } diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index 0f4af144eadea..32f3b571de796 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -380,6 +380,7 @@ impl<'a> TraitDef<'a> { generics: &Generics, methods: Vec<@ast::Method> ) -> @ast::Item { let trait_path = self.path.to_path(cx, self.span, type_ident, generics); + let trait_path_2 = trait_path.clone(); let Generics { mut lifetimes, ty_params } = self.generics.to_generics(cx, self.span, type_ident, generics); @@ -399,7 +400,7 @@ impl<'a> TraitDef<'a> { type_ident, generics)) }).collect(); // require the current trait - bounds.push(cx.typarambound(trait_path.clone())); + bounds.push(cx.typarambound(trait_path_2.clone())); cx.typaram(self.span, ty_param.ident, @@ -690,11 +691,12 @@ impl<'a> MethodDef<'a> { // transpose raw_fields let fields = if raw_fields.len() > 0 { - raw_fields.get(0) - .iter() - .enumerate() - .map(|(i, &(span, opt_id, field))| { - let other_fields = raw_fields.tail().iter().map(|l| { + let raw_fields_ptr = &raw_fields; + raw_fields_ptr.get(0) + .iter() + .enumerate() + .map(|(i, &(span, opt_id, field))| { + let other_fields = raw_fields_ptr.tail().iter().map(|l| { match l.get(i) { &(_, _, ex) => ex } @@ -1256,27 +1258,30 @@ fields. `use_foldl` controls whether this is done left-to-right */ #[inline] pub fn cs_same_method_fold(use_foldl: bool, - f: |&mut ExtCtxt, Span, @Expr, @Expr| -> @Expr, + mut f: |&mut ExtCtxt, Span, @Expr, @Expr| -> @Expr, base: @Expr, enum_nonmatch_f: EnumNonMatchFunc, cx: &mut ExtCtxt, trait_span: Span, substructure: &Substructure) -> @Expr { + let f_ptr = &mut f; cs_same_method( |cx, span, vals| { if use_foldl { vals.iter().fold(base, |old, &new| { - f(cx, span, old, new) + (*f_ptr)(cx, span, old, new) }) } else { vals.iter().rev().fold(base, |old, &new| { - f(cx, span, old, new) + (*f_ptr)(cx, span, old, new) }) } }, enum_nonmatch_f, - cx, trait_span, substructure) + cx, + trait_span, + substructure) } /** diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 3e6b8d522d4f9..afe2bd3806f40 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -69,10 +69,6 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) _ => cx.span_bug(trait_span, "incorrect number of arguments in `deriving(Hash)`") }; let hash_ident = substr.method_ident; - let call_hash = |span, thing_expr| { - let expr = cx.expr_method_call(span, thing_expr, hash_ident, vec!(state_expr)); - cx.stmt_expr(expr) - }; let mut stmts = Vec::new(); let fields = match *substr.fields { @@ -85,6 +81,13 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) None => cx.expr_uint(trait_span, index) }; + let call_hash = |span, thing_expr| { + let expr = cx.expr_method_call(span, + thing_expr, + hash_ident, + vec!(state_expr)); + cx.stmt_expr(expr) + }; stmts.push(call_hash(trait_span, discriminant)); fs @@ -93,6 +96,13 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) }; for &FieldInfo { self_, span, .. } in fields.iter() { + let call_hash = |span, thing_expr| { + let expr = cx.expr_method_call(span, + thing_expr, + hash_ident, + vec!(state_expr)); + cx.stmt_expr(expr) + }; stmts.push(call_hash(span, self_)); } diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index aeff36a49e60e..db9e6767f209f 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -49,7 +49,8 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, _span: Span, mitem: @MetaItem, item: @Item, - push: |@Item|) { + mut push: |@Item|) { + let push_ref = &mut push; match mitem.node { MetaNameValue(_, ref l) => { cx.span_err(l.span, "unexpected value in `deriving`"); @@ -68,7 +69,7 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt, MetaWord(ref tname) => { macro_rules! expand(($func:path) => ($func(cx, titem.span, titem, item, - |i| push(i)))); + |i| (*push_ref)(i)))); match tname.get() { "Clone" => expand!(clone::expand_deriving_clone), diff --git a/src/libsyntax/ext/deriving/rand.rs b/src/libsyntax/ext/deriving/rand.rs index 397b99925c8ec..e4831e62cd350 100644 --- a/src/libsyntax/ext/deriving/rand.rs +++ b/src/libsyntax/ext/deriving/rand.rs @@ -62,14 +62,14 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) cx.ident_of("Rand"), cx.ident_of("rand") ); - let rand_call = |cx: &mut ExtCtxt, span| { - cx.expr_call_global(span, - rand_ident.clone(), - vec!( *rng.get(0) )) - }; return match *substr.fields { StaticStruct(_, ref summary) => { + let rand_call = |cx: &mut ExtCtxt, span| { + cx.expr_call_global(span, + rand_ident.clone(), + vec!( *rng.get(0) )) + }; rand_thing(cx, trait_span, substr.type_ident, summary, rand_call) } StaticEnum(_, ref variants) => { @@ -113,6 +113,13 @@ fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) let i_expr = cx.expr_uint(v_span, i); let pat = cx.pat_lit(v_span, i_expr); + let rand_ident_ptr = &rand_ident; + let rng_ptr = &rng; + let rand_call = |cx: &mut ExtCtxt, span| { + cx.expr_call_global(span, + (*rand_ident_ptr).clone(), + vec!( *(*rng_ptr).get(0) )) + }; let thing = rand_thing(cx, v_span, ident, summary, |cx, sp| rand_call(cx, sp)); cx.arm(v_span, vec!( pat ), thing) }).collect:: >(); diff --git a/src/libsyntax/ext/deriving/zero.rs b/src/libsyntax/ext/deriving/zero.rs index 449851dd3ea59..ea4c85835a258 100644 --- a/src/libsyntax/ext/deriving/zero.rs +++ b/src/libsyntax/ext/deriving/zero.rs @@ -62,14 +62,16 @@ pub fn expand_deriving_zero(cx: &mut ExtCtxt, trait_def.expand(cx, mitem, item, push) } -fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> @Expr { +fn zero_substructure(cx: &mut ExtCtxt, + trait_span: Span, + substr: &Substructure) + -> @Expr { let zero_ident = vec!( cx.ident_of("std"), cx.ident_of("num"), cx.ident_of("Zero"), cx.ident_of("zero") ); - let zero_call = |span| cx.expr_call_global(span, zero_ident.clone(), Vec::new()); return match *substr.fields { StaticStruct(_, ref summary) => { @@ -78,14 +80,31 @@ fn zero_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) if fields.is_empty() { cx.expr_ident(trait_span, substr.type_ident) } else { - let exprs = fields.iter().map(|sp| zero_call(*sp)).collect(); + let exprs = { + let zero_call = |span| { + cx.expr_call_global(span, + zero_ident.clone(), + Vec::new()) + }; + fields.iter().map(|sp| zero_call(*sp)).collect() + }; cx.expr_call_ident(trait_span, substr.type_ident, exprs) } } Named(ref fields) => { - let zero_fields = fields.iter().map(|&(ident, span)| { - cx.field_imm(span, ident, zero_call(span)) - }).collect(); + let zero_fields = { + let cx: &ExtCtxt = cx; + let zero_ident_ref = &zero_ident; + fields.iter().map(|&(ident, span)| { + let zero_call = |span| { + cx.expr_call_global( + span, + (*zero_ident_ref).clone(), + Vec::new()) + }; + cx.field_imm(span, ident, zero_call(span)) + }).collect() + }; cx.expr_struct_ident(trait_span, substr.type_ident, zero_fields) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 03001acc5d04d..aed584fb11c43 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -306,8 +306,14 @@ pub fn expand_item(it: @ast::Item, fld: &mut MacroExpander) // we'd ideally decorator_items.push_all(expand_item(item, fld)), // but that double-mut-borrows fld let mut items: SmallVector<@ast::Item> = SmallVector::zero(); - dec_fn(fld.cx, attr.span, attr.node.value, it, - |item| items.push(item)); + { + let items_ptr = &mut items; + dec_fn(fld.cx, + attr.span, + attr.node.value, + it, + |item| items_ptr.push(item)); + } decorator_items.extend(items.move_iter() .flat_map(|item| expand_item(item, fld).move_iter())); diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs index cc08cb429f55f..fb5549dc55849 100644 --- a/src/libsyntax/parse/comments.rs +++ b/src/libsyntax/parse/comments.rs @@ -397,9 +397,13 @@ pub fn gather_comments_and_literals(span_diagnostic: //discard, and look ahead; we're working with internal state let TokenAndSpan {tok: tok, sp: sp} = rdr.peek(); if token::is_lit(&tok) { + let literals_ptr = &mut literals; with_str_from(&rdr, bstart, |s| { debug!("tok lit: {}", s); - literals.push(Literal {lit: s.to_string(), pos: sp.lo}); + literals_ptr.push(Literal { + lit: s.to_string(), + pos: sp.lo, + }); }) } else { debug!("tok: {}", token::to_str(&tok)); diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs index fb67a76b85b4c..dddc5da48dfc3 100644 --- a/src/libsyntax/parse/lexer.rs +++ b/src/libsyntax/parse/lexer.rs @@ -158,14 +158,20 @@ fn fatal_span_char(rdr: &mut StringReader, m: &str, c: char) -> ! { let mut m = m.to_string(); m.push_str(": "); - char::escape_default(c, |c| m.push_char(c)); + { + let m_ptr = &mut m; + char::escape_default(c, |c| m_ptr.push_char(c)); + } fatal_span(rdr, from_pos, to_pos, m.as_slice()); } fn err_span_char(rdr: &mut StringReader, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { let mut m = m.to_string(); m.push_str(": "); - char::escape_default(c, |c| m.push_char(c)); + { + let m_ptr = &mut m; + char::escape_default(c, |c| m_ptr.push_char(c)); + } err_span(rdr, from_pos, to_pos, m.as_slice()); } @@ -324,12 +330,14 @@ fn consume_any_line_comment(rdr: &mut StringReader) while !rdr.curr_is('\n') && !is_eof(rdr) { bump(rdr); } + + let rdr_pos = rdr.pos; let ret = with_str_from(rdr, start_bpos, |string| { // but comments with only more "/"s are not if !is_line_non_doc_comment(string) { Some(TokenAndSpan{ tok: token::DOC_COMMENT(str_to_ident(string)), - sp: codemap::mk_sp(start_bpos, rdr.pos) + sp: codemap::mk_sp(start_bpos, rdr_pos) }) } else { None @@ -405,12 +413,13 @@ fn consume_block_comment(rdr: &mut StringReader) -> Option { } let res = if is_doc_comment { + let rdr_pos = rdr.pos; with_str_from(rdr, start_bpos, |string| { // but comments with only "*"s between two "/"s are not if !is_block_non_doc_comment(string) { Some(TokenAndSpan{ tok: token::DOC_COMMENT(str_to_ident(string)), - sp: codemap::mk_sp(start_bpos, rdr.pos) + sp: codemap::mk_sp(start_bpos, rdr_pos) }) } else { None @@ -674,11 +683,13 @@ fn next_token_inner(rdr: &mut StringReader) -> token::Token { bump(rdr); } - return with_str_from(rdr, start, |string| { + let rdr_ptr = &rdr; + return with_str_from(*rdr_ptr, start, |string| { if string == "_" { token::UNDERSCORE } else { - let is_mod_name = rdr.curr_is(':') && nextch_is(rdr, ':'); + let is_mod_name = rdr_ptr.curr_is(':') && + nextch_is(*rdr_ptr, ':'); // FIXME: perform NFKC normalization here. (Issue #2253) token::IDENT(str_to_ident(string), is_mod_name) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 65ad83d4b4fb1..19d55d9615461 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3442,18 +3442,22 @@ impl<'a> Parser<'a> { if self.eat(&token::LT) { let lifetimes = self.parse_lifetimes(); let mut seen_default = false; + let seen_default_ptr = &mut seen_default; let ty_params = self.parse_seq_to_gt(Some(token::COMMA), |p| { p.forbid_lifetime(); let ty_param = p.parse_ty_param(); if ty_param.default.is_some() { - seen_default = true; - } else if seen_default { + *seen_default_ptr = true; + } else if *seen_default_ptr { p.span_err(p.last_span, "type parameters with a default must be trailing"); } ty_param }); - ast::Generics { lifetimes: lifetimes, ty_params: ty_params } + ast::Generics { + lifetimes: lifetimes, + ty_params: ty_params, + } } else { ast_util::empty_generics() } @@ -4235,7 +4239,8 @@ impl<'a> Parser<'a> { name: String, id_sp: Span) -> (ast::Item_, Vec ) { let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - match included_mod_stack.iter().position(|p| *p == path) { + let path_ptr = &path; + match included_mod_stack.iter().position(|p| *p == *path_ptr) { Some(i) => { let mut err = String::from_str("circular modules: "); let len = included_mod_stack.len(); @@ -4243,12 +4248,12 @@ impl<'a> Parser<'a> { err.push_str(p.display().as_maybe_owned().as_slice()); err.push_str(" -> "); } - err.push_str(path.display().as_maybe_owned().as_slice()); + err.push_str(path_ptr.display().as_maybe_owned().as_slice()); self.span_fatal(id_sp, err.as_slice()); } None => () } - included_mod_stack.push(path.clone()); + included_mod_stack.push((*path_ptr).clone()); drop(included_mod_stack); let mut p0 = diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 2c090d053a3d2..b66af20abea0a 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -195,9 +195,12 @@ pub fn to_str(t: &Token) -> String { /* Literals */ LIT_CHAR(c) => { let mut res = String::from_str("'"); - c.escape_default(|c| { - res.push_char(c); - }); + { + let res_ptr = &mut res; + c.escape_default(|c| { + res_ptr.push_char(c); + }); + } res.push_char('\''); res } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3127085ffedca..4d009fdae6139 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2234,7 +2234,10 @@ impl<'a> State<'a> { ast::LitStr(ref st, style) => self.print_string(st.get(), style), ast::LitChar(ch) => { let mut res = String::from_str("'"); - ch.escape_default(|c| res.push_char(c)); + { + let res_ptr = &mut res; + ch.escape_default(|c| res_ptr.push_char(c)); + } res.push_char('\''); word(&mut self.s, res.as_slice()) } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f02bc144d153c..a00b905669a5d 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -816,7 +816,10 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec ) -> io::IoR }, None => {} } - try!(run_tests(opts, tests, |x| callback(&x, &mut st))); + { + let st_ptr = &mut st; + try!(run_tests(opts, tests, |x| callback(&x, st_ptr))); + } match opts.save_metrics { None => (), Some(ref pth) => { @@ -1287,11 +1290,13 @@ impl Bencher { } // This is a more statistics-driven benchmark algorithm - pub fn auto_bench(&mut self, f: |&mut Bencher|) -> stats::Summary { + pub fn auto_bench(&mut self, mut f: |&mut Bencher|) + -> stats::Summary { + let f_ptr = &mut f; // Initial bench run to get ballpark figure. let mut n = 1_u64; - self.bench_n(n, |x| f(x)); + self.bench_n(n, |x| (*f_ptr)(x)); // Try to estimate iter count for 1ms falling back to 1m // iterations if first run took < 1ns. @@ -1313,7 +1318,7 @@ impl Bencher { let loop_start = precise_time_ns(); for p in samples.mut_iter() { - self.bench_n(n, |x| f(x)); + self.bench_n(n, |x| (*f_ptr)(x)); *p = self.ns_per_iter() as f64; }; @@ -1321,7 +1326,7 @@ impl Bencher { let summ = stats::Summary::new(samples); for p in samples.mut_iter() { - self.bench_n(5 * n, |x| f(x)); + self.bench_n(5 * n, |x| (*f_ptr)(x)); *p = self.ns_per_iter() as f64; }; diff --git a/src/libworkcache/lib.rs b/src/libworkcache/lib.rs index 064979fa2771c..affcf31862fe3 100644 --- a/src/libworkcache/lib.rs +++ b/src/libworkcache/lib.rs @@ -505,10 +505,12 @@ fn test() { let cx = Context::new(Arc::new(RWLock::new(Database::new(db_path))), Arc::new(TreeMap::new())); - let s = cx.with_prep("test1", |prep| { + let cx_ptr = &cx; + let pth_ptr = &pth; + let s = cx_ptr.with_prep("test1", |prep| { - let subcx = cx.clone(); - let pth = pth.clone(); + let subcx = (*cx_ptr).clone(); + let pth = (*pth_ptr).clone(); let contents = File::open(&pth).read_to_end().unwrap(); let file_content = from_utf8(contents.as_slice()).unwrap() diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index ab2f9b0020624..f379bff0b201f 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -46,35 +46,38 @@ impl Results { rand_cap: uint, f: || -> T) { { let mut set = f(); + let set_ptr = &mut set; timed(&mut self.sequential_ints, || { for i in range(0u, num_keys) { - set.insert(i); + set_ptr.insert(i); } for i in range(0u, num_keys) { - assert!(set.contains(&i)); + assert!(set_ptr.contains(&i)); } }) } { let mut set = f(); + let set_ptr = &mut set; timed(&mut self.random_ints, || { for _ in range(0, num_keys) { - set.insert(rng.gen::() % rand_cap); + set_ptr.insert(rng.gen::() % rand_cap); } }) } { let mut set = f(); + let set_ptr = &mut set; for i in range(0u, num_keys) { - set.insert(i); + set_ptr.insert(i); } timed(&mut self.delete_ints, || { for i in range(0u, num_keys) { - assert!(set.remove(&i)); + assert!(set_ptr.remove(&i)); } }) } @@ -88,35 +91,38 @@ impl Results { f: || -> T) { { let mut set = f(); + let set_ptr = &mut set; timed(&mut self.sequential_strings, || { for i in range(0u, num_keys) { - set.insert(i.to_str().to_string()); + set_ptr.insert(i.to_str().to_string()); } for i in range(0u, num_keys) { - assert!(set.contains(&i.to_str().to_string())); + assert!(set_ptr.contains(&i.to_str().to_string())); } }) } { let mut set = f(); + let set_ptr = &mut set; timed(&mut self.random_strings, || { for _ in range(0, num_keys) { let s = rng.gen::().to_str().to_string(); - set.insert(s); + set_ptr.insert(s); } }) } { let mut set = f(); + let set_ptr = &mut set; for i in range(0u, num_keys) { - set.insert(i.to_str().to_string()); + set_ptr.insert(i.to_str().to_string()); } timed(&mut self.delete_strings, || { for i in range(0u, num_keys) { - assert!(set.remove(&i.to_str().to_string())); + assert!(set_ptr.remove(&i.to_str().to_string())); } }) } diff --git a/src/test/bench/core-std.rs b/src/test/bench/core-std.rs index d53a89684213d..39e2a82480864 100644 --- a/src/test/bench/core-std.rs +++ b/src/test/bench/core-std.rs @@ -48,7 +48,10 @@ fn maybe_run_test(argv: &[String], name: String, test: ||) { if os::getenv("RUST_BENCH").is_some() { run_test = true } else if argv.len() > 0 { - run_test = argv.iter().any(|x| x == &"all".to_string()) || argv.iter().any(|x| x == &name) + let name_ptr = &name; + run_test = argv.iter() + .any(|x| x == &"all".to_string()) || + argv.iter().any(|x| x == name_ptr) } if !run_test { diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs index 2c8b23f2acdf1..302fe2b6c16ee 100644 --- a/src/test/bench/shootout-chameneos-redux.rs +++ b/src/test/bench/shootout-chameneos-redux.rs @@ -148,12 +148,13 @@ fn rendezvous(nn: uint, set: Vec) { let (to_rendezvous_log, from_creatures_log) = channel::(); // these channels will allow us to talk to each creature by 'name'/index - let mut to_creature: Vec> = + let mut to_creature: Vec> = { + let to_rendezvous_log_ptr = &to_rendezvous_log; set.iter().enumerate().map(|(ii, &col)| { // create each creature as a listener with a port, and // give us a channel to talk to each let to_rendezvous = to_rendezvous.clone(); - let to_rendezvous_log = to_rendezvous_log.clone(); + let to_rendezvous_log = (*to_rendezvous_log_ptr).clone(); let (to_creature, from_rendezvous) = channel(); spawn(proc() { creature(ii, @@ -163,7 +164,8 @@ fn rendezvous(nn: uint, set: Vec) { to_rendezvous_log); }); to_creature - }).collect(); + }).collect() + }; let mut creatures_met = 0; diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index 4126fda00bcce..49d09f6c40a08 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -40,9 +40,12 @@ struct AAGen<'a> { impl<'a> AAGen<'a> { fn new<'b>(rng: &'b mut MyRandom, aa: &[(char, f32)]) -> AAGen<'b> { let mut cum = 0.; + let cum_ptr = &mut cum; let data = aa.iter() - .map(|&(ch, p)| { cum += p; (MyRandom::normalize(cum), ch as u8) }) - .collect(); + .map(|&(ch, p)| { + *cum_ptr += p; + (MyRandom::normalize(*cum_ptr), ch as u8) + }).collect(); AAGen { rng: rng, data: data } } } diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index 8be6439d88c41..3c25421591d24 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -118,11 +118,13 @@ fn make_sequence_processor(sz: uint, line = from_parent.recv(); if line == Vec::new() { break; } - carry = windows_with_carry(carry.append(line.as_slice()).as_slice(), - sz, - |window| { - update_freq(&mut freqs, window); - total += 1u; + let freqs_ptr = &mut freqs; + let total_ptr = &mut total; + carry = windows_with_carry(carry.append(line.as_slice()).as_slice(), + sz, + |window| { + update_freq(freqs_ptr, window); + *total_ptr += 1u; }); } @@ -157,21 +159,24 @@ fn main() { let sizes = vec!(1u,2,3,4,6,12,18); let mut streams = Vec::from_fn(sizes.len(), |_| Some(channel::())); let mut from_child = Vec::new(); - let to_child = sizes.iter().zip(streams.mut_iter()).map(|(sz, stream_ref)| { - let sz = *sz; - let stream = replace(stream_ref, None); - let (to_parent_, from_child_) = stream.unwrap(); + let to_child = { + let from_child_ptr = &mut from_child; + sizes.iter().zip(streams.mut_iter()).map(|(sz, stream_ref)| { + let sz = *sz; + let stream = replace(stream_ref, None); + let (to_parent_, from_child_) = stream.unwrap(); - from_child.push(from_child_); + from_child_ptr.push(from_child_); - let (to_child, from_parent) = channel(); + let (to_child, from_parent) = channel(); - spawn(proc() { - make_sequence_processor(sz, &from_parent, &to_parent_); - }); + spawn(proc() { + make_sequence_processor(sz, &from_parent, &to_parent_); + }); - to_child - }).collect:: >> >(); + to_child + }).collect:: >> >() + }; // latch stores true after we've started diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index 4b561def720c1..5f516c709fece 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -271,14 +271,23 @@ fn main() { }; let input = Arc::new(input); - let nb_freqs: Vec<(uint, Future)> = range(1u, 3).map(|i| { - let input = input.clone(); - (i, Future::spawn(proc() generate_frequencies(input.as_slice(), i))) - }).collect(); - let occ_freqs: Vec> = OCCURRENCES.iter().map(|&occ| { - let input = input.clone(); - Future::spawn(proc() generate_frequencies(input.as_slice(), occ.len())) - }).collect(); + let nb_freqs: Vec<(uint, Future
)>; + let occ_freqs: Vec>; + { + let input_ptr = &input; + nb_freqs = range(1u, 3).map(|i| { + let input = (*input_ptr).clone(); + (i, Future::spawn(proc() { + generate_frequencies(input.as_slice(), i) + })) + }).collect(); + occ_freqs = OCCURRENCES.iter().map(|&occ| { + let input = (*input_ptr).clone(); + Future::spawn(proc() { + generate_frequencies(input.as_slice(), occ.len()) + }) + }).collect(); + } for (i, freq) in nb_freqs.move_iter() { print_frequencies(&freq.unwrap(), i); diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index ab3f6892bb8af..48d100c828ac3 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -168,10 +168,16 @@ fn is_board_unfeasible(board: u64, masks: &Vec>>) -> bool { fn filter_masks(masks: &mut Vec>>) { for i in range(0, masks.len()) { for j in range(0, masks.get(i).len()) { - *masks.get_mut(i).get_mut(j) = - masks.get(i).get(j).iter().map(|&m| m) - .filter(|&m| !is_board_unfeasible(m, masks)) - .collect(); + let mut result = Vec::new(); + { + let array = masks.get(i).get(j); + for &value in array.iter() { + if !is_board_unfeasible(value, masks) { + result.push(value) + } + } + } + *masks.get_mut(i).get_mut(j) = result } } } diff --git a/src/test/compile-fail/borrowck-assign-comp-idx.rs b/src/test/compile-fail/borrowck-assign-comp-idx.rs index 143ebdaa77399..facdf2c5bc076 100644 --- a/src/test/compile-fail/borrowck-assign-comp-idx.rs +++ b/src/test/compile-fail/borrowck-assign-comp-idx.rs @@ -26,17 +26,6 @@ fn a() { fn borrow(_x: &[int], _f: ||) {} -fn b() { - // here we alias the mutable vector into an imm slice and try to - // modify the original: - - let mut p = vec!(1); - - borrow( - p.as_slice(), - || *p.get_mut(0) = 5); //~ ERROR cannot borrow `p` as mutable -} - fn c() { // Legal because the scope of the borrow does not include the // modification: diff --git a/src/test/compile-fail/borrowck-autoref-3261.rs b/src/test/compile-fail/borrowck-autoref-3261.rs index 2a2a3dee1dfa6..8f1cfcce74559 100644 --- a/src/test/compile-fail/borrowck-autoref-3261.rs +++ b/src/test/compile-fail/borrowck-autoref-3261.rs @@ -21,11 +21,12 @@ impl X { fn main() { let mut x = X(Right(main)); - (&mut x).with( - |opt| { //~ ERROR cannot borrow `x` as mutable more than once at a time + let x_ptr = &mut x; + x_ptr.with( + |opt| { //~ ERROR closure requires unique access match opt { &Right(ref f) => { - x = X(Left((0,0))); + *x_ptr = X(Left((0,0))); //~ ERROR cannot move `x_ptr` (*f)() }, _ => fail!() diff --git a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs index 002ae5a7d28b4..fc798a014f3f3 100644 --- a/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs +++ b/src/test/compile-fail/borrowck-call-is-borrow-issue-12224.rs @@ -19,8 +19,8 @@ struct Test<'a> { fn call(f: |Fn|) { f(|| { - //~^ ERROR: closure requires unique access to `f` but it is already borrowed f(|| {}) + //~^ ERROR: cannot move `f` into closure }); } @@ -56,8 +56,9 @@ fn test6() { fn test7() { fn foo(_: |g: |int|, b: int|) {} let f = |g: |int|, b: int| {}; - f(|a| { //~ ERROR: cannot borrow `f` as immutable because previous closure - foo(f); //~ ERROR: cannot move out of captured outer variable + f(|a| { + foo(f); //~ ERROR: cannot move `f` + //~^ ERROR cannot move out of captured outer variable }, 3); } diff --git a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck-closures-mut-and-imm.rs deleted file mode 100644 index ce8b17ea40bc6..0000000000000 --- a/src/test/compile-fail/borrowck-closures-mut-and-imm.rs +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that two closures cannot simultaneously have mutable -// and immutable access to the variable. Issue #6801. - - -fn get(x: &int) -> int { - *x -} - -fn set(x: &mut int) { - *x = 4; -} - -fn a() { - let mut x = 3; - let c1 = || x = 4; - let c2 = || x * 5; //~ ERROR cannot borrow `x` -} - -fn b() { - let mut x = 3; - let c1 = || set(&mut x); - let c2 = || get(&x); //~ ERROR cannot borrow `x` -} - -fn c() { - let mut x = 3; - let c1 = || set(&mut x); - let c2 = || x * 5; //~ ERROR cannot borrow `x` -} - -fn d() { - let mut x = 3; - let c2 = || x * 5; - x = 5; //~ ERROR cannot assign -} - -fn e() { - let mut x = 3; - let c1 = || get(&x); - x = 5; //~ ERROR cannot assign -} - -fn f() { - let mut x = box 3; - let c1 = || get(&*x); - *x = 5; //~ ERROR cannot assign -} - -fn g() { - struct Foo { - f: Box - } - - let mut x = box Foo { f: box 3 }; - let c1 = || get(&*x.f); - *x.f = 5; //~ ERROR cannot assign to `*x.f` -} - -fn h() { - struct Foo { - f: Box - } - - let mut x = box Foo { f: box 3 }; - let c1 = || get(&*x.f); - let c2 = || *x.f = 5; //~ ERROR cannot borrow `x` as mutable -} - -fn main() { -} diff --git a/src/test/compile-fail/borrowck-closures-mut-of-imm.rs b/src/test/compile-fail/borrowck-closures-mut-of-imm.rs deleted file mode 100644 index cdfb569762de3..0000000000000 --- a/src/test/compile-fail/borrowck-closures-mut-of-imm.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that two closures cannot simultaneously have mutable -// and immutable access to the variable. Issue #6801. - -fn get(x: &int) -> int { - *x -} - -fn set(x: &mut int) { - *x = 4; -} - -fn a(x: &int) { - let c1 = || set(&mut *x); - //~^ ERROR cannot borrow - let c2 = || set(&mut *x); - //~^ ERROR closure requires unique access to `x` - //~^^ ERROR cannot borrow -} - -fn main() { -} diff --git a/src/test/compile-fail/borrowck-closures-two-mut.rs b/src/test/compile-fail/borrowck-closures-two-mut.rs deleted file mode 100644 index e1967d4e6df94..0000000000000 --- a/src/test/compile-fail/borrowck-closures-two-mut.rs +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Tests that two closures cannot simultaneously have mutable -// access to the variable, whether that mutable access be used -// for direct assignment or for taking mutable ref. Issue #6801. - - -fn a() { - let mut x = 3; - let c1 = || x = 4; - let c2 = || x = 5; //~ ERROR cannot borrow `x` as mutable more than once -} - -fn set(x: &mut int) { - *x = 4; -} - -fn b() { - let mut x = 3; - let c1 = || set(&mut x); - let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once -} - -fn c() { - let mut x = 3; - let c1 = || x = 5; - let c2 = || set(&mut x); //~ ERROR cannot borrow `x` as mutable more than once -} - -fn d() { - let mut x = 3; - let c1 = || x = 5; - let c2 = || { let _y = || set(&mut x); }; // (nested closure) - //~^ ERROR cannot borrow `x` as mutable more than once -} - -fn g() { - struct Foo { - f: Box - } - - let mut x = box Foo { f: box 3 }; - let c1 = || set(&mut *x.f); - let c2 = || set(&mut *x.f); - //~^ ERROR cannot borrow `x` as mutable more than once -} - -fn main() { -} diff --git a/src/test/compile-fail/borrowck-closures-unique.rs b/src/test/compile-fail/borrowck-closures-unique.rs index 80d942e58d15c..3ff8fc71455c6 100644 --- a/src/test/compile-fail/borrowck-closures-unique.rs +++ b/src/test/compile-fail/borrowck-closures-unique.rs @@ -24,26 +24,8 @@ fn set(x: &mut int) -> int { fn a(x: &mut int) { let c1 = || get(x); - let c2 = || get(x); -} - -fn b(x: &mut int) { - let c1 = || get(x); - let c2 = || set(x); //~ ERROR closure requires unique access to `x` -} - -fn c(x: &mut int) { - let c1 = || get(x); - let c2 = || { get(x); set(x); }; //~ ERROR closure requires unique access to `x` -} - -fn d(x: &mut int) { - let c1 = || set(x); - let c2 = || set(x); //~ ERROR closure requires unique access to `x` -} - -fn e(x: &mut int) { - let c1: || = || x = fail!(); //~ ERROR closure cannot assign to immutable argument `x` + let c2 = || get(x); //~ ERROR closure requires unique access to `*x` + //~^ ERROR cannot move `x` } fn main() { diff --git a/src/test/compile-fail/borrowck-closures-use-after-free.rs b/src/test/compile-fail/borrowck-closures-use-after-free.rs index ec31160f0d535..9cab8c4f2d829 100644 --- a/src/test/compile-fail/borrowck-closures-use-after-free.rs +++ b/src/test/compile-fail/borrowck-closures-use-after-free.rs @@ -25,8 +25,11 @@ impl Drop for Foo { fn main() { let mut ptr = box Foo { x: 0 }; + let ptr_ref = &mut ptr; let test = |foo: &Foo| { - ptr = box Foo { x: ptr.x + 1 }; + *ptr_ref = box Foo { + x: ptr_ref.x + 1, + }; }; test(ptr); //~ ERROR cannot borrow `*ptr` } diff --git a/src/test/compile-fail/borrowck-insert-during-each.rs b/src/test/compile-fail/borrowck-insert-during-each.rs index b478117148745..f214af8b07c5f 100644 --- a/src/test/compile-fail/borrowck-insert-during-each.rs +++ b/src/test/compile-fail/borrowck-insert-during-each.rs @@ -25,8 +25,8 @@ impl Foo { fn bar(f: &mut Foo) { f.foo( - |a| { //~ ERROR closure requires unique access to `f` - f.n.insert(*a); + |a| { //~ ERROR closure requires unique access to `*f` + f.n.insert(*a); //~ ERROR cannot move `f` }) } diff --git a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs index c11a08b254f1c..973f201363599 100644 --- a/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs +++ b/src/test/compile-fail/borrowck-loan-blocks-mut-uniq.rs @@ -14,10 +14,11 @@ fn borrow(v: &int, f: |x: &int|) { fn box_imm() { let mut v = box 3; - borrow(v, - |w| { //~ ERROR cannot borrow `v` as mutable - v = box 4; - assert_eq!(*v, 3); + let v_ptr = &mut v; + borrow(*v_ptr, + |w| { //~ ERROR closure requires unique access to `*v_ptr` + *v_ptr = box 4; //~ ERROR cannot move `v_ptr` + assert_eq!(**v_ptr, 3); assert_eq!(*w, 4); }) } diff --git a/src/test/compile-fail/borrowck-loan-rcvr.rs b/src/test/compile-fail/borrowck-loan-rcvr.rs index 2461f1ab39604..cc99bfbec5dd5 100644 --- a/src/test/compile-fail/borrowck-loan-rcvr.rs +++ b/src/test/compile-fail/borrowck-loan-rcvr.rs @@ -32,8 +32,9 @@ fn a() { p.impurem(); // But in this case we do not honor the loan: - p.blockm(|| { //~ ERROR cannot borrow `p` as mutable - p.x = 10; + p.blockm(|| { + p.x = 10; //~ ERROR cannot move `p` into closure + //~^ ERROR cannot assign to immutable field }) } diff --git a/src/test/compile-fail/borrowck-loan-vec-content.rs b/src/test/compile-fail/borrowck-loan-vec-content.rs index 393b528869a94..e779f0e21800c 100644 --- a/src/test/compile-fail/borrowck-loan-vec-content.rs +++ b/src/test/compile-fail/borrowck-loan-vec-content.rs @@ -25,8 +25,9 @@ fn has_mut_vec_but_tries_to_change_it() { let mut v = vec!(1, 2, 3); takes_imm_elt( v.get(0), - || { //~ ERROR cannot borrow `v` as mutable - *v.get_mut(1) = 4; + || { + *v.get_mut(1) = 4; //~ ERROR cannot move `v` + //~^ ERROR cannot borrow }) } diff --git a/src/test/compile-fail/borrowck-preserve-box-in-field.rs b/src/test/compile-fail/borrowck-preserve-box-in-field.rs index 68410ae4fe196..8083ddfcdbf19 100644 --- a/src/test/compile-fail/borrowck-preserve-box-in-field.rs +++ b/src/test/compile-fail/borrowck-preserve-box-in-field.rs @@ -25,11 +25,11 @@ struct F { f: Box } pub fn main() { let mut x = @F {f: box 3}; borrow(x.f, |b_x| { - //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); - //~^ NOTE borrow occurs due to use of `x` in closure + //~^ ERROR cannot move `x` into closure x = @F {f: box 4}; + //~^ ERROR cannot assign println!("&*b_x = {:p}", &(*b_x)); assert_eq!(*b_x, 3); diff --git a/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs b/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs index 0db097ec003c2..49f1b5dedd96d 100644 --- a/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs +++ b/src/test/compile-fail/borrowck-preserve-box-in-uniq.rs @@ -25,11 +25,11 @@ struct F { f: Box } pub fn main() { let mut x = box @F{f: box 3}; borrow(x.f, |b_x| { - //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); - //~^ NOTE borrow occurs due to use of `x` in closure + //~^ ERROR cannot move `x` into closure *x = @F{f: box 4}; + //~^ ERROR cannot assign to immutable dereference println!("&*b_x = {:p}", &(*b_x)); assert_eq!(*b_x, 3); diff --git a/src/test/compile-fail/borrowck-preserve-box.rs b/src/test/compile-fail/borrowck-preserve-box.rs index cd36d93060462..8f58c19627970 100644 --- a/src/test/compile-fail/borrowck-preserve-box.rs +++ b/src/test/compile-fail/borrowck-preserve-box.rs @@ -22,11 +22,11 @@ fn borrow(x: &int, f: |x: &int|) { pub fn main() { let mut x = @3; borrow(x, |b_x| { - //~^ ERROR cannot borrow `x` as mutable because `*x` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x) as *int, &(*b_x) as *int); - //~^ NOTE borrow occurs due to use of `x` in closure + //~^ ERROR cannot move `x` into closure x = @22; + //~^ ERROR cannot assign to immutable captured outer variable println!("&*b_x = {:p}", &(*b_x)); assert_eq!(*b_x, 3); diff --git a/src/test/compile-fail/borrowck-preserve-expl-deref.rs b/src/test/compile-fail/borrowck-preserve-expl-deref.rs index ca24192e797e2..249f8e5ef7c30 100644 --- a/src/test/compile-fail/borrowck-preserve-expl-deref.rs +++ b/src/test/compile-fail/borrowck-preserve-expl-deref.rs @@ -25,11 +25,11 @@ struct F { f: Box } pub fn main() { let mut x = @F {f: box 3}; borrow((*x).f, |b_x| { - //~^ ERROR cannot borrow `x` as mutable because `*x.f` is also borrowed as immutable assert_eq!(*b_x, 3); assert_eq!(&(*x.f) as *int, &(*b_x) as *int); - //~^ NOTE borrow occurs due to use of `x` in closure + //~^ ERROR cannot move `x` into closure x = @F {f: box 4}; + //~^ ERROR cannot assign to immutable captured outer variable println!("&*b_x = {:p}", &(*b_x)); assert_eq!(*b_x, 3); diff --git a/src/test/compile-fail/issue-11192.rs b/src/test/compile-fail/issue-11192.rs index e7fa8300bcb69..73351270ab47f 100644 --- a/src/test/compile-fail/issue-11192.rs +++ b/src/test/compile-fail/issue-11192.rs @@ -23,9 +23,10 @@ fn main() { let test = |foo: &Foo| { println!("access {}", foo.x); ptr = box Foo { x: ptr.x + 1 }; + //~^ ERROR cannot assign to immutable captured outer variable println!("access {}", foo.x); }; test(ptr); - //~^ ERROR: cannot borrow `*ptr` as immutable + //~^ ERROR use of moved value } diff --git a/src/test/compile-fail/issue-11873.rs b/src/test/compile-fail/issue-11873.rs index 0ca326c1e0d9f..168781ba09ee7 100644 --- a/src/test/compile-fail/issue-11873.rs +++ b/src/test/compile-fail/issue-11873.rs @@ -11,7 +11,8 @@ fn main() { let mut v = vec!(1); let f = || v.push(2); - let _w = v; //~ ERROR: cannot move out of `v` + //~^ ERROR cannot borrow immutable captured outer variable + let _w = v; //~ ERROR: use of moved value f(); } diff --git a/src/test/compile-fail/issue-6801.rs b/src/test/compile-fail/issue-6801.rs index 5925f6869391a..4db74e24ab458 100644 --- a/src/test/compile-fail/issue-6801.rs +++ b/src/test/compile-fail/issue-6801.rs @@ -25,6 +25,6 @@ fn main() { let x : Box = box 9; let sq : || -> uint = || { *x * *x }; - twice(x); //~ ERROR: cannot move out of + twice(x); //~ ERROR use of moved value invoke(sq); } diff --git a/src/test/compile-fail/lint-unused-mut-variables.rs b/src/test/compile-fail/lint-unused-mut-variables.rs index 671fecc4e22e7..08c809d9a477d 100644 --- a/src/test/compile-fail/lint-unused-mut-variables.rs +++ b/src/test/compile-fail/lint-unused-mut-variables.rs @@ -45,9 +45,12 @@ fn main() { let mut a = Vec::new(); a.push(3); let mut a = Vec::new(); - callback(|| { - a.push(3); - }); + { + let a_ptr = &mut a; + callback(|| { + a_ptr.push(3); + }); + } let (mut a, b) = (1, 2); a = 34; diff --git a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs b/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs deleted file mode 100644 index aded89e5820ae..0000000000000 --- a/src/test/compile-fail/moves-based-on-type-no-recursive-stack-closure.rs +++ /dev/null @@ -1,47 +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. - -// Tests correct kind-checking of the reason stack closures without the :Copy -// bound must be noncopyable. For details see -// http://smallcultfollowing.com/babysteps/blog/2013/04/30/the-case-of-the-recurring-closure/ - -extern crate debug; - -struct R<'a> { - // This struct is needed to create the - // otherwise infinite type of a fn that - // accepts itself as argument: - c: |&mut R, bool|: 'a -} - -fn innocent_looking_victim() { - let mut x = Some("hello".to_string()); - conspirator(|f, writer| { - if writer { - x = None; - } else { - match x { - Some(ref msg) => { - (f.c)(f, true); - //~^ ERROR: cannot borrow `*f` as mutable because - println!("{:?}", msg); - }, - None => fail!("oops"), - } - } - }) -} - -fn conspirator(f: |&mut R, bool|) { - let mut r = R {c: f}; - f(&mut r, false) //~ ERROR use of moved value -} - -fn main() { innocent_looking_victim() } diff --git a/src/test/compile-fail/regions-creating-enums.rs b/src/test/compile-fail/regions-creating-enums.rs deleted file mode 100644 index 4fd3cd2704437..0000000000000 --- a/src/test/compile-fail/regions-creating-enums.rs +++ /dev/null @@ -1,43 +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. - -enum ast<'a> { - num(uint), - add(&'a ast<'a>, &'a ast<'a>) -} - -fn build() { - let x = num(3u); - let y = num(4u); - let z = add(&x, &y); - compute(&z); -} - -fn compute(x: &ast) -> uint { - match *x { - num(x) => { x } - add(x, y) => { compute(x) + compute(y) } - } -} - -fn map_nums(x: &ast, f: |uint| -> uint) -> &ast { - match *x { - num(x) => { - return &num(f(x)); //~ ERROR borrowed value does not live long enough - } - add(x, y) => { - let m_x = map_nums(x, |z| f(z)); - let m_y = map_nums(y, |z| f(z)); - return &add(m_x, m_y); //~ ERROR borrowed value does not live long enough - } - } -} - -fn main() {} diff --git a/src/test/compile-fail/regions-nested-fns-2.rs b/src/test/compile-fail/regions-nested-fns-2.rs deleted file mode 100644 index 60eae9ce80af1..0000000000000 --- a/src/test/compile-fail/regions-nested-fns-2.rs +++ /dev/null @@ -1,21 +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 ignore(_f: <'z>|&'z int| -> &'z int) {} - -fn nested() { - let y = 3; - ignore( - |z| { //~ ERROR `y` does not live long enough - if false { &y } else { z } - }); -} - -fn main() {} diff --git a/src/test/compile-fail/regions-steal-closure.rs b/src/test/compile-fail/regions-steal-closure.rs index 7ffc6a75cff8c..b16d520fb2368 100644 --- a/src/test/compile-fail/regions-steal-closure.rs +++ b/src/test/compile-fail/regions-steal-closure.rs @@ -19,7 +19,8 @@ fn box_it<'r>(x: ||: 'r) -> closure_box<'r> { fn main() { let cl_box = { let mut i = 3; - box_it(|| i += 1) //~ ERROR cannot infer + let i_ptr = &mut i; //~ ERROR `i` does not live long enough + box_it(|| *i_ptr += 1) }; (cl_box.cl)(); } diff --git a/src/test/run-pass/argument-passing.rs b/src/test/run-pass/argument-passing.rs index 75e197923c635..c1d481e83969a 100644 --- a/src/test/run-pass/argument-passing.rs +++ b/src/test/run-pass/argument-passing.rs @@ -29,6 +29,9 @@ pub fn main() { assert_eq!(f1(&mut a, &mut b, c), 6); assert_eq!(a.x, 0); assert_eq!(b, 10); - assert_eq!(f2(a.x, |_| a.x = 50), 0); + { + let a_ptr = &mut a; + assert_eq!(f2(a_ptr.x, |_| a_ptr.x = 50), 0); + } assert_eq!(a.x, 50); } diff --git a/src/test/run-pass/assignability-trait.rs b/src/test/run-pass/assignability-trait.rs index dddec5a56249b..55e4c0adc5db6 100644 --- a/src/test/run-pass/assignability-trait.rs +++ b/src/test/run-pass/assignability-trait.rs @@ -31,17 +31,24 @@ impl iterable for Vec { fn length>(x: T) -> uint { let mut len = 0; + let len_ptr = &mut len; x.iterate(|_y| { - len += 1; + *len_ptr += 1; true }); - return len; + return *len_ptr; } pub fn main() { let x: Vec = vec!(0,1,2,3); // Call a method - x.iterate(|y| { assert!(*x.get(*y as uint) == *y); true }); + { + let x_ptr = &x; + x_ptr.iterate(|y| { + assert!(*x_ptr.get(*y as uint) == *y); + true + }); + } // Call a parameterized function assert_eq!(length(x.clone()), x.len()); // Call a parameterized function, with type arguments that require @@ -51,7 +58,13 @@ pub fn main() { // Now try it with a type that *needs* to be borrowed let z = [0,1,2,3]; // Call a method - z.iterate(|y| { assert!(z[*y as uint] == *y); true }); + { + let z_ptr = &z; + z_ptr.iterate(|y| { + assert!((*z_ptr)[*y as uint] == *y); + true + }); + } // Call a parameterized function assert_eq!(length::(z), z.len()); } diff --git a/src/test/run-pass/block-iter-1.rs b/src/test/run-pass/block-iter-1.rs index 4f0cf855dd11f..cfb42846b8c86 100644 --- a/src/test/run-pass/block-iter-1.rs +++ b/src/test/run-pass/block-iter-1.rs @@ -15,11 +15,12 @@ fn iter_vec(v: Vec , f: |&T|) { for x in v.iter() { f(x); } } pub fn main() { let v = vec!(1, 2, 3, 4, 5, 6, 7); let mut odds = 0; + let odds_ptr = &mut odds; iter_vec(v, |i| { if *i % 2 == 1 { - odds += 1; + *odds_ptr += 1; } }); - println!("{:?}", odds); - assert_eq!(odds, 4); + println!("{:?}", *odds_ptr); + assert_eq!(*odds_ptr, 4); } diff --git a/src/test/run-pass/block-iter-2.rs b/src/test/run-pass/block-iter-2.rs index 8d28022bc1df6..01a22e04db023 100644 --- a/src/test/run-pass/block-iter-2.rs +++ b/src/test/run-pass/block-iter-2.rs @@ -15,11 +15,12 @@ fn iter_vec(v: Vec , f: |&T|) { for x in v.iter() { f(x); } } pub fn main() { let v = vec!(1, 2, 3, 4, 5); let mut sum = 0; + let sum_ptr = &mut sum; iter_vec(v.clone(), |i| { iter_vec(v.clone(), |j| { - sum += *i * *j; + *sum_ptr += *i * *j; }); }); - println!("{:?}", sum); - assert_eq!(sum, 225); + println!("{:?}", *sum_ptr); + assert_eq!(*sum_ptr, 225); } diff --git a/src/test/run-pass/foreach-nested.rs b/src/test/run-pass/foreach-nested.rs index 357d1201a4cbb..9d2a673c70831 100644 --- a/src/test/run-pass/foreach-nested.rs +++ b/src/test/run-pass/foreach-nested.rs @@ -14,9 +14,16 @@ fn two(it: |int|) { it(0); it(1); } pub fn main() { let mut a: Vec = vec!(-1, -1, -1, -1); let mut p: int = 0; - two(|i| { - two(|j| { *a.get_mut(p as uint) = 10 * i + j; p += 1; }) - }); + { + let a_ptr = &mut a; + let p_ptr = &mut p; + two(|i| { + two(|j| { + *a_ptr.get_mut(*p_ptr as uint) = 10 * i + j; + *p_ptr += 1; + }) + }); + } assert_eq!(*a.get(0), 0); assert_eq!(*a.get(1), 1); assert_eq!(*a.get(2), 10); diff --git a/src/test/run-pass/foreach-put-structured.rs b/src/test/run-pass/foreach-put-structured.rs index 7a728e18a2901..ba684e21281b6 100644 --- a/src/test/run-pass/foreach-put-structured.rs +++ b/src/test/run-pass/foreach-put-structured.rs @@ -19,13 +19,17 @@ fn pairs(it: |(int, int)|) { pub fn main() { let mut i: int = 10; let mut j: int = 0; - pairs(|p| { - let (_0, _1) = p; - println!("{}", _0); - println!("{}", _1); - assert_eq!(_0 + 10, i); - i += 1; - j = _1; - }); + { + let i_ptr = &mut i; + let j_ptr = &mut j; + pairs(|p| { + let (_0, _1) = p; + println!("{}", _0); + println!("{}", _1); + assert_eq!(_0 + 10, *i_ptr); + *i_ptr += 1; + *j_ptr = _1; + }); + } assert_eq!(j, 45); } diff --git a/src/test/run-pass/foreach-simple-outer-slot.rs b/src/test/run-pass/foreach-simple-outer-slot.rs index bb726773bb5db..d4ef946f26a70 100644 --- a/src/test/run-pass/foreach-simple-outer-slot.rs +++ b/src/test/run-pass/foreach-simple-outer-slot.rs @@ -13,10 +13,15 @@ pub fn main() { let mut sum: int = 0; - first_ten(|i| { println!("main"); println!("{}", i); sum = sum + i; }); + let sum_ptr = &mut sum; + first_ten(|i| { + println!("main"); + println!("{}", i); + *sum_ptr = *sum_ptr + i; + }); println!("sum"); - println!("{}", sum); - assert_eq!(sum, 45); + println!("{}", *sum_ptr); + assert_eq!(*sum_ptr, 45); } fn first_ten(it: |int|) { diff --git a/src/test/run-pass/hashmap-memory.rs b/src/test/run-pass/hashmap-memory.rs index e64ef3def2db7..734a954d94abf 100644 --- a/src/test/run-pass/hashmap-memory.rs +++ b/src/test/run-pass/hashmap-memory.rs @@ -45,6 +45,7 @@ mod map_reduce { fn map_task(ctrl: Sender, input: String) { let mut intermediates = HashMap::new(); + let intermediates_ptr = &mut intermediates; fn emit(im: &mut HashMap, ctrl: Sender, key: String, @@ -62,7 +63,7 @@ mod map_reduce { } let ctrl_clone = ctrl.clone(); - ::map(input, |a,b| emit(&mut intermediates, ctrl.clone(), a, b) ); + ::map(input, |a,b| emit(intermediates_ptr, ctrl.clone(), a, b) ); ctrl_clone.send(mapper_done); } diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index b69450024f656..7cb8bb70ed60a 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -196,10 +196,13 @@ fn test_print() { fn test_format_args() { let mut buf = MemWriter::new(); { - let w = &mut buf as &mut io::Writer; - format_args!(|args| { write!(w, "{}", args); }, "{}", 1); - format_args!(|args| { write!(w, "{}", args); }, "test"); - format_args!(|args| { write!(w, "{}", args); }, "{test}", test=3); + let mut w = &mut buf as &mut io::Writer; + let w_ptr = &mut w; + format_args!(|args| { write!(*w_ptr, "{}", args); }, "{}", 1); + format_args!(|args| { write!(*w_ptr, "{}", args); }, "test"); + format_args!(|args| { + write!(*w_ptr, "{}", args); + }, "{test}", test=3); } let s = str::from_utf8(buf.unwrap().as_slice()).unwrap().to_string(); t!(s, "1test3"); diff --git a/src/test/run-pass/iter-range.rs b/src/test/run-pass/iter-range.rs index 794c4f4016e62..e57b268e8a7c4 100644 --- a/src/test/run-pass/iter-range.rs +++ b/src/test/run-pass/iter-range.rs @@ -18,6 +18,7 @@ fn range_(a: int, b: int, it: |int|) { pub fn main() { let mut sum: int = 0; - range_(0, 100, |x| sum += x ); - println!("{}", sum); + let sum_ptr = &mut sum; + range_(0, 100, |x| *sum_ptr += x ); + println!("{}", *sum_ptr); } diff --git a/src/test/run-pass/lambda-infer-unresolved.rs b/src/test/run-pass/lambda-infer-unresolved.rs index 190d25015840c..c32c45bc6cc6d 100644 --- a/src/test/run-pass/lambda-infer-unresolved.rs +++ b/src/test/run-pass/lambda-infer-unresolved.rs @@ -16,7 +16,10 @@ struct Refs { refs: Vec , n: int } pub fn main() { let mut e = Refs{refs: vec!(), n: 0}; - let _f: || = || println!("{}", e.n); + { + let e_ptr = &mut e; + let _f: || = || println!("{}", e_ptr.n); + } let x: &[int] = e.refs.as_slice(); assert_eq!(x.len(), 0); } diff --git a/src/test/run-pass/regions-copy-closure.rs b/src/test/run-pass/regions-copy-closure.rs index ac40fb885a134..5ff16adc1a257 100644 --- a/src/test/run-pass/regions-copy-closure.rs +++ b/src/test/run-pass/regions-copy-closure.rs @@ -20,7 +20,8 @@ pub fn main() { let mut i = 3; assert_eq!(i, 3); { - let cl = || i += 1; + let i_ptr = &mut i; + let cl = || *i_ptr += 1; let cl_box = box_it(cl); (cl_box.cl)(); } diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs index 1545de93786ee..1ecd532002da9 100644 --- a/src/test/run-pass/static-impl.rs +++ b/src/test/run-pass/static-impl.rs @@ -67,6 +67,7 @@ pub fn main() { let vect = (vec!(3, 4)).map_::(|a| *a as uint + 4u); assert_eq!(*vect.get(0), 7u); let mut x = 0u; - 10u.multi(|_n| x += 2u ); - assert_eq!(x, 20u); + let x_ptr = &mut x; + 10u.multi(|_n| *x_ptr += 2u ); + assert_eq!(*x_ptr, 20u); } diff --git a/src/test/run-pass/vector-sort-failure-safe.rs b/src/test/run-pass/vector-sort-failure-safe.rs index 00bc95b36f7a7..04060b7e00f61 100644 --- a/src/test/run-pass/vector-sort-failure-safe.rs +++ b/src/test/run-pass/vector-sort-failure-safe.rs @@ -51,7 +51,12 @@ pub fn main() { // work out the total number of comparisons required to sort // this array... let mut count = 0; - main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) }); + { + let count_ptr = &mut count; + main.clone() + .as_mut_slice() + .sort_by(|a, b| { *count_ptr += 1; a.cmp(b) }); + } // ... and then fail on each and every single one. for fail_countdown in range(0, count) { @@ -66,11 +71,12 @@ pub fn main() { task::try(proc() { let mut v = v; let mut fail_countdown = fail_countdown; + let fail_countdown_ptr = &mut fail_countdown; v.as_mut_slice().sort_by(|a, b| { - if fail_countdown == 0 { + if *fail_countdown_ptr == 0 { fail!() } - fail_countdown -= 1; + *fail_countdown_ptr -= 1; a.cmp(b) }) });