Skip to content

Commit 42b37e7

Browse files
committed
---
yaml --- r: 172799 b: refs/heads/try c: d71a68a h: refs/heads/master i: 172797: 7939c69 172795: f07bc52 172791: adbc226 172783: 38205fc 172767: 7770fd9 172735: a96101b 172671: 39ed06c 172543: fb12dff v: v3
1 parent fec3465 commit 42b37e7

File tree

22 files changed

+453
-136
lines changed

22 files changed

+453
-136
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: 170c4399e614fe599c3d41306b3429ca8b3b68c6
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 5b3cd3900ceda838f5798c30ab96ceb41f962534
5-
refs/heads/try: 4c78d2834446426b2dd3cc467f1324dacdc9042e
5+
refs/heads/try: d71a68ae23773e5faaaf88b68b5963288b2cc5ad
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
88
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596

branches/try/src/doc/trpl/closures.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -110,25 +110,27 @@ passing two variables: one is an i32, and one is a function."
110110
Next, let's look at how `twice` is defined:
111111

112112
```{rust,ignore}
113-
fn twice(x: i32, f: |i32| -> i32) -> i32 {
113+
fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
114114
```
115115

116116
`twice` takes two arguments, `x` and `f`. That's why we called it with two
117117
arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
118-
though, and that function takes an `i32` and returns an `i32`. Notice
119-
how the `|i32| -> i32` syntax looks a lot like our definition of `square`
120-
above, if we added the return type in:
121-
122-
```{rust}
123-
let square = |&: x: i32| -> i32 { x * x };
124-
// |i32| -> i32
125-
```
126-
127-
This function takes an `i32` and returns an `i32`.
118+
though, and that function takes an `i32` and returns an `i32`. This is
119+
what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
120+
You might ask yourself: why do we need to introduce a type parameter here?
121+
That is because in Rust each closure has its own unique type.
122+
So, not only do closures with different signatures have different types,
123+
but different closures with the *same* signature have *different* types!
124+
You can think of it this way: the behaviour of a closure is part of its type.
125+
And since we want to support many different closures that all take
126+
an `i32` and return an `i32` we introduced a type parameter that is able
127+
to represent all these closures.
128128

129129
This is the most complicated function signature we've seen yet! Give it a read
130130
a few times until you can see how it works. It takes a teeny bit of practice, and
131-
then it's easy.
131+
then it's easy. The good news is that this kind of passing a closure around
132+
can be very efficient. With all the type information available at compile-time
133+
the compiler can do wonders.
132134

133135
Finally, `twice` returns an `i32` as well.
134136

branches/try/src/doc/trpl/error-handling.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
% Error Handling in Rust
22

3-
> The best-laid plans of mice and men
3+
> The best-laid plans of mice and men
44
> Often go awry
55
>
66
> "Tae a Moose", Robert Burns

branches/try/src/libcollections/dlist.rs

Lines changed: 161 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,12 @@ impl<T> DList<T> {
221221
DList{list_head: None, list_tail: Rawlink::none(), length: 0}
222222
}
223223

