rustc: Parse and stub (broken) typechecking for bounded function types
This commit is contained in:
parent
c0f7ed68e2
commit
60f47eabe2
17 changed files with 119 additions and 72 deletions
|
@ -558,7 +558,7 @@ enum ty_ {
|
||||||
ty_ptr(mt),
|
ty_ptr(mt),
|
||||||
ty_rptr(@region, mt),
|
ty_rptr(@region, mt),
|
||||||
ty_rec(~[ty_field]),
|
ty_rec(~[ty_field]),
|
||||||
ty_fn(proto, fn_decl),
|
ty_fn(proto, @~[ty_param_bound], fn_decl),
|
||||||
ty_tup(~[@ty]),
|
ty_tup(~[@ty]),
|
||||||
ty_path(@path, node_id),
|
ty_path(@path, node_id),
|
||||||
ty_fixed_length(@ty, option<uint>),
|
ty_fixed_length(@ty, option<uint>),
|
||||||
|
|
|
@ -186,10 +186,12 @@ impl helpers of ext_ctxt_helpers for ext_ctxt {
|
||||||
};
|
};
|
||||||
|
|
||||||
@{id: self.next_id(),
|
@{id: self.next_id(),
|
||||||
node: ast::ty_fn(ast::proto_block, {inputs: args,
|
node: ast::ty_fn(ast::proto_block,
|
||||||
output: output,
|
@~[],
|
||||||
purity: ast::impure_fn,
|
{inputs: args,
|
||||||
cf: ast::return_val}),
|
output: output,
|
||||||
|
purity: ast::impure_fn,
|
||||||
|
cf: ast::return_val}),
|
||||||
span: span}
|
span: span}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +443,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
|
||||||
~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}]
|
~[#ast[stmt]{$(s).emit_rec($(fld_lambda));}]
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_fn(_, _) => {
|
ast::ty_fn(*) => {
|
||||||
cx.span_err(ty.span, ~"cannot serialize function types");
|
cx.span_err(ty.span, ~"cannot serialize function types");
|
||||||
~[]
|
~[]
|
||||||
}
|
}
|
||||||
|
@ -681,7 +683,7 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
|
||||||
#ast{ $(d).read_rec($(fld_lambda)) }
|
#ast{ $(d).read_rec($(fld_lambda)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ty_fn(_, _) => {
|
ast::ty_fn(*) => {
|
||||||
#ast{ fail }
|
#ast{ fail }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -514,7 +514,10 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
|
||||||
ty_ptr(mt) => ty_ptr(fold_mt(mt, fld)),
|
ty_ptr(mt) => ty_ptr(fold_mt(mt, fld)),
|
||||||
ty_rptr(region, mt) => ty_rptr(region, 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_rec(fields) => ty_rec(vec::map(fields, |f| fold_field(f, fld))),
|
||||||
ty_fn(proto, decl) => ty_fn(proto, fold_fn_decl(decl, fld)),
|
ty_fn(proto, bounds, decl) =>
|
||||||
|
ty_fn(proto, @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_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_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(t, vs) => ty_fixed_length(fld.fold_ty(t), vs),
|
||||||
|
|
|
@ -50,10 +50,10 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
|
||||||
stmt_semi, subtract, sty_box, sty_by_ref, sty_region, sty_uniq,
|
stmt_semi, subtract, sty_box, sty_by_ref, sty_region, sty_uniq,
|
||||||
sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq,
|
sty_value, token_tree, trait_method, trait_ref, tt_delim, tt_seq,
|
||||||
tt_tok, tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
|
tt_tok, tt_nonterminal, ty, ty_, ty_bot, ty_box, ty_field, ty_fn,
|
||||||
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_path, ty_ptr,
|
ty_infer, ty_mac, ty_method, ty_nil, ty_param, ty_param_bound,
|
||||||
ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq, ty_vec,
|
ty_path, ty_ptr, ty_rec, ty_rptr, ty_tup, ty_u32, ty_uniq,
|
||||||
ty_fixed_length, unchecked_blk, uniq, unsafe_blk, unsafe_fn,
|
ty_vec, ty_fixed_length, unchecked_blk, uniq, unsafe_blk,
|
||||||
variant, view_item, view_item_, view_item_export,
|
unsafe_fn, variant, view_item, view_item_, view_item_export,
|
||||||
view_item_import, view_item_use, view_path, view_path_glob,
|
view_item_import, view_item_use, view_path, view_path_glob,
|
||||||
view_path_list, view_path_simple, visibility, vstore, vstore_box,
|
view_path_list, view_path_simple, visibility, vstore, vstore_box,
|
||||||
vstore_fixed, vstore_slice, vstore_uniq};
|
vstore_fixed, vstore_slice, vstore_uniq};
|
||||||
|
@ -240,14 +240,17 @@ class parser {
|
||||||
fn get_id() -> node_id { next_node_id(self.sess) }
|
fn get_id() -> node_id { next_node_id(self.sess) }
|
||||||
|
|
||||||
fn parse_ty_fn(purity: ast::purity) -> ty_ {
|
fn parse_ty_fn(purity: ast::purity) -> ty_ {
|
||||||
let proto = if self.eat_keyword(~"extern") {
|
let proto, bounds;
|
||||||
|
if self.eat_keyword(~"extern") {
|
||||||
self.expect_keyword(~"fn");
|
self.expect_keyword(~"fn");
|
||||||
ast::proto_bare
|
proto = ast::proto_bare;
|
||||||
|
bounds = @~[];
|
||||||
} else {
|
} else {
|
||||||
self.expect_keyword(~"fn");
|
self.expect_keyword(~"fn");
|
||||||
self.parse_fn_ty_proto()
|
proto = self.parse_fn_ty_proto();
|
||||||
|
bounds = self.parse_optional_ty_param_bounds();
|
||||||
};
|
};
|
||||||
ty_fn(proto, self.parse_ty_fn_decl(purity))
|
ty_fn(proto, bounds, self.parse_ty_fn_decl(purity))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ty_fn_decl(purity: ast::purity) -> fn_decl {
|
fn parse_ty_fn_decl(purity: ast::purity) -> fn_decl {
|
||||||
|
@ -467,7 +470,7 @@ class parser {
|
||||||
self.parse_ty_fn(ast::impure_fn)
|
self.parse_ty_fn(ast::impure_fn)
|
||||||
} else if self.eat_keyword(~"extern") {
|
} else if self.eat_keyword(~"extern") {
|
||||||
self.expect_keyword(~"fn");
|
self.expect_keyword(~"fn");
|
||||||
ty_fn(proto_bare, self.parse_ty_fn_decl(ast::impure_fn))
|
ty_fn(proto_bare, @~[], self.parse_ty_fn_decl(ast::impure_fn))
|
||||||
} else if self.token == token::MOD_SEP || is_ident(self.token) {
|
} else if self.token == token::MOD_SEP || is_ident(self.token) {
|
||||||
let path = self.parse_path_with_tps(colons_before_params);
|
let path = self.parse_path_with_tps(colons_before_params);
|
||||||
ty_path(path, self.get_id())
|
ty_path(path, self.get_id())
|
||||||
|
@ -2125,11 +2128,10 @@ class parser {
|
||||||
return spanned(lo, hi, bloc);
|
return spanned(lo, hi, bloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ty_param() -> ty_param {
|
fn parse_optional_ty_param_bounds() -> @~[ty_param_bound] {
|
||||||
let mut bounds = ~[];
|
let mut bounds = ~[];
|
||||||
let ident = self.parse_ident();
|
|
||||||
if self.eat(token::COLON) {
|
if self.eat(token::COLON) {
|
||||||
while self.token != token::COMMA && self.token != token::GT {
|
while is_ident(self.token) {
|
||||||
if self.eat_keyword(~"send") {
|
if self.eat_keyword(~"send") {
|
||||||
push(bounds, bound_send); }
|
push(bounds, bound_send); }
|
||||||
else if self.eat_keyword(~"copy") {
|
else if self.eat_keyword(~"copy") {
|
||||||
|
@ -2139,10 +2141,17 @@ class parser {
|
||||||
} else if self.eat_keyword(~"owned") {
|
} else if self.eat_keyword(~"owned") {
|
||||||
push(bounds, bound_owned);
|
push(bounds, bound_owned);
|
||||||
} else {
|
} else {
|
||||||
push(bounds, bound_trait(self.parse_ty(false))); }
|
push(bounds, bound_trait(self.parse_ty(false)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {ident: ident, id: self.get_id(), bounds: @bounds};
|
return @move bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ty_param() -> ty_param {
|
||||||
|
let ident = self.parse_ident();
|
||||||
|
let bounds = self.parse_optional_ty_param_bounds();
|
||||||
|
return {ident: ident, id: self.get_id(), bounds: bounds};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ty_params() -> ~[ty_param] {
|
fn parse_ty_params() -> ~[ty_param] {
|
||||||
|
|
|
@ -399,8 +399,8 @@ fn print_type_ex(s: ps, &&ty: @ast::ty, print_colons: bool) {
|
||||||
commasep(s, inconsistent, elts, print_type);
|
commasep(s, inconsistent, elts, print_type);
|
||||||
pclose(s);
|
pclose(s);
|
||||||
}
|
}
|
||||||
ast::ty_fn(proto, d) => {
|
ast::ty_fn(proto, bounds, d) => {
|
||||||
print_ty_fn(s, some(proto), d, none, none);
|
print_ty_fn(s, some(proto), bounds, d, none, none);
|
||||||
}
|
}
|
||||||
ast::ty_path(path, _) => print_path(s, path, print_colons),
|
ast::ty_path(path, _) => print_path(s, path, print_colons),
|
||||||
ast::ty_fixed_length(t, v) => {
|
ast::ty_fixed_length(t, v) => {
|
||||||
|
@ -702,7 +702,7 @@ fn print_ty_method(s: ps, m: ast::ty_method) {
|
||||||
hardbreak_if_not_bol(s);
|
hardbreak_if_not_bol(s);
|
||||||
maybe_print_comment(s, m.span.lo);
|
maybe_print_comment(s, m.span.lo);
|
||||||
print_outer_attributes(s, m.attrs);
|
print_outer_attributes(s, m.attrs);
|
||||||
print_ty_fn(s, none, m.decl, some(m.ident), some(m.tps));
|
print_ty_fn(s, none, @~[], m.decl, some(m.ident), some(m.tps));
|
||||||
word(s.s, ~";");
|
word(s.s, ~";");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1645,10 +1645,12 @@ fn print_arg(s: ps, input: ast::arg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_ty_fn(s: ps, opt_proto: option<ast::proto>,
|
fn print_ty_fn(s: ps, opt_proto: option<ast::proto>,
|
||||||
|
bounds: @~[ast::ty_param_bound],
|
||||||
decl: ast::fn_decl, id: option<ast::ident>,
|
decl: ast::fn_decl, id: option<ast::ident>,
|
||||||
tps: option<~[ast::ty_param]>) {
|
tps: option<~[ast::ty_param]>) {
|
||||||
ibox(s, indent_unit);
|
ibox(s, indent_unit);
|
||||||
word(s.s, opt_proto_to_str(opt_proto));
|
word(s.s, opt_proto_to_str(opt_proto));
|
||||||
|
print_bounds(s, bounds);
|
||||||
match id { some(id) => { word(s.s, ~" "); word(s.s, *id); } _ => () }
|
match id { some(id) => { word(s.s, ~" "); word(s.s, *id); } _ => () }
|
||||||
match tps { some(tps) => print_type_params(s, tps), _ => () }
|
match tps { some(tps) => print_type_params(s, tps), _ => () }
|
||||||
zerobreak(s.s);
|
zerobreak(s.s);
|
||||||
|
|
|
@ -195,8 +195,9 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
||||||
ty_tup(ts) => for ts.each |tt| {
|
ty_tup(ts) => for ts.each |tt| {
|
||||||
v.visit_ty(tt, e, v);
|
v.visit_ty(tt, e, v);
|
||||||
}
|
}
|
||||||
ty_fn(_, decl) => {
|
ty_fn(_, bounds, decl) => {
|
||||||
for decl.inputs.each |a| { v.visit_ty(a.ty, e, v); }
|
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);
|
v.visit_ty(decl.output, e, v);
|
||||||
}
|
}
|
||||||
ty_path(p, _) => visit_path(p, e, v),
|
ty_path(p, _) => visit_path(p, e, v),
|
||||||
|
@ -251,14 +252,18 @@ fn visit_foreign_item<E>(ni: @foreign_item, e: E, v: vt<E>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_ty_param_bounds<E>(bounds: @~[ty_param_bound], e: E, v: vt<E>) {
|
||||||
|
for vec::each(*bounds) |bound| {
|
||||||
|
match bound {
|
||||||
|
bound_trait(t) => v.visit_ty(t, e, v),
|
||||||
|
bound_copy | bound_send | bound_const | bound_owned => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_ty_params<E>(tps: ~[ty_param], e: E, v: vt<E>) {
|
fn visit_ty_params<E>(tps: ~[ty_param], e: E, v: vt<E>) {
|
||||||
for tps.each |tp| {
|
for tps.each |tp| {
|
||||||
for vec::each(*tp.bounds) |bound| {
|
visit_ty_param_bounds(tp.bounds, e, v);
|
||||||
match bound {
|
|
||||||
bound_trait(t) => v.visit_ty(t, e, v),
|
|
||||||
bound_copy | bound_send | bound_const | bound_owned => ()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -362,6 +362,7 @@ fn parse_purity(c: char) -> purity {
|
||||||
fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
|
fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
|
||||||
let proto = parse_proto(next(st));
|
let proto = parse_proto(next(st));
|
||||||
let purity = parse_purity(next(st));
|
let purity = parse_purity(next(st));
|
||||||
|
let bounds = parse_bounds(st, conv);
|
||||||
assert (next(st) == '[');
|
assert (next(st) == '[');
|
||||||
let mut inputs: ~[ty::arg] = ~[];
|
let mut inputs: ~[ty::arg] = ~[];
|
||||||
while peek(st) != ']' {
|
while peek(st) != ']' {
|
||||||
|
@ -377,8 +378,8 @@ fn parse_ty_fn(st: @pstate, conv: conv_did) -> ty::fn_ty {
|
||||||
}
|
}
|
||||||
st.pos += 1u; // eat the ']'
|
st.pos += 1u; // eat the ']'
|
||||||
let (ret_style, ret_ty) = parse_ret_ty(st, conv);
|
let (ret_style, ret_ty) = parse_ret_ty(st, conv);
|
||||||
return {purity: purity, proto: proto, inputs: inputs, output: ret_ty,
|
return {purity: purity, proto: proto, bounds: bounds, inputs: inputs,
|
||||||
ret_style: ret_style};
|
output: ret_ty, ret_style: ret_style};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -337,6 +337,7 @@ fn enc_purity(w: io::writer, p: purity) {
|
||||||
fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
|
fn enc_ty_fn(w: io::writer, cx: @ctxt, ft: ty::fn_ty) {
|
||||||
enc_proto(w, ft.proto);
|
enc_proto(w, ft.proto);
|
||||||
enc_purity(w, ft.purity);
|
enc_purity(w, ft.purity);
|
||||||
|
enc_bounds(w, cx, ft.bounds);
|
||||||
w.write_char('[');
|
w.write_char('[');
|
||||||
for ft.inputs.each |arg| {
|
for ft.inputs.each |arg| {
|
||||||
enc_mode(w, cx, arg.mode);
|
enc_mode(w, cx, arg.mode);
|
||||||
|
|
|
@ -1982,6 +1982,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> option<ty::t> {
|
||||||
ty::ty_fn(fty) => {
|
ty::ty_fn(fty) => {
|
||||||
some(ty::mk_fn(tcx, {purity: ast::impure_fn,
|
some(ty::mk_fn(tcx, {purity: ast::impure_fn,
|
||||||
proto: fty.proto,
|
proto: fty.proto,
|
||||||
|
bounds: @~[],
|
||||||
inputs: ~[],
|
inputs: ~[],
|
||||||
output: ty::mk_nil(tcx),
|
output: ty::mk_nil(tcx),
|
||||||
ret_style: ast::return_val}))
|
ret_style: ast::return_val}))
|
||||||
|
@ -1989,6 +1990,7 @@ fn normalize_for_monomorphization(tcx: ty::ctxt, ty: ty::t) -> option<ty::t> {
|
||||||
ty::ty_trait(_, _) => {
|
ty::ty_trait(_, _) => {
|
||||||
some(ty::mk_fn(tcx, {purity: ast::impure_fn,
|
some(ty::mk_fn(tcx, {purity: ast::impure_fn,
|
||||||
proto: ast::proto_box,
|
proto: ast::proto_box,
|
||||||
|
bounds: @~[],
|
||||||
inputs: ~[],
|
inputs: ~[],
|
||||||
output: ty::mk_nil(tcx),
|
output: ty::mk_nil(tcx),
|
||||||
ret_style: ast::return_val}))
|
ret_style: ast::return_val}))
|
||||||
|
|
|
@ -961,6 +961,7 @@ fn trans_intrinsic(ccx: @crate_ctxt, decl: ValueRef, item: @ast::foreign_item,
|
||||||
let fty = ty::mk_fn(bcx.tcx(), {
|
let fty = ty::mk_fn(bcx.tcx(), {
|
||||||
purity: ast::impure_fn,
|
purity: ast::impure_fn,
|
||||||
proto: ast::proto_block,
|
proto: ast::proto_block,
|
||||||
|
bounds: @~[],
|
||||||
inputs: ~[{
|
inputs: ~[{
|
||||||
mode: ast::expl(ast::by_val),
|
mode: ast::expl(ast::by_val),
|
||||||
ty: ty::mk_imm_ptr(
|
ty: ty::mk_imm_ptr(
|
||||||
|
|
|
@ -316,11 +316,13 @@ enum closure_kind {
|
||||||
///
|
///
|
||||||
/// - `purity` is the function's effect (pure, impure, unsafe).
|
/// - `purity` is the function's effect (pure, impure, unsafe).
|
||||||
/// - `proto` is the protocol (fn@, fn~, etc).
|
/// - `proto` is the protocol (fn@, fn~, etc).
|
||||||
|
/// - `bound` is the parameter bounds on the function's upvars.
|
||||||
/// - `inputs` is the list of arguments and their modes.
|
/// - `inputs` is the list of arguments and their modes.
|
||||||
/// - `output` is the return type.
|
/// - `output` is the return type.
|
||||||
/// - `ret_style`indicates whether the function returns a value or fails.
|
/// - `ret_style` indicates whether the function returns a value or fails.
|
||||||
type fn_ty = {purity: ast::purity,
|
type fn_ty = {purity: ast::purity,
|
||||||
proto: ast::proto,
|
proto: ast::proto,
|
||||||
|
bounds: @~[param_bound],
|
||||||
inputs: ~[arg],
|
inputs: ~[arg],
|
||||||
output: t,
|
output: t,
|
||||||
ret_style: ret_style};
|
ret_style: ret_style};
|
||||||
|
|
|
@ -246,7 +246,7 @@ fn check_main_fn_ty(ccx: @crate_ctxt,
|
||||||
let tcx = ccx.tcx;
|
let tcx = ccx.tcx;
|
||||||
let main_t = ty::node_id_to_type(tcx, main_id);
|
let main_t = ty::node_id_to_type(tcx, main_id);
|
||||||
match ty::get(main_t).struct {
|
match ty::get(main_t).struct {
|
||||||
ty::ty_fn({purity: ast::impure_fn, proto: ast::proto_bare,
|
ty::ty_fn({purity: ast::impure_fn, proto: ast::proto_bare, bounds,
|
||||||
inputs, output, ret_style: ast::return_val}) => {
|
inputs, output, ret_style: ast::return_val}) => {
|
||||||
match tcx.items.find(main_id) {
|
match tcx.items.find(main_id) {
|
||||||
some(ast_map::node_item(it,_)) => {
|
some(ast_map::node_item(it,_)) => {
|
||||||
|
|
|
@ -261,8 +261,10 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy owned>(
|
||||||
};
|
};
|
||||||
ty::mk_rec(tcx, flds)
|
ty::mk_rec(tcx, flds)
|
||||||
}
|
}
|
||||||
ast::ty_fn(proto, decl) => {
|
ast::ty_fn(proto, ast_bounds, decl) => {
|
||||||
ty::mk_fn(tcx, ty_of_fn_decl(self, rscope, proto, decl, none))
|
let bounds = collect::compute_bounds(self.ccx(), ast_bounds);
|
||||||
|
let fn_decl = ty_of_fn_decl(self, rscope, proto, bounds, decl, none);
|
||||||
|
ty::mk_fn(tcx, fn_decl)
|
||||||
}
|
}
|
||||||
ast::ty_path(path, id) => {
|
ast::ty_path(path, id) => {
|
||||||
let a_def = match tcx.def_map.find(id) {
|
let a_def = match tcx.def_map.find(id) {
|
||||||
|
@ -398,6 +400,7 @@ type expected_tys = option<{inputs: ~[ty::arg],
|
||||||
fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
|
fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
|
||||||
self: AC, rscope: RS,
|
self: AC, rscope: RS,
|
||||||
proto: ast::proto,
|
proto: ast::proto,
|
||||||
|
bounds: @~[ty::param_bound],
|
||||||
decl: ast::fn_decl,
|
decl: ast::fn_decl,
|
||||||
expected_tys: expected_tys) -> ty::fn_ty {
|
expected_tys: expected_tys) -> ty::fn_ty {
|
||||||
|
|
||||||
|
@ -423,7 +426,7 @@ fn ty_of_fn_decl<AC: ast_conv, RS: region_scope copy owned>(
|
||||||
_ => ast_ty_to_ty(self, rb, decl.output)
|
_ => ast_ty_to_ty(self, rb, decl.output)
|
||||||
};
|
};
|
||||||
|
|
||||||
{purity: decl.purity, proto: proto, inputs: input_tys,
|
{purity: decl.purity, proto: proto, bounds: bounds, inputs: input_tys,
|
||||||
output: output_ty, ret_style: decl.cf}
|
output: output_ty, ret_style: decl.cf}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1135,7 +1135,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||||
};
|
};
|
||||||
|
|
||||||
// construct the function type
|
// construct the function type
|
||||||
let fn_ty = astconv::ty_of_fn_decl(fcx, fcx, proto,
|
let fn_ty = astconv::ty_of_fn_decl(fcx, fcx, proto, @~[],
|
||||||
decl, expected_tys);
|
decl, expected_tys);
|
||||||
let fty = ty::mk_fn(tcx, fn_ty);
|
let fty = ty::mk_fn(tcx, fn_ty);
|
||||||
|
|
||||||
|
@ -2401,6 +2401,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||||
let fty = ty::mk_fn(ccx.tcx, {
|
let fty = ty::mk_fn(ccx.tcx, {
|
||||||
purity: ast::impure_fn,
|
purity: ast::impure_fn,
|
||||||
proto: ast::proto_block,
|
proto: ast::proto_block,
|
||||||
|
bounds: @~[],
|
||||||
inputs: ~[{
|
inputs: ~[{
|
||||||
mode: ast::expl(ast::by_val),
|
mode: ast::expl(ast::by_val),
|
||||||
ty: ty::mk_imm_ptr(
|
ty: ty::mk_imm_ptr(
|
||||||
|
@ -2420,6 +2421,7 @@ fn check_intrinsic_type(ccx: @crate_ctxt, it: @ast::foreign_item) {
|
||||||
};
|
};
|
||||||
let fty = ty::mk_fn(tcx, {purity: ast::impure_fn,
|
let fty = ty::mk_fn(tcx, {purity: ast::impure_fn,
|
||||||
proto: ast::proto_bare,
|
proto: ast::proto_bare,
|
||||||
|
bounds: @~[],
|
||||||
inputs: inputs, output: output,
|
inputs: inputs, output: output,
|
||||||
ret_style: ast::return_val});
|
ret_style: ast::return_val});
|
||||||
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
|
let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
|
||||||
|
|
|
@ -125,6 +125,7 @@ fn get_enum_variant_types(ccx: @crate_ctxt,
|
||||||
});
|
});
|
||||||
ty::mk_fn(tcx, {purity: ast::pure_fn,
|
ty::mk_fn(tcx, {purity: ast::pure_fn,
|
||||||
proto: ast::proto_box,
|
proto: ast::proto_box,
|
||||||
|
bounds: @~[],
|
||||||
inputs: args,
|
inputs: args,
|
||||||
output: enum_ty,
|
output: enum_ty,
|
||||||
ret_style: ast::return_val})
|
ret_style: ast::return_val})
|
||||||
|
@ -396,6 +397,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
||||||
let t_ctor = ty::mk_fn(
|
let t_ctor = ty::mk_fn(
|
||||||
tcx, {purity: ast::impure_fn,
|
tcx, {purity: ast::impure_fn,
|
||||||
proto: ast::proto_block,
|
proto: ast::proto_block,
|
||||||
|
bounds: @~[],
|
||||||
inputs: t_args,
|
inputs: t_args,
|
||||||
output: t_res,
|
output: t_res,
|
||||||
ret_style: ast::return_val});
|
ret_style: ast::return_val});
|
||||||
|
@ -410,7 +412,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
|
||||||
// Write the dtor type
|
// Write the dtor type
|
||||||
let t_dtor = ty::mk_fn(
|
let t_dtor = ty::mk_fn(
|
||||||
tcx,
|
tcx,
|
||||||
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_block,
|
ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_block, @~[],
|
||||||
ast_util::dtor_dec(), none));
|
ast_util::dtor_dec(), none));
|
||||||
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
|
write_ty_to_tcx(tcx, dtor.node.id, t_dtor);
|
||||||
tcx.tcache.insert(local_def(dtor.node.id),
|
tcx.tcache.insert(local_def(dtor.node.id),
|
||||||
|
@ -460,9 +462,10 @@ fn convert_foreign(ccx: @crate_ctxt, i: @ast::foreign_item) {
|
||||||
fn ty_of_method(ccx: @crate_ctxt,
|
fn ty_of_method(ccx: @crate_ctxt,
|
||||||
m: @ast::method,
|
m: @ast::method,
|
||||||
rp: bool) -> ty::method {
|
rp: bool) -> ty::method {
|
||||||
|
// XXX: Are the bounds correct here?
|
||||||
{ident: m.ident,
|
{ident: m.ident,
|
||||||
tps: ty_param_bounds(ccx, m.tps),
|
tps: ty_param_bounds(ccx, m.tps),
|
||||||
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare,
|
fty: ty_of_fn_decl(ccx, type_rscope(rp), ast::proto_bare, @~[],
|
||||||
m.decl, none),
|
m.decl, none),
|
||||||
self_ty: m.self_ty.node,
|
self_ty: m.self_ty.node,
|
||||||
purity: m.decl.purity,
|
purity: m.decl.purity,
|
||||||
|
@ -474,8 +477,8 @@ fn ty_of_ty_method(self: @crate_ctxt,
|
||||||
rp: bool) -> ty::method {
|
rp: bool) -> ty::method {
|
||||||
{ident: m.ident,
|
{ident: m.ident,
|
||||||
tps: ty_param_bounds(self, m.tps),
|
tps: ty_param_bounds(self, m.tps),
|
||||||
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare,
|
fty: ty_of_fn_decl(self, type_rscope(rp), ast::proto_bare, @~[], m.decl,
|
||||||
m.decl, none),
|
none),
|
||||||
// assume public, because this is only invoked on trait methods
|
// assume public, because this is only invoked on trait methods
|
||||||
self_ty: m.self_ty.node,
|
self_ty: m.self_ty.node,
|
||||||
purity: m.decl.purity, vis: ast::public}
|
purity: m.decl.purity, vis: ast::public}
|
||||||
|
@ -528,8 +531,8 @@ fn ty_of_item(ccx: @crate_ctxt, it: @ast::item)
|
||||||
}
|
}
|
||||||
ast::item_fn(decl, tps, _) => {
|
ast::item_fn(decl, tps, _) => {
|
||||||
let bounds = ty_param_bounds(ccx, tps);
|
let bounds = ty_param_bounds(ccx, tps);
|
||||||
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare,
|
let tofd = ty_of_fn_decl(ccx, empty_rscope, ast::proto_bare, @~[],
|
||||||
decl, none);
|
decl, none);
|
||||||
let tpt = {bounds: bounds,
|
let tpt = {bounds: bounds,
|
||||||
rp: false, // functions do not have a self
|
rp: false, // functions do not have a self
|
||||||
ty: ty::mk_fn(ccx.tcx, tofd)};
|
ty: ty::mk_fn(ccx.tcx, tofd)};
|
||||||
|
@ -599,40 +602,42 @@ fn ty_of_foreign_item(ccx: @crate_ctxt, it: @ast::foreign_item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn compute_bounds(ccx: @crate_ctxt,
|
||||||
|
ast_bounds: @~[ast::ty_param_bound]) -> ty::param_bounds {
|
||||||
|
@do vec::flat_map(*ast_bounds) |b| {
|
||||||
|
match b {
|
||||||
|
ast::bound_send => ~[ty::bound_send],
|
||||||
|
ast::bound_copy => ~[ty::bound_copy],
|
||||||
|
ast::bound_const => ~[ty::bound_const],
|
||||||
|
ast::bound_owned => ~[ty::bound_owned],
|
||||||
|
ast::bound_trait(t) => {
|
||||||
|
let ity = ast_ty_to_ty(ccx, empty_rscope, t);
|
||||||
|
match ty::get(ity).struct {
|
||||||
|
ty::ty_trait(*) => {
|
||||||
|
~[ty::bound_trait(ity)]
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
ccx.tcx.sess.span_err(
|
||||||
|
t.span, ~"type parameter bounds must be \
|
||||||
|
trait types");
|
||||||
|
~[]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ty_param_bounds(ccx: @crate_ctxt,
|
fn ty_param_bounds(ccx: @crate_ctxt,
|
||||||
params: ~[ast::ty_param]) -> @~[ty::param_bounds] {
|
params: ~[ast::ty_param]) -> @~[ty::param_bounds] {
|
||||||
|
|
||||||
fn compute_bounds(ccx: @crate_ctxt,
|
|
||||||
param: ast::ty_param) -> ty::param_bounds {
|
|
||||||
@do vec::flat_map(*param.bounds) |b| {
|
|
||||||
match b {
|
|
||||||
ast::bound_send => ~[ty::bound_send],
|
|
||||||
ast::bound_copy => ~[ty::bound_copy],
|
|
||||||
ast::bound_const => ~[ty::bound_const],
|
|
||||||
ast::bound_owned => ~[ty::bound_owned],
|
|
||||||
ast::bound_trait(t) => {
|
|
||||||
let ity = ast_ty_to_ty(ccx, empty_rscope, t);
|
|
||||||
match ty::get(ity).struct {
|
|
||||||
ty::ty_trait(*) => {
|
|
||||||
~[ty::bound_trait(ity)]
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
ccx.tcx.sess.span_err(
|
|
||||||
t.span, ~"type parameter bounds must be \
|
|
||||||
trait types");
|
|
||||||
~[]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@do params.map |param| {
|
@do params.map |param| {
|
||||||
match ccx.tcx.ty_param_bounds.find(param.id) {
|
match ccx.tcx.ty_param_bounds.find(param.id) {
|
||||||
some(bs) => bs,
|
some(bs) => bs,
|
||||||
none => {
|
none => {
|
||||||
let bounds = compute_bounds(ccx, param);
|
let bounds = compute_bounds(ccx, param.bounds);
|
||||||
ccx.tcx.ty_param_bounds.insert(param.id, bounds);
|
ccx.tcx.ty_param_bounds.insert(param.id, bounds);
|
||||||
bounds
|
bounds
|
||||||
}
|
}
|
||||||
|
@ -652,6 +657,7 @@ fn ty_of_foreign_fn_decl(ccx: @crate_ctxt,
|
||||||
|
|
||||||
let t_fn = ty::mk_fn(ccx.tcx, {purity: decl.purity,
|
let t_fn = ty::mk_fn(ccx.tcx, {purity: decl.purity,
|
||||||
proto: ast::proto_bare,
|
proto: ast::proto_bare,
|
||||||
|
bounds: @~[],
|
||||||
inputs: input_tys,
|
inputs: input_tys,
|
||||||
output: output_ty,
|
output: output_ty,
|
||||||
ret_style: ast::return_val});
|
ret_style: ast::return_val});
|
||||||
|
|
|
@ -1717,6 +1717,7 @@ fn super_fns<C:combine>(
|
||||||
// b_f.constraints).then {||
|
// b_f.constraints).then {||
|
||||||
ok({purity: purity,
|
ok({purity: purity,
|
||||||
proto: p,
|
proto: p,
|
||||||
|
bounds: a_f.bounds, // XXX: This is wrong!
|
||||||
inputs: inputs,
|
inputs: inputs,
|
||||||
output: output,
|
output: output,
|
||||||
ret_style: rs})
|
ret_style: rs})
|
||||||
|
|
7
src/test/run-pass/bounded-fn-type.rs
Normal file
7
src/test/run-pass/bounded-fn-type.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
fn ignore<T>(_x: T) {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let f: fn@:send() = ||();
|
||||||
|
ignore(f);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue