Skip to content

Commit

Permalink
Cleanup how we handle proto in types, remove unsound subtyping
Browse files Browse the repository at this point in the history
Fixes rust-lang#1896 which was never truly fixed, just masked.
The given tests would have failed had they used `~fn()` and
not `@fn()`.  They now result in compilation errors.

Fixes rust-lang#2978.

Necessary first step for rust-lang#2202, rust-lang#2263.
  • Loading branch information
nikomatsakis committed Nov 6, 2012
1 parent 53ec6c3 commit 87b8938
Show file tree
Hide file tree
Showing 51 changed files with 883 additions and 974 deletions.
45 changes: 31 additions & 14 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,18 +410,24 @@ impl mutability : cmp::Eq {

#[auto_serialize]
#[auto_deserialize]
enum proto {
proto_bare, // foreign fn
proto_uniq, // fn~
proto_box, // fn@
proto_block, // fn&
pub enum Proto {
ProtoBare, // bare functions (deprecated)
ProtoUniq, // ~fn
ProtoBox, // @fn
ProtoBorrowed, // &fn
}

impl proto : cmp::Eq {
pure fn eq(other: &proto) -> bool {
impl Proto : cmp::Eq {
pure fn eq(other: &Proto) -> bool {
(self as uint) == ((*other) as uint)
}
pure fn ne(other: &proto) -> bool { !self.eq(other) }
pure fn ne(other: &Proto) -> bool { !self.eq(other) }
}

impl Proto : to_bytes::IterBytes {
pure fn iter_bytes(+lsb0: bool, f: to_bytes::Cb) {
(self as uint).iter_bytes(lsb0, f);
}
}

#[auto_serialize]
Expand All @@ -444,10 +450,10 @@ enum expr_vstore {
expr_vstore_slice // &[1,2,3,4]
}

pure fn is_blockish(p: ast::proto) -> bool {
pure fn is_blockish(p: ast::Proto) -> bool {
match p {
proto_block => true,
proto_bare | proto_uniq | proto_box => false
ProtoBorrowed => true,
ProtoBare | ProtoUniq | ProtoBox => false
}
}

Expand Down Expand Up @@ -678,7 +684,7 @@ enum expr_ {
(implicit) condition is always true. */
expr_loop(blk, Option<ident>),
expr_match(@expr, ~[arm]),
expr_fn(proto, fn_decl, blk, capture_clause),
expr_fn(Proto, fn_decl, blk, capture_clause),
expr_fn_block(fn_decl, blk, capture_clause),
// Inner expr is always an expr_fn_block. We need the wrapping node to
// easily type this (a function returning nil on the inside but bool on
Expand Down Expand Up @@ -1078,6 +1084,17 @@ impl Onceness : cmp::Eq {
}
}

#[auto_serialize]
#[auto_deserialize]
struct TyFn {
proto: Proto,
region: Option<@region>,
purity: purity,
onceness: Onceness,
bounds: @~[ty_param_bound],
decl: fn_decl
}

#[auto_serialize]
#[auto_deserialize]
enum ty_ {
Expand All @@ -1086,13 +1103,13 @@ enum ty_ {
ty_box(mt),
ty_uniq(mt),
ty_vec(mt),
ty_fixed_length_vec(mt, uint),
ty_ptr(mt),
ty_rptr(@region, mt),
ty_rec(~[ty_field]),
ty_fn(proto, purity, Onceness, @~[ty_param_bound], fn_decl),
ty_fn(@TyFn),
ty_tup(~[@Ty]),
ty_path(@path, node_id),
ty_fixed_length(@Ty, Option<uint>),
ty_mac(mac),
// ty_infer means the type should be inferred instead of it having been
// specified. This should only appear at the "top level" of a type and not
Expand Down
18 changes: 11 additions & 7 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -524,15 +524,19 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
ty_ptr(mt) => ty_ptr(fold_mt(mt, fld)),
ty_rptr(region, mt) => ty_rptr(region, fold_mt(mt, fld)),
ty_rec(fields) => ty_rec(vec::map(fields, |f| fold_field(*f, fld))),
ty_fn(proto, purity, onceness, bounds, decl) =>
ty_fn(proto,
purity,
onceness,
@vec::map(*bounds, |x| fold_ty_param_bound(*x, fld)),
fold_fn_decl(decl, fld)),
ty_fn(f) =>
ty_fn(@TyFn {
proto: f.proto,
purity: f.purity,
region: f.region,
onceness: f.onceness,
bounds: @vec::map(*f.bounds, |x| fold_ty_param_bound(*x, fld)),
decl: fold_fn_decl(f.decl, fld)
}),
ty_tup(tys) => ty_tup(vec::map(tys, |ty| fld.fold_ty(*ty))),
ty_path(path, id) => ty_path(fld.fold_path(path), fld.new_id(id)),
ty_fixed_length(t, vs) => ty_fixed_length(fld.fold_ty(t), vs),
ty_fixed_length_vec(mt, vs) =>
ty_fixed_length_vec(fold_mt(mt, fld), vs),
ty_mac(mac) => ty_mac(fold_mac(mac))
}
}
Expand Down
66 changes: 0 additions & 66 deletions src/libsyntax/parse/obsolete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ pub enum ObsoleteSyntax {
ObsoletePrivSection,
ObsoleteModeInFnType,
ObsoleteByMutRefMode,
ObsoleteFixedLengthVec,
ObsoleteMoveInit,
ObsoleteBinaryMove
}
Expand Down Expand Up @@ -102,11 +101,6 @@ impl Parser : ObsoleteReporter {
"by-mutable-reference mode",
"Declare an argument of type &mut T instead"
),
ObsoleteFixedLengthVec => (
"fixed-length vector",
"Fixed-length types are now written `[T * N]`, and instances \
are type-inferred"
),
ObsoleteMoveInit => (
"initializer-by-move",
"Write `let foo = move bar` instead"
Expand Down Expand Up @@ -200,65 +194,5 @@ impl Parser : ObsoleteReporter {
}
}

fn try_parse_obsolete_fixed_vstore() -> Option<Option<uint>> {
if self.token == token::BINOP(token::SLASH) {
self.bump();
match copy self.token {
token::UNDERSCORE => {
self.obsolete(copy self.last_span,
ObsoleteFixedLengthVec);
self.bump(); Some(None)
}
token::LIT_INT_UNSUFFIXED(i) if i >= 0i64 => {
self.obsolete(copy self.last_span,
ObsoleteFixedLengthVec);
self.bump(); Some(Some(i as uint))
}
_ => None
}
} else {
None
}
}

fn try_convert_ty_to_obsolete_fixed_length_vstore(sp: span, t: ast::ty_)
-> ast::ty_ {
match self.try_parse_obsolete_fixed_vstore() {
// Consider a fixed length vstore suffix (/N or /_)
None => t,
Some(v) => {
ast::ty_fixed_length(
@{id: self.get_id(), node: t, span: sp}, v)
}
}
}

fn try_convert_expr_to_obsolete_fixed_length_vstore(
lo: uint, hi: uint, ex: ast::expr_
) -> (uint, ast::expr_) {

let mut hi = hi;
let mut ex = ex;

// Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
// only.
match ex {
ast::expr_lit(@{node: ast::lit_str(_), span: _}) |
ast::expr_vec(_, _) => {
match self.try_parse_obsolete_fixed_vstore() {
None => (),
Some(v) => {
hi = self.span.hi;
ex = ast::expr_vstore(self.mk_expr(lo, hi, ex),
ast::expr_vstore_fixed(v));
}
}
}
_ => ()
}

return (hi, ex);
}

}

Loading

0 comments on commit 87b8938

Please sign in to comment.