224-
/// Adds all elements from `other` to the end of the list.
224+
/// Moves all elements from `other` to the end of the list.
225225
///
226-
/// This operation should compute in O(1) time.
226+
/// This reuses all the nodes from `other` and moves them into `self`. After
227+
/// this operation, `other` becomes empty.
228+
///
229+
/// This operation should compute in O(1) time and O(1) memory.
227230
///
228231
/// # Examples
229232
///
@@ -237,16 +240,20 @@ impl<T> DList<T> {
237240
/// b.push_back(3i);
238241
/// b.push_back(4);
239242
///
240-
/// a.append(b);
243+
/// a.append(&mut b);
241244
///
242245
/// for e in a.iter() {
243246
/// println!("{}", e); // prints 1, then 2, then 3, then 4
244247
/// }
248+
/// println!("{}", b.len()); // prints 0
245249
/// ```
246-
#[unstable = "append should be by-mutable-reference"]
247-
pub fn append(&mut self, mut other: DList<T>) {
250+
pub fn append(&mut self, other: &mut DList<T>) {
248251
match self.list_tail.resolve() {
249-
None => *self = other,
252+
None => {
253+
self.length = other.length;
254+
self.list_head = other.list_head.take();
255+
self.list_tail = other.list_tail.take();
256+
},
250257
Some(tail) => {
251258
// Carefully empty `other`.
252259
let o_tail = other.list_tail.take();
@@ -261,6 +268,7 @@ impl<T> DList<T> {
261268
}
262269
}
263270
}
271+
other.length = 0;
264272
}
265273

266274
/// Provides a forward iterator.
@@ -404,6 +412,51 @@ impl<T> DList<T> {
404412
pub fn pop_back(&mut self) -> Option<T> {
405413
self.pop_back_node().map(|box Node{value, ..}| value)
406414
}
415+
416+
/// Splits the list into two at the given index. Returns everything after the given index,
417+
/// including the index.
418+
///
419+
/// This operation should compute in O(n) time.
420+
#[stable]
421+
pub fn split_off(&mut self, at: uint) -> DList<T> {
422+
let len = self.len();
423+
assert!(at < len, "Cannot split off at a nonexistent index");
424+
if at == 0 {
425+
return mem::replace(self, DList::new());
426+
}
427+
428+
// Below, we iterate towards the `i-1`th node, either from the start or the end,
429+
// depending on which would be faster.
430+
let mut split_node = if at - 1 <= len - 1 - (at - 1) {
431+
let mut iter = self.iter_mut();
432+
// instead of skipping using .skip() (which creates a new struct),
433+
// we skip manually so we can access the head field without
434+
// depending on implementation details of Skip
435+
for _ in range(0, at - 1) {
436+
iter.next();
437+
}
438+
iter.head
439+
} else {
440+
// better off starting from the end
441+
let mut iter = self.iter_mut();
442+
for _ in range(0, len - 1 - (at - 1)) {
443+
iter.next_back();
444+
}
445+
iter.tail
446+
};
447+
448+
let mut splitted_list = DList {
449+
list_head: None,
450+
list_tail: self.list_tail,
451+
length: len - at
452+
};
453+
454+
mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
455+
self.list_tail = split_node;
456+
self.length = at;
457+
458+
splitted_list
459+
}
407460
}
408461

409462
#[unsafe_destructor]
@@ -777,6 +830,108 @@ mod tests {
777830
v.iter().map(|x| (*x).clone()).collect()
778831
}
779832

833+
#[test]
834+
fn test_append() {
835+
// Empty to empty
836+
{
837+
let mut m: DList<int> = DList::new();
838+
let mut n = DList::new();
839+
m.append(&mut n);
840+
check_links(&m);
841+
assert_eq!(m.len(), 0);
842+
assert_eq!(n.len(), 0);
843+
}
844+
// Non-empty to empty
845+
{
846+
let mut m = DList::new();
847+
let mut n = DList::new();
848+
n.push_back(2i);
849+
m.append(&mut n);
850+
check_links(&m);
851+
assert_eq!(m.len(), 1);
852+
assert_eq!(m.pop_back(), Some(2));
853+
assert_eq!(n.len(), 0);
854+
check_links(&m);
855+
}
856+
// Empty to non-empty
857+
{
858+
let mut m = DList::new();
859+
let mut n = DList::new();
860+
m.push_back(2i);
861+
m.append(&mut n);
862+
check_links(&m);
863+
assert_eq!(m.len(), 1);
864+
assert_eq!(m.pop_back(), Some(2));
865+
check_links(&m);
866+
}
867+
868+
// Non-empty to non-empty
869+
let v = vec![1i,2,3,4,5];
870+
let u = vec![9i,8,1,2,3,4,5];
871+
let mut m = list_from(v.as_slice());
872+
let mut n = list_from(u.as_slice());
873+
m.append(&mut n);
874+
check_links(&m);
875+
let mut sum = v;
876+
sum.push_all(u.as_slice());
877+
assert_eq!(sum.len(), m.len());
878+
for elt in sum.into_iter() {
879+
assert_eq!(m.pop_front(), Some(elt))
880+
}
881+
assert_eq!(n.len(), 0);
882+
// let's make sure it's working properly, since we
883+
// did some direct changes to private members
884+
n.push_back(3);
885+
assert_eq!(n.len(), 1);
886+
assert_eq!(n.pop_front(), Some(3));
887+
check_links(&n);
888+
}
889+
890+
#[test]
891+
fn test_split_off() {
892+
// singleton
893+
{
894+
let mut m = DList::new();
895+
m.push_back(1i);
896+
897+
let p = m.split_off(0);
898+
assert_eq!(m.len(), 0);
899+
assert_eq!(p.len(), 1);
900+
assert_eq!(p.back(), Some(&1));
901+
assert_eq!(p.front(), Some(&1));
902+
}
903+
904+
// not singleton, forwards
905+
{
906+
let u = vec![1i,2,3,4,5];
907+
let mut m = list_from(u.as_slice());
908+
let mut n = m.split_off(2);
909+
assert_eq!(m.len(), 2);
910+
assert_eq!(n.len(), 3);
911+
for elt in range(1i, 3) {
912+
assert_eq!(m.pop_front(), Some(elt));
913+
}
914+
for elt in range(3i, 6) {
915+
assert_eq!(n.pop_front(), Some(elt));
916+
}
917+
}
918+
// not singleton, backwards
919+
{
920+
let u = vec![1i,2,3,4,5];
921+
let mut m = list_from(u.as_slice());
922+
let mut n = m.split_off(4);
923+
assert_eq!(m.len(), 4);
924+
assert_eq!(n.len(), 1);
925+
for elt in range(1i, 5) {
926+
assert_eq!(m.pop_front(), Some(elt));
927+
}
928+
for elt in range(5i, 6) {
929+
assert_eq!(n.pop_front(), Some(elt));
930+
}
931+
}
932+
933+
}
934+
780935
#[test]
781936
fn test_iterator() {
782937
let m = generate_test();
@@ -1065,41 +1220,6 @@ mod tests {
10651220
assert_eq!(i, v.len());
10661221
}
10671222

1068-
#[allow(deprecated)]
1069-
#[test]
1070-
fn test_append() {
1071-
{
1072-
let mut m = DList::new();
1073-
let mut n = DList::new();
1074-
n.push_back(2i);
1075-
m.append(n);
1076-
assert_eq!(m.len(), 1);
1077-
assert_eq!(m.pop_back(), Some(2));
1078-
check_links(&m);
1079-
}
1080-
{
1081-
let mut m = DList::new();
1082-
let n = DList::new();
1083-
m.push_back(2i);
1084-
m.append(n);
1085-
assert_eq!(m.len(), 1);
1086-
assert_eq!(m.pop_back(), Some(2));
1087-
check_links(&m);
1088-
}
1089-
1090-
let v = vec![1i,2,3,4,5];
1091-
let u = vec![9i,8,1,2,3,4,5];
1092-
let mut m = list_from(v.as_slice());
1093-
m.append(list_from(u.as_slice()));
1094-
check_links(&m);
1095-
let mut sum = v;
1096-
sum.push_all(u.as_slice());
1097-
assert_eq!(sum.len(), m.len());
1098-
for elt in sum.into_iter() {
1099-
assert_eq!(m.pop_front(), Some(elt))
1100-
}
1101-
}
1102-
11031223
#[bench]
11041224
fn bench_collect_into(b: &mut test::Bencher) {
11051225
let v = &[0i; 64];

branches/try/src/librustc/middle/infer/mod.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,39 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
613613
self.commit_unconditionally(move || self.try(move |_| f()))
614614
}
615615

616+
/// Execute `f` and commit only the region bindings if successful.
617+
/// The function f must be very careful not to leak any non-region
618+
/// variables that get created.
619+
pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
620+
F: FnOnce() -> Result<T, E>
621+
{
622+
debug!("commit_regions_if_ok()");
623+
let CombinedSnapshot { type_snapshot,
624+
int_snapshot,
625+
float_snapshot,
626+
region_vars_snapshot } = self.start_snapshot();
627+
628+
let r = self.try(move |_| f());
629+
630+
// Roll back any non-region bindings - they should be resolved
631+
// inside `f`, with, e.g. `resolve_type_vars_if_possible`.
632+
self.type_variables
633+
.borrow_mut()
634+
.rollback_to(type_snapshot);
635+
self.int_unification_table
636+
.borrow_mut()
637+
.rollback_to(int_snapshot);
638+
self.float_unification_table
639+
.borrow_mut()
640+
.rollback_to(float_snapshot);
641+
642+
// Commit region vars that may escape through resolved types.
643+
self.region_vars
644+
.commit(region_vars_snapshot);
645+
646+
r
647+
}
648+
616649
/// Execute `f`, unroll bindings on panic
617650
pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
618651
F: FnOnce(&CombinedSnapshot) -> Result<T, E>

branches/try/src/librustc_back/target/apple_ios_base.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use target::TargetOptions;
1414
use self::Arch::*;
1515

1616
#[allow(non_camel_case_types)]
17+
#[derive(Copy)]
1718
pub enum Arch {
1819
Armv7,
1920
Armv7s,
@@ -70,8 +71,16 @@ fn pre_link_args(arch: Arch) -> Vec<String> {
7071
"-Wl,-syslibroot".to_string(), get_sdk_root(sdk_name)]
7172
}
7273

74+
fn target_cpu(arch: Arch) -> String {
75+
match arch {
76+
X86_64 => "x86-64",
77+
_ => "generic",
78+
}.to_string()
79+
}
80+
7381
pub fn opts(arch: Arch) -> TargetOptions {
7482
TargetOptions {
83+
cpu: target_cpu(arch),
7584
dynamic_linking: false,
7685
executables: true,
7786
// Although there is an experimental implementation of LLVM which

branches/try/src/librustc_back/target/x86_64_apple_darwin.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use target::Target;
1212

1313
pub fn target() -> Target {
1414
let mut base = super::apple_base::opts();
15+
base.cpu = "x86-64".to_string();
1516
base.eliminate_frame_pointer = false;
1617
base.pre_link_args.push("-m64".to_string());
1718

branches/try/src/librustc_back/target/x86_64_pc_windows_gnu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use target::Target;
1212

1313
pub fn target() -> Target {
1414
let mut base = super::windows_base::opts();
15+
base.cpu = "x86-64".to_string();
1516
// On Win64 unwinding is handled by the OS, so we can link libgcc statically.
1617
base.pre_link_args.push("-static-libgcc".to_string());
1718
base.pre_link_args.push("-m64".to_string());

branches/try/src/librustc_back/target/x86_64_unknown_dragonfly.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use target::Target;
1212

1313
pub fn target() -> Target {
1414
let mut base = super::dragonfly_base::opts();
15+
base.cpu = "x86-64".to_string();
1516
base.pre_link_args.push("-m64".to_string());
1617

1718
Target {

0 commit comments

Comments
 (0)