Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc: Implement deriving involving generic bounded traits #3910

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1091,6 +1091,25 @@ enum region_ {
re_named(ident)
}

#[auto_serialize]
#[auto_deserialize]
enum onceness {
on_once,
on_many
}

impl onceness : cmp::Eq {
pure fn eq(other: &onceness) -> bool {
match (self, *other) {
(on_once, on_once) | (on_many, on_many) => true,
_ => false
}
}
pure fn ne(other: &onceness) -> bool {
!self.eq(other)
}
}

#[auto_serialize]
#[auto_deserialize]
enum ty_ {
Expand All @@ -1102,7 +1121,7 @@ enum ty_ {
ty_ptr(mt),
ty_rptr(@region, mt),
ty_rec(~[ty_field]),
ty_fn(proto, purity, @~[ty_param_bound], fn_decl),
ty_fn(proto, purity, onceness, @~[ty_param_bound], fn_decl),
ty_tup(~[@Ty]),
ty_path(@path, node_id),
ty_fixed_length(@Ty, Option<uint>),
Expand Down
9 changes: 5 additions & 4 deletions src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,11 @@ 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, bounds, decl) =>
ty_fn(proto, purity,
@vec::map(*bounds,
|x| fold_ty_param_bound(*x, 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_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)),
Expand Down
39 changes: 33 additions & 6 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl Parser {

pure fn id_to_str(id: ident) -> @~str { self.sess.interner.get(id) }

fn parse_ty_fn(purity: ast::purity) -> ty_ {
fn parse_ty_fn(purity: ast::purity, onceness: ast::onceness) -> ty_ {
let proto, bounds;
if self.eat_keyword(~"extern") {
self.expect_keyword(~"fn");
Expand All @@ -298,7 +298,17 @@ impl Parser {
proto = self.parse_fn_ty_proto();
bounds = self.parse_optional_ty_param_bounds();
};
ty_fn(proto, purity, bounds, self.parse_ty_fn_decl())
ty_fn(proto, purity, onceness, bounds, self.parse_ty_fn_decl())
}

fn parse_ty_fn_with_onceness(purity: ast::purity) -> ty_ {
let onceness = self.parse_optional_onceness();
self.parse_ty_fn(purity, onceness)
}

fn parse_ty_fn_with_purity_and_onceness() -> ty_ {
let purity = self.parse_optional_purity();
self.parse_ty_fn_with_onceness(purity)
}

fn parse_ty_fn_decl() -> fn_decl {
Expand Down Expand Up @@ -526,15 +536,18 @@ impl Parser {
let region = self.parse_region_with_sep();
let mt = self.parse_mt();
ty_rptr(region, mt)
} else if self.eat_keyword(~"once") {
self.parse_ty_fn(ast::impure_fn, ast::on_once)
} else if self.eat_keyword(~"pure") {
self.parse_ty_fn(ast::pure_fn)
self.parse_ty_fn_with_onceness(ast::pure_fn)
} else if self.eat_keyword(~"unsafe") {
self.parse_ty_fn(ast::unsafe_fn)
self.parse_ty_fn_with_onceness(ast::unsafe_fn)
} else if self.is_keyword(~"fn") {
self.parse_ty_fn(ast::impure_fn)
self.parse_ty_fn_with_onceness(ast::impure_fn)
} else if self.eat_keyword(~"extern") {
self.expect_keyword(~"fn");
ty_fn(proto_bare, ast::impure_fn, @~[], self.parse_ty_fn_decl())
ty_fn(proto_bare, ast::impure_fn, ast::on_many, @~[],
self.parse_ty_fn_decl())
} else if self.token == token::MOD_SEP || is_ident(self.token) {
let path = self.parse_path_with_tps(colons_before_params);
ty_path(path, self.get_id())
Expand Down Expand Up @@ -2275,6 +2288,20 @@ impl Parser {
self.get_id()), span: self.last_span}
}

fn parse_optional_purity() -> ast::purity {
if self.eat_keyword(~"pure") {
ast::pure_fn
} else if self.eat_keyword(~"unsafe") {
ast::unsafe_fn
} else {
ast::impure_fn
}
}

fn parse_optional_onceness() -> ast::onceness {
if self.eat_keyword(~"once") { ast::on_once } else { ast::on_many }
}

fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
let mut bounds = ~[];
if self.eat(token::COLON) {
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ fn strict_keyword_table() -> HashMap<~str, ()> {
~"if", ~"impl",
~"let", ~"log", ~"loop",
~"match", ~"mod", ~"move", ~"mut",
~"once",
~"priv", ~"pub", ~"pure",
~"ref", ~"return",
~"struct",
Expand Down
36 changes: 28 additions & 8 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,9 @@ fn print_type_ex(s: ps, &&ty: @ast::Ty, print_colons: bool) {
commasep(s, inconsistent, elts, print_type);
pclose(s);
}
ast::ty_fn(proto, purity, bounds, d) => {
print_ty_fn(s, Some(proto), purity, bounds, d, None, None, None);
ast::ty_fn(proto, purity, onceness, bounds, d) => {
print_ty_fn(s, Some(proto), purity, onceness, bounds, d, None, None,
None);
}
ast::ty_path(path, _) => print_path(s, path, print_colons),
ast::ty_fixed_length(t, v) => {
Expand Down Expand Up @@ -804,7 +805,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
hardbreak_if_not_bol(s);
maybe_print_comment(s, m.span.lo);
print_outer_attributes(s, m.attrs);
print_ty_fn(s, None, m.purity,
print_ty_fn(s, None, m.purity, ast::on_many,
@~[], m.decl, Some(m.ident), Some(m.tps),
Some(m.self_ty.node));
word(s.s, ~";");
Expand Down Expand Up @@ -1273,7 +1274,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
cbox(s, indent_unit);
// head-box, will be closed by print-block at start
ibox(s, 0u);
word(s.s, fn_header_info_to_str(None, None, Some(proto),
word(s.s, fn_header_info_to_str(None, None, Some(proto), ast::on_many,
ast::inherited));
print_fn_args_and_ret(s, decl, *cap_clause, None);
space(s.s);
Expand Down Expand Up @@ -1606,12 +1607,15 @@ fn print_self_ty(s: ps, self_ty: ast::self_ty_) -> bool {
return true;
}

fn print_fn(s: ps, decl: ast::fn_decl, purity: Option<ast::purity>,
fn print_fn(s: ps,
decl: ast::fn_decl,
purity: Option<ast::purity>,
name: ast::ident,
typarams: ~[ast::ty_param],
opt_self_ty: Option<ast::self_ty_>,
vis: ast::visibility) {
head(s, fn_header_info_to_str(opt_self_ty, purity, None, vis));
head(s, fn_header_info_to_str(opt_self_ty, purity, None, ast::on_many,
vis));
print_ident(s, name);
print_type_params(s, typarams);
print_fn_args_and_ret(s, decl, ~[], opt_self_ty);
Expand Down Expand Up @@ -1831,14 +1835,17 @@ fn print_arg(s: ps, input: ast::arg) {
end(s);
}

fn print_ty_fn(s: ps, opt_proto: Option<ast::proto>, purity: ast::purity,
fn print_ty_fn(s: ps,
opt_proto: Option<ast::proto>,
purity: ast::purity,
onceness: ast::onceness,
bounds: @~[ast::ty_param_bound],
decl: ast::fn_decl, id: Option<ast::ident>,
tps: Option<~[ast::ty_param]>,
opt_self_ty: Option<ast::self_ty_>) {
ibox(s, indent_unit);
word(s.s, fn_header_info_to_str(opt_self_ty, Some(purity), opt_proto,
ast::inherited));
onceness, ast::inherited));
print_bounds(s, bounds);
match id { Some(id) => { word(s.s, ~" "); print_ident(s, id); } _ => () }
match tps { Some(tps) => print_type_params(s, tps), _ => () }
Expand Down Expand Up @@ -2062,6 +2069,7 @@ fn next_comment(s: ps) -> Option<comments::cmnt> {
fn fn_header_info_to_str(opt_sty: Option<ast::self_ty_>,
opt_purity: Option<ast::purity>,
opt_p: Option<ast::proto>,
onceness: ast::onceness,
vis: ast::visibility) -> ~str {

let mut s = visibility_qualified(vis, ~"");
Expand All @@ -2082,6 +2090,11 @@ fn fn_header_info_to_str(opt_sty: Option<ast::self_ty_>,

str::push_str(&mut s, opt_proto_to_str(opt_p));

match onceness {
ast::on_once => str::push_str(&mut s, ~"once "),
ast::on_many => {}
}

return s;
}

Expand All @@ -2101,6 +2114,13 @@ pure fn purity_to_str(p: ast::purity) -> ~str {
}
}

pure fn onceness_to_str(o: ast::onceness) -> ~str {
match o {
ast::on_once => ~"once",
ast::on_many => ~"many"
}
}

fn print_purity(s: ps, p: ast::purity) {
match p {
ast::impure_fn => (),
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ fn visit_ty<E>(t: @Ty, e: E, v: vt<E>) {
ty_tup(ts) => for ts.each |tt| {
v.visit_ty(*tt, e, v);
},
ty_fn(_, _, bounds, decl) => {
ty_fn(_, _, _, bounds, decl) => {
for decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
visit_ty_param_bounds(bounds, e, v);
v.visit_ty(decl.output, e, v);
Expand Down
10 changes: 10 additions & 0 deletions src/rustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,14 @@ fn parse_purity(c: char) -> purity {
}
}

fn parse_onceness(c: char) -> ast::onceness {
match c {
'o' => ast::on_once,
'm' => ast::on_many,
_ => fail ~"parse_onceness: bad onceness"
}
}

fn parse_arg(st: @pstate, conv: conv_did) -> ty::arg {
{mode: parse_mode(st),
ty: parse_ty(st, conv)}
Expand All @@ -406,6 +414,7 @@ fn parse_mode(st: @pstate) -> ast::mode {
fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
let proto = parse_proto(st);
let purity = parse_purity(next(st));
let onceness = parse_onceness(next(st));
let bounds = parse_bounds(st, conv);
assert (next(st) == '[');
let mut inputs: ~[ty::arg] = ~[];
Expand All @@ -418,6 +427,7 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::FnTy {
return FnTyBase {
meta: FnMeta {purity: purity,
proto: proto,
onceness: onceness,
bounds: bounds,
ret_style: ret_style},
sig: FnSig {inputs: inputs,
Expand Down
8 changes: 8 additions & 0 deletions src/rustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,17 @@ fn enc_purity(w: io::Writer, p: purity) {
}
}

fn enc_onceness(w: io::Writer, o: onceness) {
match o {
on_once => w.write_char('o'),
on_many => w.write_char('m')
}
}

fn enc_ty_fn(w: io::Writer, cx: @ctxt, ft: ty::FnTy) {
enc_proto(w, cx, ft.meta.proto);
enc_purity(w, ft.meta.purity);
enc_onceness(w, ft.meta.onceness);
enc_bounds(w, cx, ft.meta.bounds);
w.write_char('[');
for ft.sig.inputs.each |arg| {
Expand Down
6 changes: 3 additions & 3 deletions src/rustc/middle/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
let span = arg_ast.ty.span;
// Recurse to check fn-type argument
match arg_ast.ty.node {
ast::ty_fn(_, _, _, decl) => {
ast::ty_fn(_, _, _, _, decl) => {
check_fn_deprecated_modes(tcx, arg_ty.ty,
decl, span, id);
}
Expand All @@ -856,7 +856,7 @@ fn check_fn_deprecated_modes(tcx: ty::ctxt, fn_ty: ty::t, decl: ast::fn_decl,
// Functions with preceding sigil are parsed
// as pointers of functions
match mt.ty.node {
ast::ty_fn(_, _, _, decl) => {
ast::ty_fn(_, _, _, _, decl) => {
check_fn_deprecated_modes(
tcx, arg_ty.ty,
decl, span, id);
Expand Down Expand Up @@ -889,7 +889,7 @@ fn check_item_deprecated_modes(tcx: ty::ctxt, it: @ast::item) {
match it.node {
ast::item_ty(ty, _) => {
match ty.node {
ast::ty_fn(_, _, _, decl) => {
ast::ty_fn(_, _, _, _, decl) => {
let fn_ty = ty::node_id_to_type(tcx, it.id);
check_fn_deprecated_modes(
tcx, fn_ty, decl, ty.span, it.id)
Expand Down
10 changes: 5 additions & 5 deletions src/rustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -624,8 +624,8 @@ fn determine_rp_in_ty(ty: @ast::Ty,
}
}

ast::ty_fn(ast::proto_bare, _, _, _) |
ast::ty_fn(ast::proto_block, _, _, _) if cx.anon_implies_rp => {
ast::ty_fn(ast::proto_bare, _, _, _, _) |
ast::ty_fn(ast::proto_block, _, _, _, _) if cx.anon_implies_rp => {
debug!("referenced bare fn type with regions %s",
pprust::ty_to_str(ty, cx.sess.intr()));
cx.add_rp(cx.item_id, cx.add_variance(rv_contravariant));
Expand Down Expand Up @@ -672,8 +672,8 @@ fn determine_rp_in_ty(ty: @ast::Ty,
match ty.node {
ast::ty_box(mt) | ast::ty_uniq(mt) => {
match mt.ty.node {
ast::ty_fn(ast::proto_bare, _, _, _) |
ast::ty_fn(ast::proto_block, _, _, _) => {
ast::ty_fn(ast::proto_bare, _, _, _, _) |
ast::ty_fn(ast::proto_block, _, _, _, _) => {
do cx.with(cx.item_id, false) {
visit_mt(mt, cx, visitor);
}
Expand Down Expand Up @@ -706,7 +706,7 @@ fn determine_rp_in_ty(ty: @ast::Ty,
}
}

ast::ty_fn(_, _, bounds, decl) => {
ast::ty_fn(_, _, _, bounds, decl) => {
// fn() binds the & region, so do not consider &T types that
// appear *inside* a fn() type to affect the enclosing item:
do cx.with(cx.item_id, false) {
Expand Down
2 changes: 1 addition & 1 deletion src/rustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ fn trans_fn_ref_with_vtables_to_callee(bcx: block,
fn trans_fn_ref_with_vtables(
bcx: block, //
def_id: ast::def_id, // def id of fn
ref_id: ast::node_id, // node id of use of fn
ref_id: ast::node_id, // node id of use of fn; may be zero if N/A
type_params: ~[ty::t], // values for fn's ty params
vtables: Option<typeck::vtable_res>)
-> FnData
Expand Down
Loading