Skip to content

Commit

Permalink
Implement proper subtyping for region fn types (part of rust-lang#2263)
Browse files Browse the repository at this point in the history
  • Loading branch information
nikomatsakis committed Oct 24, 2012
1 parent 3b6f5a1 commit 043b007
Show file tree
Hide file tree
Showing 20 changed files with 877 additions and 417 deletions.
11 changes: 11 additions & 0 deletions src/libcore/at_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,23 @@ pub pure fn from_elem<T: Copy>(n_elts: uint, t: T) -> @[T] {
#[cfg(notest)]
pub mod traits {
#[legacy_exports];

#[cfg(stage0)]
pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
#[inline(always)]
pure fn add(rhs: & &[const T]) -> @[T] {
append(self, (*rhs))
}
}

#[cfg(stage1)]
#[cfg(stage2)]
pub impl<T: Copy> @[T] : Add<&[const T],@[T]> {
#[inline(always)]
pure fn add(rhs: & &self/[const T]) -> @[T] {
append(self, (*rhs))
}
}
}

#[cfg(test)]
Expand Down
18 changes: 18 additions & 0 deletions src/libcore/ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,19 +226,37 @@ impl<T> *const T : Ord {
}

// Equality for region pointers
#[cfg(stage0)]
impl<T:Eq> &const T : Eq {
pure fn eq(other: & &const T) -> bool { return *self == *(*other); }
pure fn ne(other: & &const T) -> bool { return *self != *(*other); }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T:Eq> &const T : Eq {
pure fn eq(other: & &self/const T) -> bool { return *self == *(*other); }
pure fn ne(other: & &self/const T) -> bool { return *self != *(*other); }
}

// Comparison for region pointers
#[cfg(stage0)]
impl<T:Ord> &const T : Ord {
pure fn lt(other: & &const T) -> bool { *self < *(*other) }
pure fn le(other: & &const T) -> bool { *self <= *(*other) }
pure fn ge(other: & &const T) -> bool { *self >= *(*other) }
pure fn gt(other: & &const T) -> bool { *self > *(*other) }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T:Ord> &const T : Ord {
pure fn lt(other: & &self/const T) -> bool { *self < *(*other) }
pure fn le(other: & &self/const T) -> bool { *self <= *(*other) }
pure fn ge(other: & &self/const T) -> bool { *self >= *(*other) }
pure fn gt(other: & &self/const T) -> bool { *self > *(*other) }
}

#[test]
pub fn test() {
unsafe {
Expand Down
38 changes: 37 additions & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,7 @@ pure fn gt(a: &str, b: &str) -> bool {
!le(a, b)
}

#[cfg(stage0)]
impl &str : Eq {
#[inline(always)]
pure fn eq(other: & &str) -> bool {
Expand All @@ -744,6 +745,17 @@ impl &str : Eq {
pure fn ne(other: & &str) -> bool { !self.eq(other) }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl &str : Eq {
#[inline(always)]
pure fn eq(other: & &self/str) -> bool {
eq_slice(self, (*other))
}
#[inline(always)]
pure fn ne(other: & &self/str) -> bool { !self.eq(other) }
}

impl ~str : Eq {
#[inline(always)]
pure fn eq(other: &~str) -> bool {
Expand Down Expand Up @@ -773,6 +785,7 @@ impl ~str : Ord {
pure fn gt(other: &~str) -> bool { gt(self, (*other)) }
}

#[cfg(stage0)]
impl &str : Ord {
#[inline(always)]
pure fn lt(other: & &str) -> bool { lt(self, (*other)) }
Expand All @@ -784,6 +797,19 @@ impl &str : Ord {
pure fn gt(other: & &str) -> bool { gt(self, (*other)) }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl &str : Ord {
#[inline(always)]
pure fn lt(other: & &self/str) -> bool { lt(self, (*other)) }
#[inline(always)]
pure fn le(other: & &self/str) -> bool { le(self, (*other)) }
#[inline(always)]
pure fn ge(other: & &self/str) -> bool { ge(self, (*other)) }
#[inline(always)]
pure fn gt(other: & &self/str) -> bool { gt(self, (*other)) }
}

impl @str : Ord {
#[inline(always)]
pure fn lt(other: &@str) -> bool { lt(self, (*other)) }
Expand Down Expand Up @@ -2096,12 +2122,22 @@ impl ~str: Trimmable {

#[cfg(notest)]
pub mod traits {
#[cfg(stage0)]
impl ~str : Add<&str,~str> {
#[inline(always)]
pure fn add(rhs: & &str) -> ~str {
append(copy self, (*rhs))
}
}

#[cfg(stage1)]
#[cfg(stage2)]
impl ~str : Add<&str,~str> {
#[inline(always)]
pure fn add(rhs: & &self/str) -> ~str {
append(copy self, (*rhs))
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -2558,7 +2594,7 @@ mod tests {
assert find_str_between(data, ~"ab", 2u, 4u).is_none();

let mut data = ~"ประเทศไทย中华Việt Nam";
data += data;
data = data + data;
assert find_str_between(data, ~"", 0u, 43u) == Some(0u);
assert find_str_between(data, ~"", 6u, 43u) == Some(6u);

Expand Down
88 changes: 81 additions & 7 deletions src/libcore/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,27 @@ pub pure fn filter<T: Copy>(v: &[T], f: fn(t: &T) -> bool) -> ~[T] {
move result
}

/**
* Like `filter()`, but in place. Preserves order of `v`. Linear time.
*/
pub fn retain<T>(v: &mut ~[T], f: pure fn(t: &T) -> bool) {
let len = v.len();
let mut deleted: uint = 0;

for uint::range(0, len) |i| {
if !f(&v[i]) {
deleted += 1;
} else if deleted > 0 {
v[i - deleted] <-> v[i];
}
}

while deleted > 0 {
v.pop();
deleted -= 1;
}
}

/**
* Concatenate a vector of vectors.
*
Expand All @@ -759,14 +780,17 @@ pub pure fn connect<T: Copy>(v: &[~[T]], sep: &T) -> ~[T] {
}

/// Reduce a vector from left to right
pub pure fn foldl<T: Copy, U>(z: T, v: &[U], p: fn(t: T, u: &U) -> T) -> T {
let mut accum = z;
for each(v) |elt| {
// it should be possible to move accum in, but the liveness analysis
// is not smart enough.
accum = p(accum, elt);
pub pure fn foldl<T, U>(z: T, v: &[U], p: fn(t: T, u: &U) -> T) -> T {
let mut accum = move z;
let mut i = 0;
let l = v.len();
while i < l {
// Use a while loop so that liveness analysis can handle moving
// the accumulator.
accum = p(move accum, &v[i]);
i += 1;
}
return accum;
return move accum;
}

/// Reduce a vector from right to left
Expand Down Expand Up @@ -1293,13 +1317,24 @@ pure fn eq<T: Eq>(a: &[T], b: &[T]) -> bool {
return true;
}

#[cfg(stage0)]
impl<T: Eq> &[T] : Eq {
#[inline(always)]
pure fn eq(other: & &[T]) -> bool { eq(self, (*other)) }
#[inline(always)]
pure fn ne(other: & &[T]) -> bool { !self.eq(other) }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T: Eq> &[T] : Eq {
#[inline(always)]
pure fn eq(other: & &self/[T]) -> bool { eq(self, (*other)) }
#[inline(always)]
pure fn ne(other: & &self/[T]) -> bool { !self.eq(other) }
}


impl<T: Eq> ~[T] : Eq {
#[inline(always)]
pure fn eq(other: &~[T]) -> bool { eq(self, (*other)) }
Expand Down Expand Up @@ -1335,6 +1370,7 @@ pure fn le<T: Ord>(a: &[T], b: &[T]) -> bool { !lt(b, a) }
pure fn ge<T: Ord>(a: &[T], b: &[T]) -> bool { !lt(a, b) }
pure fn gt<T: Ord>(a: &[T], b: &[T]) -> bool { lt(b, a) }

#[cfg(stage0)]
impl<T: Ord> &[T] : Ord {
#[inline(always)]
pure fn lt(other: & &[T]) -> bool { lt(self, (*other)) }
Expand All @@ -1346,6 +1382,19 @@ impl<T: Ord> &[T] : Ord {
pure fn gt(other: & &[T]) -> bool { gt(self, (*other)) }
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T: Ord> &[T] : Ord {
#[inline(always)]
pure fn lt(other: & &self/[T]) -> bool { lt(self, (*other)) }
#[inline(always)]
pure fn le(other: & &self/[T]) -> bool { le(self, (*other)) }
#[inline(always)]
pure fn ge(other: & &self/[T]) -> bool { ge(self, (*other)) }
#[inline(always)]
pure fn gt(other: & &self/[T]) -> bool { gt(self, (*other)) }
}

impl<T: Ord> ~[T] : Ord {
#[inline(always)]
pure fn lt(other: &~[T]) -> bool { lt(self, (*other)) }
Expand All @@ -1370,19 +1419,39 @@ impl<T: Ord> @[T] : Ord {

#[cfg(notest)]
pub mod traits {
#[cfg(stage0)]
impl<T: Copy> ~[T] : Add<&[const T],~[T]> {
#[inline(always)]
pure fn add(rhs: & &[const T]) -> ~[T] {
append(copy self, (*rhs))
}
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T: Copy> ~[T] : Add<&[const T],~[T]> {
#[inline(always)]
pure fn add(rhs: & &self/[const T]) -> ~[T] {
append(copy self, (*rhs))
}
}

#[cfg(stage0)]
impl<T: Copy> ~[mut T] : Add<&[const T],~[mut T]> {
#[inline(always)]
pure fn add(rhs: & &[const T]) -> ~[mut T] {
append_mut(copy self, (*rhs))
}
}

#[cfg(stage1)]
#[cfg(stage2)]
impl<T: Copy> ~[mut T] : Add<&[const T],~[mut T]> {
#[inline(always)]
pure fn add(rhs: & &self/[const T]) -> ~[mut T] {
append_mut(copy self, (*rhs))
}
}
}

#[cfg(test)]
Expand Down Expand Up @@ -1590,6 +1659,7 @@ pub trait MutableVector<T> {
fn unshift(&mut self, x: T);
fn swap_remove(&mut self, index: uint) -> T;
fn truncate(&mut self, newlen: uint);
fn retain(&mut self, f: pure fn(t: &T) -> bool);
}

pub trait MutableCopyableVector<T: Copy> {
Expand Down Expand Up @@ -1631,6 +1701,10 @@ impl<T> ~[T]: MutableVector<T> {
fn truncate(&mut self, newlen: uint) {
truncate(self, newlen);
}

fn retain(&mut self, f: pure fn(t: &T) -> bool) {
retain(self, f);
}
}

impl<T: Copy> ~[T]: MutableCopyableVector<T> {
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fn enc_region(w: io::Writer, cx: @ctxt, r: ty::Region) {
ty::re_static => {
w.write_char('t');
}
ty::re_var(_) => {
ty::re_infer(_) => {
// these should not crop up after typeck
cx.diag.handler().bug(~"Cannot encode region variables");
}
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ impl ty::Region: tr {
ty::re_bound(br) => ty::re_bound(br.tr(xcx)),
ty::re_free(id, br) => ty::re_free(xcx.tr_id(id), br.tr(xcx)),
ty::re_scope(id) => ty::re_scope(xcx.tr_id(id)),
ty::re_static | ty::re_var(*) => self,
ty::re_static | ty::re_infer(*) => self,
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ fn check_cast_for_escaping_regions(
match target_substs.self_r {
Some(ty::re_scope(*)) => { return; /* case (1) */ }
None | Some(ty::re_static) | Some(ty::re_free(*)) => {}
Some(ty::re_bound(*)) | Some(ty::re_var(*)) => {
Some(ty::re_bound(*)) | Some(ty::re_infer(*)) => {
cx.tcx.sess.span_bug(
source.span,
fmt!("bad region found in kind: %?", target_substs.self_r));
Expand Down
20 changes: 10 additions & 10 deletions src/rustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,18 @@ fn is_subregion_of(region_map: region_map,
super_region: ty::Region) -> bool {
sub_region == super_region ||
match (sub_region, super_region) {
(_, ty::re_static) => {
true
}
(_, ty::re_static) => {
true
}

(ty::re_scope(sub_scope), ty::re_scope(super_scope)) |
(ty::re_scope(sub_scope), ty::re_free(super_scope, _)) => {
scope_contains(region_map, super_scope, sub_scope)
}
(ty::re_scope(sub_scope), ty::re_scope(super_scope)) |
(ty::re_scope(sub_scope), ty::re_free(super_scope, _)) => {
scope_contains(region_map, super_scope, sub_scope)
}

_ => {
false
}
_ => {
false
}
}
}

Expand Down
Loading

0 comments on commit 043b007

Please sign in to comment.