Skip to content

Commit 2111166

Browse files
committed
Improve type inference to compute LUB/GLB
1 parent 2112c39 commit 2111166

File tree

5 files changed

+765
-184
lines changed

5 files changed

+765
-184
lines changed

src/libcore/result.rs

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -109,20 +109,21 @@ fn chain_err<T: copy, U: copy, V: copy>(
109109
}
110110
}
111111

112-
// ______________________________________________________________________
113-
// Note:
114-
//
115-
// These helper functions are written in a "pre-chained" (a.k.a,
116-
// deforested) style because I have found that, in practice, this is
117-
// the most concise way to do things. That means that they do not not
118-
// terminate with a call to `ok(v)` but rather `nxt(v)`. If you would
119-
// like to just get the result, just pass in `ok` as `nxt`.
112+
impl methods<T:copy,E:copy> for result<T,E> {
113+
fn chain<U:copy>(op: fn(T) -> result<U,E>) -> result<U,E> {
114+
chain(self, op)
115+
}
116+
117+
fn chain_err<F:copy>(op: fn(E) -> result<T,F>) -> result<T,F> {
118+
chain_err(self, op)
119+
}
120+
}
120121

121122
#[doc = "
122123
Maps each element in the vector `ts` using the operation `op`. Should an
123124
error occur, no further mappings are performed and the error is returned.
124125
Should no error occur, a vector containing the result of each map is
125-
passed to the `nxt` function.
126+
returned.
126127
127128
Here is an example which increments every integer in a vector,
128129
checking for overflow:
@@ -131,27 +132,11 @@ checking for overflow:
131132
if x == uint::max_value { ret err(\"overflow\"); }
132133
else { ret ok(x+1u); }
133134
}
134-
map([1u, 2u, 3u], inc_conditionally) {|incd|
135-
assert incd == [2u, 3u, 4u];
136-
}
137-
138-
Note: if you have to combine a deforested style transform with map,
139-
you should use `ok` for the `nxt` operation, as shown here (this is an
140-
alternate version of the previous example where the
141-
`inc_conditionally()` routine is deforested):
142-
143-
fn inc_conditionally<T>(x: uint,
144-
nxt: fn(uint) -> result<T,str>) -> result<T,str> {
145-
if x == uint::max_value { ret err(\"overflow\"); }
146-
else { ret nxt(x+1u); }
147-
}
148-
map([1u, 2u, 3u], inc_conditionally(_, ok)) {|incd|
135+
map([1u, 2u, 3u], inc_conditionally).chain {|incd|
149136
assert incd == [2u, 3u, 4u];
150137
}
151138
"]
152-
fn map<T,U:copy,V:copy,W>(ts: [T],
153-
op: fn(T) -> result<V,U>,
154-
nxt: fn([V]) -> result<W,U>) -> result<W,U> {
139+
fn map<T,U:copy,V:copy>(ts: [T], op: fn(T) -> result<V,U>) -> result<[V],U> {
155140
let mut vs: [V] = [];
156141
vec::reserve(vs, vec::len(ts));
157142
for t in ts {
@@ -160,7 +145,7 @@ fn map<T,U:copy,V:copy,W>(ts: [T],
160145
err(u) { ret err(u); }
161146
}
162147
}
163-
ret nxt(vs);
148+
ret ok(vs);
164149
}
165150

166151
#[doc = "Same as map, but it operates over two parallel vectors.
@@ -170,11 +155,9 @@ length. While we do not often use preconditions in the standard
170155
library, a precondition is used here because result::t is generally
171156
used in 'careful' code contexts where it is both appropriate and easy
172157
to accommodate an error like the vectors being of different lengths."]
173-
fn map2<S,T,U:copy,V:copy,W>(ss: [S], ts: [T],
174-
op: fn(S,T) -> result<V,U>,
175-
nxt: fn([V]) -> result<W,U>)
176-
: vec::same_length(ss, ts)
177-
-> result<W,U> {
158+
fn map2<S,T,U:copy,V:copy>(ss: [S], ts: [T], op: fn(S,T) -> result<V,U>)
159+
: vec::same_length(ss, ts) -> result<[V],U> {
160+
178161
let n = vec::len(ts);
179162
let mut vs = [];
180163
vec::reserve(vs, n);
@@ -186,13 +169,19 @@ fn map2<S,T,U:copy,V:copy,W>(ss: [S], ts: [T],
186169
}
187170
i += 1u;
188171
}
189-
ret nxt(vs);
172+
ret ok(vs);
190173
}
191174

175+
#[doc = "
176+
Applies op to the pairwise elements from `ss` and `ts`, aborting on
177+
error. This could be implemented using `map2()` but it is more efficient
178+
on its own as no result vector is built.
179+
"]
192180
fn iter2<S,T,U:copy>(ss: [S], ts: [T],
193181
op: fn(S,T) -> result<(),U>)
194182
: vec::same_length(ss, ts)
195183
-> result<(),U> {
184+
196185
let n = vec::len(ts);
197186
let mut i = 0u;
198187
while i < n {

src/libcore/vec.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export rsplit;
2727
export rsplitn;
2828
export shift;
2929
export pop;
30-
export clear;
3130
export push;
3231
export grow;
3332
export grow_fn;
@@ -321,7 +320,7 @@ fn rsplitn<T: copy>(v: [const T], n: uint, f: fn(T) -> bool) -> [[T]] {
321320
// Mutators
322321

323322
#[doc = "Removes the first element from a vector and return it"]
324-
fn shift<T: copy>(&v: [const T]) -> T {
323+
fn shift<T: copy>(&v: [T]) -> T {
325324
let ln = len::<T>(v);
326325
assert (ln > 0u);
327326
let e = v[0];
@@ -331,6 +330,9 @@ fn shift<T: copy>(&v: [const T]) -> T {
331330

332331
#[doc = "Prepend an element to a vector"]
333332
fn unshift<T: copy>(&v: [const T], +t: T) {
333+
// n.b.---for most callers, using unshift() ought not to type check, but
334+
// it does. It's because the type system is unaware of the mutability of
335+
// `v` and so allows the vector to be covariant.
334336
v = [const t] + v;
335337
}
336338

@@ -344,14 +346,6 @@ fn pop<T>(&v: [const T]) -> T unsafe {
344346
val
345347
}
346348

347-
#[doc = "
348-
Removes all elements from a vector without affecting
349-
how much space is reserved.
350-
"]
351-
fn clear<T>(&v: [const T]) unsafe {
352-
unsafe::set_len(v, 0u);
353-
}
354-
355349
#[doc = "Append an element to a vector"]
356350
fn push<T>(&v: [const T], +initval: T) {
357351
v += [initval];

0 commit comments

Comments
 (0)