auto merge of #11595 : eddyb/rust/env-et-self-no-more, r=nikomatsakis

Non-exhaustive change list:
* `self` is now present in argument lists (modulo type-checking code I don't trust myself to refactor)
* methods have the same calling convention as bare functions (including the self argument)
* the env param is gone from all bare functions (and methods), only used by closures and `proc`s
* bare functions can only be coerced to closures and `proc`s if they are statically resolved, as they now require creating a wrapper specific to that function, to avoid indirect wrappers (equivalent to `impl<..Args, Ret> Fn<..Args, Ret> for fn(..Args) -> Ret`) that might not be optimizable by LLVM and don't work for `proc`s
* refactored some `trans::closure` code, leading to the removal of `trans::glue::make_free_glue` and `ty_opaque_closure_ptr`
This commit is contained in:
bors 2014-01-27 09:31:44 -08:00
commit d6d7812da8
88 changed files with 1437 additions and 2139 deletions

View file

@ -895,7 +895,7 @@ fn run_test_inner(desc: TestDesc,
return;
}
StaticBenchFn(benchfn) => {
let bs = ::test::bench::benchmark(benchfn);
let bs = ::test::bench::benchmark(|harness| benchfn(harness));
monitor_ch.send((desc, TrBench(bs)));
return;
}

View file

@ -176,24 +176,23 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
pub static tag_item_method_tps: uint = 0x7b;
pub static tag_item_method_fty: uint = 0x7c;
pub static tag_item_method_transformed_self_ty: uint = 0x7d;
pub static tag_mod_child: uint = 0x7e;
pub static tag_misc_info: uint = 0x7f;
pub static tag_misc_info_crate_items: uint = 0x80;
pub static tag_mod_child: uint = 0x7d;
pub static tag_misc_info: uint = 0x7e;
pub static tag_misc_info_crate_items: uint = 0x7f;
pub static tag_item_method_provided_source: uint = 0x81;
pub static tag_item_impl_vtables: uint = 0x82;
pub static tag_item_method_provided_source: uint = 0x80;
pub static tag_item_impl_vtables: uint = 0x81;
pub static tag_impls: uint = 0x83;
pub static tag_impls_impl: uint = 0x84;
pub static tag_impls: uint = 0x82;
pub static tag_impls_impl: uint = 0x83;
pub static tag_items_data_item_inherent_impl: uint = 0x85;
pub static tag_items_data_item_extension_impl: uint = 0x86;
pub static tag_items_data_item_inherent_impl: uint = 0x84;
pub static tag_items_data_item_extension_impl: uint = 0x85;
pub static tag_path_elem_pretty_name: uint = 0x87;
pub static tag_path_elem_pretty_name_ident: uint = 0x88;
pub static tag_path_elem_pretty_name_extra: uint = 0x89;
pub static tag_path_elem_pretty_name: uint = 0x86;
pub static tag_path_elem_pretty_name_ident: uint = 0x87;
pub static tag_path_elem_pretty_name_extra: uint = 0x88;
pub static tag_region_param_def: uint = 0x100;
pub static tag_region_param_def_ident: uint = 0x101;

View file

@ -227,16 +227,6 @@ fn doc_method_fty(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::BareFnTy {
|_, did| translate_def_id(cdata, did))
}
fn doc_transformed_self_ty(doc: ebml::Doc,
tcx: ty::ctxt,
cdata: Cmd) -> Option<ty::t>
{
reader::maybe_get_doc(doc, tag_item_method_transformed_self_ty).map(|tp| {
parse_ty_data(tp.data, cdata.cnum, tp.start, tcx,
|_, did| translate_def_id(cdata, did))
})
}
pub fn item_type(_item_id: ast::DefId, item: ebml::Doc,
tcx: ty::ctxt, cdata: Cmd) -> ty::t {
doc_type(item, tcx, cdata)
@ -781,9 +771,9 @@ fn get_mutability(ch: u8) -> ast::Mutability {
let explicit_self_kind = string[0];
match explicit_self_kind as char {
's' => ast::SelfStatic,
'v' => ast::SelfValue(get_mutability(string[1])),
'v' => ast::SelfValue,
'@' => ast::SelfBox,
'~' => ast::SelfUniq(get_mutability(string[1])),
'~' => ast::SelfUniq,
// FIXME(#4846) expl. region
'&' => ast::SelfRegion(None, get_mutability(string[1])),
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
@ -847,7 +837,6 @@ pub fn get_method(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId,
let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
tag_item_method_tps);
let rp_defs = item_region_param_defs(method_doc, tcx, cdata);
let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata);
let fty = doc_method_fty(method_doc, tcx, cdata);
let vis = item_visibility(method_doc);
let explicit_self = get_explicit_self(method_doc);
@ -859,7 +848,6 @@ pub fn get_method(intr: @IdentInterner, cdata: Cmd, id: ast::NodeId,
type_param_defs: type_param_defs,
region_param_defs: rp_defs,
},
transformed_self_ty,
fty,
explicit_self,
vis,

View file

@ -261,16 +261,6 @@ fn encode_type(ecx: &EncodeContext,
ebml_w.end_tag();
}
fn encode_transformed_self_ty(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
opt_typ: Option<ty::t>) {
for &typ in opt_typ.iter() {
ebml_w.start_tag(tag_item_method_transformed_self_ty);
write_type(ecx, ebml_w, typ);
ebml_w.end_tag();
}
}
fn encode_method_fty(ecx: &EncodeContext,
ebml_w: &mut writer::Encoder,
typ: &ty::BareFnTy) {
@ -679,23 +669,13 @@ fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::Explic
// Encode the base self type.
match explicit_self {
SelfStatic => {
ebml_w.writer.write(&[ 's' as u8 ]);
}
SelfValue(m) => {
ebml_w.writer.write(&[ 'v' as u8 ]);
encode_mutability(ebml_w, m);
}
SelfStatic => ebml_w.writer.write(&[ 's' as u8 ]),
SelfValue => ebml_w.writer.write(&[ 'v' as u8 ]),
SelfBox => ebml_w.writer.write(&[ '@' as u8 ]),
SelfUniq => ebml_w.writer.write(&[ '~' as u8 ]),
SelfRegion(_, m) => {
// FIXME(#4846) encode custom lifetime
ebml_w.writer.write(&[ '&' as u8 ]);
encode_mutability(ebml_w, m);
}
SelfBox => {
ebml_w.writer.write(&[ '@' as u8 ]);
}
SelfUniq(m) => {
ebml_w.writer.write(&[ '~' as u8 ]);
ebml_w.writer.write(&['&' as u8]);
encode_mutability(ebml_w, m);
}
}
@ -807,7 +787,6 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
encode_ty_type_param_defs(ebml_w, ecx,
method_ty.generics.type_param_defs,
tag_item_method_tps);
encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
encode_method_fty(ecx, ebml_w, &method_ty.fty);
encode_visibility(ebml_w, method_ty.vis);
encode_explicit_self(ebml_w, method_ty.explicit_self);

View file

@ -374,10 +374,6 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
return ty::mk_bare_fn(st.tcx, parse_bare_fn_ty(st, |x,y| conv(x,y)));
}
'Y' => return ty::mk_type(st.tcx),
'C' => {
let sigil = parse_sigil(st);
return ty::mk_opaque_closure_ptr(st.tcx, sigil);
}
'#' => {
let pos = parse_hex(st);
assert_eq!(next(st), ':');

View file

@ -327,10 +327,6 @@ fn enc_sty(w: &mut MemWriter, cx: @ctxt, st: &ty::sty) {
mywrite!(w, "s{}|", (cx.ds)(did));
}
ty::ty_type => mywrite!(w, "Y"),
ty::ty_opaque_closure_ptr(p) => {
mywrite!(w, "C&");
enc_sigil(w, p);
}
ty::ty_struct(def, ref substs) => {
mywrite!(w, "a[{}|", (cx.ds)(def));
enc_substs(w, cx, substs);

View file

@ -435,7 +435,6 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::Def {
ast::DefMethod(did0.tr(xcx), did1.map(|did1| did1.tr(xcx)))
}
ast::DefSelfTy(nid) => { ast::DefSelfTy(xcx.tr_id(nid)) }
ast::DefSelf(nid, m) => { ast::DefSelf(xcx.tr_id(nid), m) }
ast::DefMod(did) => { ast::DefMod(did.tr(xcx)) }
ast::DefForeignMod(did) => { ast::DefForeignMod(did.tr(xcx)) }
ast::DefStatic(did, m) => { ast::DefStatic(did.tr(xcx), m) }
@ -579,16 +578,8 @@ fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry;
}
fn encode_method_map_entry(ecx: &e::EncodeContext,
ebml_w: &mut writer::Encoder,
mme: method_map_entry) {
fn encode_method_map_entry(ebml_w: &mut writer::Encoder, mme: method_map_entry) {
ebml_w.emit_struct("method_map_entry", 3, |ebml_w| {
ebml_w.emit_struct_field("self_ty", 0u, |ebml_w| {
ebml_w.emit_ty(ecx, mme.self_ty);
});
ebml_w.emit_struct_field("explicit_self", 2u, |ebml_w| {
mme.explicit_self.encode(ebml_w);
});
ebml_w.emit_struct_field("origin", 1u, |ebml_w| {
mme.origin.encode(ebml_w);
});
@ -600,15 +591,6 @@ fn read_method_map_entry(&mut self, xcx: @ExtendedDecodeContext)
-> method_map_entry {
self.read_struct("method_map_entry", 3, |this| {
method_map_entry {
self_ty: this.read_struct_field("self_ty", 0u, |this| {
this.read_ty(xcx)
}),
explicit_self: this.read_struct_field("explicit_self",
2,
|this| {
let explicit_self: ast::ExplicitSelf_ = Decodable::decode(this);
explicit_self
}),
origin: this.read_struct_field("origin", 1, |this| {
let method_origin: method_origin =
Decodable::decode(this);
@ -1043,7 +1025,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
ebml_w.id(id);
ebml_w.tag(c::tag_table_val, |ebml_w| {
encode_method_map_entry(ecx, ebml_w, *mme)
encode_method_map_entry(ebml_w, *mme)
})
})
}

View file

@ -371,9 +371,7 @@ fn mark_variable_as_used_mut(this: &CheckLoanCtxt,
debug!("mark_writes_through_upvars_as_used_mut(cmt={})",
cmt.repr(this.tcx()));
match cmt.cat {
mc::cat_local(id) |
mc::cat_arg(id) |
mc::cat_self(id) => {
mc::cat_local(id) | mc::cat_arg(id) => {
let mut used_mut_nodes = this.tcx()
.used_mut_nodes
.borrow_mut();
@ -459,7 +457,6 @@ fn check_for_aliasability_violation(this: &CheckLoanCtxt,
mc::cat_rvalue(..) |
mc::cat_local(..) |
mc::cat_arg(_) |
mc::cat_self(..) |
mc::cat_deref(_, _, mc::unsafe_ptr(..)) |
mc::cat_static_item(..) |
mc::cat_deref(_, _, mc::gc_ptr) |
@ -790,7 +787,6 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
let method_map = this.bccx.method_map.borrow();
match expr.node {
ast::ExprSelf |
ast::ExprPath(..) => {
if !this.move_data.is_assignee(expr.id) {
let cmt = this.bccx.cat_expr_unadjusted(expr);
@ -808,32 +804,24 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
ast::ExprCall(f, ref args, _) => {
this.check_call(expr, Some(f), f.id, f.span, *args);
}
ast::ExprMethodCall(callee_id, _, _, _, ref args, _) => {
ast::ExprMethodCall(callee_id, _, _, ref args, _) => {
this.check_call(expr, None, callee_id, expr.span, *args);
}
ast::ExprIndex(callee_id, _, rval) |
ast::ExprBinary(callee_id, _, _, rval)
if method_map.get().contains_key(&expr.id) => {
this.check_call(expr,
None,
callee_id,
expr.span,
[rval]);
this.check_call(expr, None, callee_id, expr.span, [rval]);
}
ast::ExprUnary(callee_id, _, _) | ast::ExprIndex(callee_id, _, _)
if method_map.get().contains_key(&expr.id) => {
this.check_call(expr,
None,
callee_id,
expr.span,
[]);
this.check_call(expr, None, callee_id, expr.span, []);
}
ast::ExprInlineAsm(ref ia) => {
for &(_, out) in ia.outputs.iter() {
this.check_assignment(out);
}
}
_ => { }
_ => {}
}
}

View file

@ -133,8 +133,7 @@ fn check_is_legal_to_move_from(bccx: &BorrowckCtxt,
mc::cat_rvalue(..) |
mc::cat_local(..) |
mc::cat_arg(..) |
mc::cat_self(..) => {
mc::cat_arg(..) => {
true
}

View file

@ -76,7 +76,6 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option<ast::NodeId>) -> R {
mc::cat_copied_upvar(..) | // L-Local
mc::cat_local(..) | // L-Local
mc::cat_arg(..) | // L-Local
mc::cat_self(..) | // L-Local
mc::cat_deref(_, _, mc::region_ptr(..)) | // L-Deref-Borrowed
mc::cat_deref(_, _, mc::unsafe_ptr(..)) => {
let scope = self.scope(cmt);
@ -261,7 +260,6 @@ fn is_moved(&self, cmt: mc::cmt) -> bool {
match cmt.guarantor().cat {
mc::cat_local(id) |
mc::cat_self(id) |
mc::cat_arg(id) => {
let moved_variables_set = self.bccx
.moved_variables_set
@ -303,8 +301,7 @@ fn scope(&self, cmt: mc::cmt) -> ty::Region {
ty::ReStatic
}
mc::cat_local(local_id) |
mc::cat_arg(local_id) |
mc::cat_self(local_id) => {
mc::cat_arg(local_id) => {
ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id))
}
mc::cat_deref(_, _, mc::unsafe_ptr(..)) => {

View file

@ -74,8 +74,7 @@ fn restrict(&self,
}
mc::cat_local(local_id) |
mc::cat_arg(local_id) |
mc::cat_self(local_id) => {
mc::cat_arg(local_id) => {
// R-Variable
let lp = @LpVar(local_id);
SafeIf(lp, ~[Restriction {loan_path: lp,

View file

@ -25,6 +25,7 @@
use std::result::{Result};
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
use syntax::codemap::Span;
use syntax::parse::token;
use syntax::visit;
@ -294,9 +295,7 @@ pub fn opt_loan_path(cmt: mc::cmt) -> Option<@LoanPath> {
None
}
mc::cat_local(id) |
mc::cat_arg(id) |
mc::cat_self(id) => {
mc::cat_local(id) | mc::cat_arg(id) => {
Some(@LpVar(id))
}
@ -771,8 +770,18 @@ pub fn append_loan_path_to_str(&self,
match *loan_path {
LpVar(id) => {
match self.tcx.items.find(id) {
Some(ast_map::NodeLocal(ref ident, _)) => {
out.push_str(token::ident_to_str(ident));
Some(ast_map::NodeLocal(pat)) => {
match pat.node {
ast::PatIdent(_, ref path, _) => {
let ident = ast_util::path_to_ident(path);
out.push_str(token::ident_to_str(&ident));
}
_ => {
self.tcx.sess.bug(
format!("Loan path LpVar({:?}) maps to {:?}, not local",
id, pat));
}
}
}
r => {
self.tcx.sess.bug(

View file

@ -355,8 +355,8 @@ fn expr(&mut self, expr: @ast::Expr, pred: CFGIndex) -> CFGIndex {
self.call(expr, pred, func, *args)
}
ast::ExprMethodCall(_, rcvr, _, _, ref args, _) => {
self.call(expr, pred, rcvr, *args)
ast::ExprMethodCall(_, _, _, ref args, _) => {
self.call(expr, pred, args[0], args.slice_from(1))
}
ast::ExprIndex(_, l, r) |
@ -410,7 +410,6 @@ fn expr(&mut self, expr: @ast::Expr, pred: CFGIndex) -> CFGIndex {
ast::ExprLogLevel |
ast::ExprMac(..) |
ast::ExprInlineAsm(..) |
ast::ExprSelf |
ast::ExprFnBlock(..) |
ast::ExprProc(..) |
ast::ExprLit(..) |

View file

@ -668,24 +668,21 @@ fn walk_expr(&mut self,
}
ast::ExprCall(f, ref args, _) => {
self.walk_call(f.id, expr.id,
f, *args, in_out, loop_scopes);
self.walk_expr(f, in_out, loop_scopes);
self.walk_call(f.id, expr.id, *args, in_out, loop_scopes);
}
ast::ExprMethodCall(callee_id, rcvr, _, _, ref args, _) => {
self.walk_call(callee_id, expr.id,
rcvr, *args, in_out, loop_scopes);
ast::ExprMethodCall(callee_id, _, _, ref args, _) => {
self.walk_call(callee_id, expr.id, *args, in_out, loop_scopes);
}
ast::ExprIndex(callee_id, l, r) |
ast::ExprBinary(callee_id, _, l, r) if self.is_method_call(expr) => {
self.walk_call(callee_id, expr.id,
l, [r], in_out, loop_scopes);
self.walk_call(callee_id, expr.id, [l, r], in_out, loop_scopes);
}
ast::ExprUnary(callee_id, _, e) if self.is_method_call(expr) => {
self.walk_call(callee_id, expr.id,
e, [], in_out, loop_scopes);
self.walk_call(callee_id, expr.id, [e], in_out, loop_scopes);
}
ast::ExprTup(ref exprs) => {
@ -706,9 +703,7 @@ fn walk_expr(&mut self,
ast::ExprLogLevel |
ast::ExprLit(..) |
ast::ExprPath(..) |
ast::ExprSelf => {
}
ast::ExprPath(..) => {}
ast::ExprAddrOf(_, e) |
ast::ExprDoBody(e) |
@ -813,11 +808,9 @@ fn walk_opt_expr(&mut self,
fn walk_call(&mut self,
_callee_id: ast::NodeId,
call_id: ast::NodeId,
arg0: &ast::Expr,
args: &[@ast::Expr],
in_out: &mut [uint],
loop_scopes: &mut ~[LoopScope]) {
self.walk_expr(arg0, in_out, loop_scopes);
self.walk_exprs(args, in_out, loop_scopes);
// FIXME(#6268) nested method calls

View file

@ -120,7 +120,7 @@ fn visit_block(&mut self, block: &ast::Block, _:()) {
fn visit_expr(&mut self, expr: &ast::Expr, _:()) {
match expr.node {
ast::ExprMethodCall(callee_id, _, _, _, _, _) => {
ast::ExprMethodCall(callee_id, _, _, _, _) => {
let base_type = ty::node_id_to_type(self.tcx, callee_id);
debug!("effect: method call case, base type is {}",
ppaux::ty_to_str(self.tcx, base_type));

View file

@ -48,7 +48,7 @@ fn visit_expr(&mut self, expr: &ast::Expr, depth: int) {
ast::ExprFnBlock(..) | ast::ExprProc(..) => {
visit::walk_expr(self, expr, depth + 1)
}
ast::ExprPath(..) | ast::ExprSelf => {
ast::ExprPath(..) => {
let mut i = 0;
let def_map = self.def_map.borrow();
match def_map.get().find(&expr.id) {

View file

@ -454,9 +454,8 @@ fn check_imm_free_var(cx: &Context, def: Def, sp: Span) {
sp,
"mutable variables cannot be implicitly captured");
}
DefLocal(..) | DefArg(..) => { /* ok */ }
DefLocal(..) | DefArg(..) | DefBinding(..) => { /* ok */ }
DefUpvar(_, def1, _, _) => { check_imm_free_var(cx, *def1, sp); }
DefBinding(..) | DefSelf(..) => { /*ok*/ }
_ => {
cx.tcx.sess.span_bug(
sp,

View file

@ -405,20 +405,6 @@ fn visit_fn(v: &mut LivenessVisitor,
})
};
// Add `this`, whether explicit or implicit.
match *fk {
visit::FkMethod(_, _, method) => {
match method.explicit_self.node {
SelfValue(_) | SelfRegion(..) | SelfBox | SelfUniq(_) => {
fn_maps.add_variable(Arg(method.self_id,
special_idents::self_));
}
SelfStatic => {}
}
}
visit::FkItemFn(..) | visit::FkFnBlock(..) => {}
}
// gather up the various local variables, significant expressions,
// and so forth:
visit::walk_fn(v, fk, decl, body, sp, id, fn_maps);
@ -493,7 +479,7 @@ fn visit_arm(v: &mut LivenessVisitor, arm: &Arm, this: @IrMaps) {
fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
match expr.node {
// live nodes required for uses or definitions of variables:
ExprPath(_) | ExprSelf => {
ExprPath(_) => {
let def_map = this.tcx.def_map.borrow();
let def = def_map.get().get_copy(&expr.id);
debug!("expr {}: path that leads to {:?}", expr.id, def);
@ -1050,7 +1036,7 @@ pub fn propagate_through_expr(&self, expr: @Expr, succ: LiveNode)
match expr.node {
// Interesting cases with control flow or which gen/kill
ExprPath(_) | ExprSelf => {
ExprPath(_) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
}
@ -1229,14 +1215,13 @@ pub fn propagate_through_expr(&self, expr: @Expr, succ: LiveNode)
self.propagate_through_expr(f, succ)
}
ExprMethodCall(callee_id, rcvr, _, _, ref args, _) => {
ExprMethodCall(callee_id, _, _, ref args, _) => {
// calling a method with bot return type means that the method
// will fail, and hence the successors can be ignored
let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, callee_id));
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
else {succ};
let succ = self.propagate_through_exprs(*args, succ);
self.propagate_through_expr(rcvr, succ)
self.propagate_through_exprs(*args, succ)
}
ExprTup(ref exprs) => {
@ -1549,7 +1534,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprPath(..) |
ExprSelf(..) | ExprBox(..) => {
ExprBox(..) => {
visit::walk_expr(this, expr, ());
}
ExprForLoop(..) => fail!("non-desugared expr_for_loop")
@ -1694,9 +1679,13 @@ pub fn warn_about_unused_args(&self, decl: &FnDecl, entry_ln: LiveNode) {
for arg in decl.inputs.iter() {
pat_util::pat_bindings(self.tcx.def_map,
arg.pat,
|_bm, p_id, sp, _n| {
|_bm, p_id, sp, path| {
let var = self.variable(p_id, sp);
self.warn_about_unused(sp, p_id, entry_ln, var);
// Ignore unused self.
let ident = ast_util::path_to_ident(path);
if ident.name != special_idents::self_.name {
self.warn_about_unused(sp, p_id, entry_ln, var);
}
})
}
}

View file

@ -70,7 +70,6 @@ pub enum categorization {
cat_interior(cmt, InteriorKind), // something interior: field, tuple, etc
cat_downcast(cmt), // selects a particular enum variant (..)
cat_discr(cmt, ast::NodeId), // match discriminant (see preserve())
cat_self(ast::NodeId), // explicit `self`
// (..) downcast is only required if the enum has more than one variant
}
@ -426,7 +425,7 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> cmt {
self.cat_index(expr, base_cmt, 0)
}
ast::ExprPath(_) | ast::ExprSelf => {
ast::ExprPath(_) => {
let def_map = self.tcx.def_map.borrow();
let def = def_map.get().get_copy(&expr.id);
self.cat_def(expr.id, expr.span, expr_ty, def)
@ -503,16 +502,6 @@ pub fn cat_def(&self,
}
}
ast::DefSelf(self_id, mutbl) => {
@cmt_ {
id:id,
span:span,
cat:cat_self(self_id),
mutbl: if mutbl { McDeclared } else { McImmutable },
ty:expr_ty
}
}
ast::DefUpvar(upvar_id, inner, fn_node_id, _) => {
let ty = ty::node_id_to_type(self.tcx, fn_node_id);
match ty::get(ty).sty {
@ -1032,9 +1021,6 @@ pub fn cmt_to_str(&self, cmt: cmt) -> ~str {
cat_local(_) => {
~"local variable"
}
cat_self(_) => {
~"self value"
}
cat_arg(..) => {
~"argument"
}
@ -1129,7 +1115,6 @@ pub fn guarantor(@self) -> cmt {
cat_static_item |
cat_copied_upvar(..) |
cat_local(..) |
cat_self(..) |
cat_arg(..) |
cat_deref(_, _, unsafe_ptr(..)) |
cat_deref(_, _, gc_ptr) |
@ -1165,7 +1150,6 @@ pub fn freely_aliasable(&self) -> Option<AliasableReason> {
cat_rvalue(..) |
cat_local(..) |
cat_arg(_) |
cat_self(..) |
cat_deref(_, _, unsafe_ptr(..)) | // of course it is aliasable, but...
cat_deref(_, _, region_ptr(MutMutable, _)) => {
None
@ -1212,7 +1196,6 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
cat_rvalue(..) |
cat_copied_upvar(..) |
cat_local(..) |
cat_self(..) |
cat_arg(..) => {
format!("{:?}", *self)
}

View file

@ -227,10 +227,9 @@ pub fn compute_moves(tcx: ty::ctxt,
pub fn moved_variable_node_id_from_def(def: Def) -> Option<NodeId> {
match def {
DefBinding(nid, _) |
DefArg(nid, _) |
DefLocal(nid, _) |
DefSelf(nid, _) => Some(nid),
DefBinding(nid, _) |
DefArg(nid, _) |
DefLocal(nid, _) => Some(nid),
_ => None
}
@ -344,7 +343,7 @@ pub fn use_expr(&mut self,
debug!("comp_mode = {:?}", comp_mode);
match expr.node {
ExprPath(..) | ExprSelf => {
ExprPath(..) => {
match comp_mode {
Move => {
let def_map = self.tcx.def_map.borrow();
@ -413,10 +412,7 @@ pub fn use_expr(&mut self,
self.use_fn_args(callee.id, *args);
}
ExprMethodCall(callee_id, rcvr, _, _, ref args, _) => { // callee.m(args)
// Implicit self is equivalent to & mode, but every
// other kind should be + mode.
self.use_receiver(rcvr);
ExprMethodCall(callee_id, _, _, ref args, _) => { // callee.m(args)
self.use_fn_args(callee_id, *args);
}
@ -620,7 +616,7 @@ pub fn use_overloaded_operator(&mut self,
return false;
}
self.use_receiver(receiver_expr);
self.use_fn_arg(receiver_expr);
// for overloaded operatrs, we are always passing in a
// reference, so it's always read mode:
@ -675,11 +671,6 @@ pub fn use_pat(&mut self, pat: @Pat) {
})
}
pub fn use_receiver(&mut self,
receiver_expr: @Expr) {
self.use_fn_arg(receiver_expr);
}
pub fn use_fn_args(&mut self,
_: NodeId,
arg_exprs: &[@Expr]) {

View file

@ -688,9 +688,9 @@ fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
_ => {}
}
}
ast::ExprMethodCall(_, base, ident, _, _, _) => {
ast::ExprMethodCall(_, ident, _, ref args, _) => {
// see above
let t = ty::type_autoderef(ty::expr_ty(self.tcx, base));
let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
match ty::get(t).sty {
ty::ty_enum(_, _) | ty::ty_struct(_, _) => {
let method_map = self.method_map.borrow();

View file

@ -820,12 +820,6 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor,
// The arguments and `self` are parented to the body of the fn.
let decl_cx = Context {parent: Some(body.id),
var_parent: Some(body.id)};
match *fk {
visit::FkMethod(_, _, method) => {
visitor.region_maps.record_var_scope(method.self_id, body.id);
}
_ => {}
}
visit::walk_fn_decl(visitor, decl, decl_cx);
// The body of the fn itself is either a root scope (top-level fn)

View file

@ -130,11 +130,6 @@ enum NameDefinition {
ImportNameDefinition(Def, LastPrivate) //< The name identifies an import.
}
enum SelfBinding {
NoSelfBinding,
HasSelfBinding(NodeId, ExplicitSelf)
}
impl Visitor<()> for Resolver {
fn visit_item(&mut self, item: &Item, _: ()) {
self.resolve_item(item);
@ -258,12 +253,6 @@ enum ModulePrefixResult {
PrefixFound(@Module, uint)
}
#[deriving(Eq)]
enum AllowCapturingSelfFlag {
AllowCapturingSelf, //< The "self" definition can be captured.
DontAllowCapturingSelf, //< The "self" definition cannot be captured.
}
#[deriving(Eq)]
enum NameSearchType {
/// We're doing a name search in order to resolve a `use` directive.
@ -294,7 +283,6 @@ enum DuplicateCheckingMode {
/// One local scope.
struct Rib {
bindings: RefCell<HashMap<Name, DefLike>>,
self_binding: RefCell<Option<DefLike>>,
kind: RibKind,
}
@ -302,7 +290,6 @@ impl Rib {
fn new(kind: RibKind) -> Rib {
Rib {
bindings: RefCell::new(HashMap::new()),
self_binding: RefCell::new(None),
kind: kind
}
}
@ -1746,8 +1733,8 @@ trait method '{}'",
ignoring {:?}", def);
// Ignored; handled elsewhere.
}
DefSelf(..) | DefArg(..) | DefLocal(..) |
DefPrimTy(..) | DefTyParam(..) | DefBinding(..) |
DefArg(..) | DefLocal(..) | DefPrimTy(..) |
DefTyParam(..) | DefBinding(..) |
DefUse(..) | DefUpvar(..) | DefRegion(..) |
DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
fail!("didn't expect `{:?}`", def);
@ -3469,8 +3456,7 @@ fn upvarify(&mut self,
ribs: &mut ~[@Rib],
rib_index: uint,
def_like: DefLike,
span: Span,
allow_capturing_self: AllowCapturingSelfFlag)
span: Span)
-> Option<DefLike> {
let mut def;
let is_ty_param;
@ -3485,11 +3471,6 @@ fn upvarify(&mut self,
def = d;
is_ty_param = true;
}
DlDef(d @ DefSelf(..))
if allow_capturing_self == DontAllowCapturingSelf => {
def = d;
is_ty_param = false;
}
_ => {
return Some(def_like);
}
@ -3589,8 +3570,7 @@ fn upvarify(&mut self,
fn search_ribs(&mut self,
ribs: &mut ~[@Rib],
name: Name,
span: Span,
allow_capturing_self: AllowCapturingSelfFlag)
span: Span)
-> Option<DefLike> {
// FIXME #4950: This should not use a while loop.
// FIXME #4950: Try caching?
@ -3604,8 +3584,7 @@ fn search_ribs(&mut self,
};
match binding_opt {
Some(def_like) => {
return self.upvarify(ribs, i, def_like, span,
allow_capturing_self);
return self.upvarify(ribs, i, def_like, span);
}
None => {
// Continue.
@ -3786,8 +3765,7 @@ fn resolve_item(&mut self, item: &Item) {
item.id,
0,
OpaqueFunctionRibKind),
block,
NoSelfBinding);
block);
}
ItemStatic(..) => {
@ -3883,11 +3861,10 @@ fn with_constant_rib(&mut self, f: |&mut Resolver|) {
}
fn resolve_function(&mut self,
rib_kind: RibKind,
optional_declaration: Option<P<FnDecl>>,
type_parameters: TypeParameters,
block: P<Block>,
self_binding: SelfBinding) {
rib_kind: RibKind,
optional_declaration: Option<P<FnDecl>>,
type_parameters: TypeParameters,
block: P<Block>) {
// Create a value rib for the function.
let function_value_rib = @Rib::new(rib_kind);
{
@ -3914,21 +3891,6 @@ fn resolve_function(&mut self,
}
}
// Add self to the rib, if necessary.
match self_binding {
NoSelfBinding => {
// Nothing to do.
}
HasSelfBinding(self_node_id, explicit_self) => {
let mutable = match explicit_self.node {
SelfUniq(m) | SelfValue(m) if m == MutMutable => true,
_ => false
};
let def_like = DlDef(DefSelf(self_node_id, mutable));
function_value_rib.self_binding.set(Some(def_like));
}
}
// Add each argument to the rib.
match optional_declaration {
None => {
@ -4050,26 +4012,17 @@ fn resolve_struct(&mut self,
// Does this really need to take a RibKind or is it always going
// to be NormalRibKind?
fn resolve_method(&mut self,
rib_kind: RibKind,
method: @Method,
outer_type_parameter_count: uint) {
rib_kind: RibKind,
method: @Method,
outer_type_parameter_count: uint) {
let method_generics = &method.generics;
let type_parameters =
HasTypeParameters(method_generics,
method.id,
outer_type_parameter_count,
rib_kind);
// we only have self ty if it is a non static method
let self_binding = match method.explicit_self.node {
SelfStatic => NoSelfBinding,
_ => HasSelfBinding(method.self_id, method.explicit_self)
};
self.resolve_function(rib_kind,
Some(method.decl),
type_parameters,
method.body,
self_binding);
self.resolve_function(rib_kind, Some(method.decl), type_parameters, method.body);
}
fn resolve_implementation(&mut self,
@ -4135,9 +4088,7 @@ fn resolve_implementation(&mut self,
method.id,
outer_type_parameter_count,
NormalRibKind),
method.body,
HasSelfBinding(method.self_id),
visitor);
method.body);
*/
}
@ -4974,16 +4925,14 @@ fn resolve_identifier_in_local_ribs(&mut self,
let mut value_ribs = self.value_ribs.borrow_mut();
search_result = self.search_ribs(value_ribs.get(),
renamed,
span,
DontAllowCapturingSelf);
span);
}
TypeNS => {
let name = ident.name;
let mut type_ribs = self.type_ribs.borrow_mut();
search_result = self.search_ribs(type_ribs.get(),
name,
span,
AllowCapturingSelf);
span);
}
}
@ -5001,46 +4950,6 @@ fn resolve_identifier_in_local_ribs(&mut self,
}
}
fn resolve_self_value_in_local_ribs(&mut self, span: Span)
-> Option<Def> {
// FIXME #4950: This should not use a while loop.
let mut i = {
let value_ribs = self.value_ribs.borrow();
value_ribs.get().len()
};
while i != 0 {
i -= 1;
let self_binding_opt = {
let value_ribs = self.value_ribs.borrow();
value_ribs.get()[i].self_binding.get()
};
match self_binding_opt {
Some(def_like) => {
let mut value_ribs = self.value_ribs.borrow_mut();
match self.upvarify(value_ribs.get(),
i,
def_like,
span,
DontAllowCapturingSelf) {
Some(DlDef(def)) => return Some(def),
_ => {
if self.session.has_errors() {
// May happen inside a nested fn item, cf #6642.
return None;
} else {
self.session.span_bug(span,
"self wasn't mapped to a def?!")
}
}
}
}
None => {}
}
}
None
}
fn resolve_item_by_identifier_in_lexical_scope(&mut self,
ident: Ident,
namespace: Namespace)
@ -5224,10 +5133,8 @@ fn resolve_expr(&mut self, expr: &Expr) {
ExprFnBlock(fn_decl, block) |
ExprProc(fn_decl, block) => {
self.resolve_function(FunctionRibKind(expr.id, block.id),
Some(fn_decl),
NoTypeParameters,
block,
NoSelfBinding);
Some(fn_decl), NoTypeParameters,
block);
}
ExprStruct(ref path, _, _) => {
@ -5274,8 +5181,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
let mut label_ribs = self.label_ribs.borrow_mut();
match self.search_ribs(label_ribs.get(), label, expr.span,
DontAllowCapturingSelf) {
match self.search_ribs(label_ribs.get(), label, expr.span) {
None =>
self.resolve_error(expr.span,
format!("use of undeclared label \
@ -5293,17 +5199,6 @@ fn resolve_expr(&mut self, expr: &Expr) {
}
}
ExprSelf => {
match self.resolve_self_value_in_local_ribs(expr.span) {
None => {
self.resolve_error(expr.span,
"`self` is not allowed in \
this context")
}
Some(def) => self.record_def(expr.id, (def, AllPublic)),
}
}
_ => {
visit::walk_expr(self, expr, ());
}
@ -5320,7 +5215,7 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
let traits = self.search_for_traits_containing_method(ident);
self.trait_map.insert(expr.id, @RefCell::new(traits));
}
ExprMethodCall(_, _, ident, _, _, _) => {
ExprMethodCall(_, ident, _, _, _) => {
debug!("(recording candidate traits for expr) recording \
traits for {}",
expr.id);

View file

@ -337,8 +337,8 @@ fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
return adt::trans_case(bcx, repr, disr_val);
}
range(l1, l2) => {
let (l1, _) = consts::const_expr(ccx, l1);
let (l2, _) = consts::const_expr(ccx, l2);
let (l1, _) = consts::const_expr(ccx, l1, true);
let (l2, _) = consts::const_expr(ccx, l2, true);
return range_result(rslt(bcx, l1), rslt(bcx, l2));
}
vec_len(n, vec_len_eq, _) => {

View file

@ -240,7 +240,7 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
}
}
let f = decl_rust_fn(ccx, None, inputs, output, name);
let f = decl_rust_fn(ccx, false, inputs, output, name);
csearch::get_item_attrs(ccx.tcx.cstore, did, |meta_items| {
set_llvm_fn_attrs(meta_items.iter().map(|&x| attr::mk_attr(x)).to_owned_vec(), f)
});
@ -250,16 +250,15 @@ fn get_extern_rust_fn(ccx: &CrateContext, inputs: &[ty::t], output: ty::t,
f
}
fn decl_rust_fn(ccx: &CrateContext,
self_ty: Option<ty::t>,
inputs: &[ty::t],
output: ty::t,
name: &str) -> ValueRef {
let llfty = type_of_rust_fn(ccx, self_ty, inputs, output);
pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
inputs: &[ty::t], output: ty::t,
name: &str) -> ValueRef {
let llfty = type_of_rust_fn(ccx, has_env, inputs, output);
let llfn = decl_cdecl_fn(ccx.llmod, name, llfty, output);
let uses_outptr = type_of::return_uses_outptr(ccx, output);
let offset = if uses_outptr { 2 } else { 1 };
let offset = if uses_outptr { 1 } else { 0 };
let offset = if has_env { offset + 1 } else { offset };
for (i, &arg_ty) in inputs.iter().enumerate() {
let llarg = unsafe { llvm::LLVMGetParam(llfn, (offset + i) as c_uint) };
@ -292,10 +291,10 @@ fn decl_rust_fn(ccx: &CrateContext,
llfn
}
pub fn decl_internal_rust_fn(ccx: &CrateContext,
self_ty: Option<ty::t>, inputs: &[ty::t],
output: ty::t, name: &str) -> ValueRef {
let llfn = decl_rust_fn(ccx, self_ty, inputs, output, name);
pub fn decl_internal_rust_fn(ccx: &CrateContext, has_env: bool,
inputs: &[ty::t], output: ty::t,
name: &str) -> ValueRef {
let llfn = decl_rust_fn(ccx, has_env, inputs, output, name);
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);
llfn
}
@ -318,14 +317,10 @@ pub fn get_extern_const(externs: &mut ExternMap, llmod: ModuleRef,
// Returns a pointer to the body for the box. The box may be an opaque
// box. The result will be casted to the type of body_t, if it is statically
// known.
//
// The runtime equivalent is box_body() in "rust_internal.h".
pub fn opaque_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef)
-> ValueRef {
let _icx = push_ctxt("opaque_box_body");
pub fn at_box_body(bcx: &Block, body_t: ty::t, boxptr: ValueRef) -> ValueRef {
let _icx = push_ctxt("at_box_body");
let ccx = bcx.ccx();
let ty = type_of(ccx, body_t);
let ty = Type::smart_ptr(ccx, &ty);
let ty = Type::at_box(ccx, type_of(ccx, body_t));
let boxptr = PointerCast(bcx, boxptr, ty.ptr_to());
GEPi(bcx, boxptr, [0u, abi::box_field_body])
}
@ -882,10 +877,6 @@ pub fn fail_if_zero<'a>(
})
}
pub fn null_env_ptr(ccx: &CrateContext) -> ValueRef {
C_null(Type::opaque_box(ccx).ptr_to())
}
pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> ValueRef {
let name = csearch::get_symbol(ccx.sess.cstore, did);
match ty::get(t).sty {
@ -898,7 +889,7 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
Some(..) | None => {
let c = foreign::llvm_calling_convention(ccx, fn_ty.abis);
let cconv = c.unwrap_or(lib::llvm::CCallConv);
let llty = type_of_fn_from_ty(ccx, None, t);
let llty = type_of_fn_from_ty(ccx, t);
let mut externs = ccx.externs.borrow_mut();
get_extern_fn(externs.get(), ccx.llmod, name,
cconv, llty, fn_ty.sig.output)
@ -1241,6 +1232,7 @@ pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
path: ast_map::Path,
llfndecl: ValueRef,
id: ast::NodeId,
has_env: bool,
output_type: ty::t,
param_substs: Option<@param_substs>,
sp: Option<Span>)
@ -1263,33 +1255,33 @@ pub fn new_fn_ctxt_detailed(ccx: @CrateContext,
let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
let fcx = FunctionContext {
llfn: llfndecl,
llenv: unsafe {
Cell::new(llvm::LLVMGetUndef(Type::i8p().to_ref()))
},
llretptr: Cell::new(None),
entry_bcx: RefCell::new(None),
alloca_insert_pt: Cell::new(None),
llreturn: Cell::new(None),
llself: Cell::new(None),
personality: Cell::new(None),
caller_expects_out_pointer: uses_outptr,
llargs: RefCell::new(HashMap::new()),
lllocals: RefCell::new(HashMap::new()),
llupvars: RefCell::new(HashMap::new()),
id: id,
param_substs: param_substs,
span: sp,
path: path,
block_arena: TypedArena::new(),
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(~[])
let mut fcx = FunctionContext {
llfn: llfndecl,
llenv: None,
llretptr: Cell::new(None),
entry_bcx: RefCell::new(None),
alloca_insert_pt: Cell::new(None),
llreturn: Cell::new(None),
personality: Cell::new(None),
caller_expects_out_pointer: uses_outptr,
llargs: RefCell::new(HashMap::new()),
lllocals: RefCell::new(HashMap::new()),
llupvars: RefCell::new(HashMap::new()),
id: id,
param_substs: param_substs,
span: sp,
path: path,
block_arena: TypedArena::new(),
ccx: ccx,
debug_context: debug_context,
scopes: RefCell::new(~[])
};
fcx.llenv.set(unsafe {
llvm::LLVMGetParam(llfndecl, fcx.env_arg_pos() as c_uint)
});
if has_env {
fcx.llenv = Some(unsafe {
llvm::LLVMGetParam(fcx.llfn, fcx.env_arg_pos() as c_uint)
});
}
fcx
}
@ -1301,14 +1293,16 @@ pub fn init_function<'a>(
skip_retptr: bool,
output_type: ty::t,
param_substs: Option<@param_substs>) {
unsafe {
let entry_bcx = fcx.new_temp_block("entry-block");
Load(entry_bcx, C_null(Type::i8p()));
let entry_bcx = fcx.new_temp_block("entry-block");
fcx.entry_bcx.set(Some(entry_bcx));
fcx.alloca_insert_pt.set(Some(
llvm::LLVMGetFirstInstruction(entry_bcx.llbb)));
}
fcx.entry_bcx.set(Some(entry_bcx));
// Use a dummy instruction as the insertion point for all allocas.
// This is later removed in FunctionContext::cleanup.
fcx.alloca_insert_pt.set(Some(unsafe {
Load(entry_bcx, C_null(Type::i8p()));
llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
}));
let substd_output_type = match param_substs {
None => output_type,
@ -1327,8 +1321,7 @@ pub fn init_function<'a>(
// Otherwise, we normally allocate the llretptr, unless we
// have been instructed to skip it for immediate return
// values.
fcx.llretptr.set(Some(make_return_pointer(fcx,
substd_output_type)));
fcx.llretptr.set(Some(make_return_pointer(fcx, substd_output_type)));
}
}
}
@ -1336,12 +1329,13 @@ pub fn init_function<'a>(
pub fn new_fn_ctxt(ccx: @CrateContext,
path: ast_map::Path,
llfndecl: ValueRef,
has_env: bool,
output_type: ty::t,
sp: Option<Span>)
-> FunctionContext {
// FIXME(#11385): Do not call `init_function` here; it will typecheck
// but segfault.
new_fn_ctxt_detailed(ccx, path, llfndecl, -1, output_type, None, sp)
new_fn_ctxt_detailed(ccx, path, llfndecl, -1, has_env, output_type, None, sp)
}
// NB: must keep 4 fns in sync:
@ -1363,35 +1357,28 @@ fn arg_kind(cx: &FunctionContext, t: ty::t) -> datum::Rvalue {
type RvalueDatum = datum::Datum<datum::Rvalue>;
type LvalueDatum = datum::Datum<datum::Lvalue>;
// create_datums_for_fn_args: creates rvalue datums for `self` and each of the
// create_datums_for_fn_args: creates rvalue datums for each of the
// incoming function arguments. These will later be stored into
// appropriate lvalue datums.
fn create_datums_for_fn_args(cx: &FunctionContext,
self_arg: Option<ty::t>,
arg_tys: &[ty::t])
-> (Option<RvalueDatum>, ~[RvalueDatum]) {
pub fn create_datums_for_fn_args(fcx: &FunctionContext,
arg_tys: &[ty::t])
-> ~[RvalueDatum] {
let _icx = push_ctxt("create_datums_for_fn_args");
let self_datum = self_arg.map(
|t| datum::Datum(cx.llenv.get(), t, arg_kind(cx, t)));
// Return an array wrapping the ValueRefs that we get from
// llvm::LLVMGetParam for each argument into datums.
let arg_datums = arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
let llarg = unsafe {
llvm::LLVMGetParam(cx.llfn, cx.arg_pos(i) as c_uint)
};
datum::Datum(llarg, arg_ty, arg_kind(cx, arg_ty))
}).collect();
(self_datum, arg_datums)
arg_tys.iter().enumerate().map(|(i, &arg_ty)| {
let llarg = unsafe {
llvm::LLVMGetParam(fcx.llfn, fcx.arg_pos(i) as c_uint)
};
datum::Datum(llarg, arg_ty, arg_kind(fcx, arg_ty))
}).collect()
}
fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
arg_scope: cleanup::CustomScopeIndex,
bcx: &'a Block<'a>,
args: &[ast::Arg],
self_datum: Option<RvalueDatum>,
arg_datums: ~[RvalueDatum])
-> &'a Block<'a> {
debug!("copy_args_to_allocas");
@ -1400,18 +1387,6 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
let mut bcx = bcx;
let arg_scope_id = cleanup::CustomScope(arg_scope);
match self_datum {
Some(slf_rv) => {
let slf = unpack_datum!(
bcx, slf_rv.to_lvalue_datum_in_scope(bcx, "__self",
arg_scope_id));
fcx.llself.set(Some(slf));
if fcx.ccx.sess.opts.extra_debuginfo {
debuginfo::create_self_argument_metadata(bcx, slf.ty, slf.val);
}
}
_ => {}
}
for (i, arg_datum) in arg_datums.move_iter().enumerate() {
// For certain mode/type combinations, the raw llarg values are passed
@ -1429,7 +1404,7 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
}
}
return bcx;
bcx
}
// Ties up the llstaticallocas -> llloadenv -> lltop edges,
@ -1488,7 +1463,6 @@ pub fn trans_closure(ccx: @CrateContext,
decl: &ast::FnDecl,
body: &ast::Block,
llfndecl: ValueRef,
self_arg: Option<ty::t>,
param_substs: Option<@param_substs>,
id: ast::NodeId,
_attributes: &[ast::Attribute],
@ -1502,13 +1476,13 @@ pub fn trans_closure(ccx: @CrateContext,
debug!("trans_closure(..., param_substs={})",
param_substs.repr(ccx.tcx));
let fcx = new_fn_ctxt_detailed(ccx,
path,
llfndecl,
id,
output_type,
param_substs,
Some(body.span));
let has_env = match ty::get(ty::node_id_to_type(ccx.tcx, id)).sty {
ty::ty_closure(_) => true,
_ => false
};
let fcx = new_fn_ctxt_detailed(ccx, path, llfndecl, id, has_env, output_type,
param_substs, Some(body.span));
init_function(&fcx, false, output_type, param_substs);
// cleanup scope for the incoming arguments
@ -1522,11 +1496,9 @@ pub fn trans_closure(ccx: @CrateContext,
// Set up arguments to the function.
let arg_tys = ty::ty_fn_args(node_id_type(bcx, id));
let (self_datum, arg_datums) =
create_datums_for_fn_args(&fcx, self_arg, arg_tys);
let arg_datums = create_datums_for_fn_args(&fcx, arg_tys);
bcx = copy_args_to_allocas(&fcx, arg_scope, bcx,
decl.inputs, self_datum, arg_datums);
bcx = copy_args_to_allocas(&fcx, arg_scope, bcx, decl.inputs, arg_datums);
maybe_load_env(&fcx);
@ -1578,15 +1550,12 @@ pub fn trans_fn(ccx: @CrateContext,
decl: &ast::FnDecl,
body: &ast::Block,
llfndecl: ValueRef,
self_arg: Option<ty::t>,
param_substs: Option<@param_substs>,
id: ast::NodeId,
attrs: &[ast::Attribute]) {
let the_path_str = path_str(ccx.sess, path);
let _s = StatRecorder::new(ccx, the_path_str);
debug!("trans_fn(self_arg={:?}, param_substs={})",
self_arg,
param_substs.repr(ccx.tcx));
debug!("trans_fn(param_substs={})", param_substs.repr(ccx.tcx));
let _icx = push_ctxt("trans_fn");
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, id));
trans_closure(ccx,
@ -1594,7 +1563,6 @@ pub fn trans_fn(ccx: @CrateContext,
decl,
body,
llfndecl,
self_arg,
param_substs,
id,
attrs,
@ -1664,18 +1632,13 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: @CrateContext,
ty_to_str(ccx.tcx, ctor_ty)))
};
let fcx = new_fn_ctxt_detailed(ccx,
~[],
llfndecl,
ctor_id,
result_ty,
param_substs,
None);
let fcx = new_fn_ctxt_detailed(ccx, ~[], llfndecl, ctor_id, false,
result_ty, param_substs, None);
init_function(&fcx, false, result_ty, param_substs);
let arg_tys = ty::ty_fn_args(ctor_ty);
let (_, arg_datums) = create_datums_for_fn_args(&fcx, None, arg_tys);
let arg_datums = create_datums_for_fn_args(&fcx, arg_tys);
let bcx = fcx.entry_bcx.get().unwrap();
@ -1750,16 +1713,9 @@ pub fn trans_item(ccx: @CrateContext, item: &ast::Item) {
llfndecl,
item.id);
} else if !generics.is_type_parameterized() {
let llfndecl = get_item_val(ccx, item.id);
trans_fn(ccx,
vec::append_one((*path).clone(), PathName(item.ident)),
decl,
body,
llfndecl,
None,
None,
item.id,
item.attrs);
let path = vec::append_one((*path).clone(), PathName(item.ident));
let llfn = get_item_val(ccx, item.id);
trans_fn(ccx, path, decl, body, llfn, None, item.id, item.attrs);
} else {
// Be sure to travel more than just one layer deep to catch nested
// items in blocks and such.
@ -1874,8 +1830,7 @@ fn register_fn(ccx: @CrateContext,
sp: Span,
sym: ~str,
node_id: ast::NodeId,
node_type: ty::t,
self_ty: Option<ty::t>)
node_type: ty::t)
-> ValueRef {
let f = match ty::get(node_type).sty {
ty::ty_bare_fn(ref f) => {
@ -1885,7 +1840,7 @@ fn register_fn(ccx: @CrateContext,
_ => fail!("expected bare rust fn or an intrinsic")
};
let llfn = decl_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, sym);
let llfn = decl_rust_fn(ccx, false, f.sig.inputs, f.sig.output, sym);
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
@ -1963,7 +1918,6 @@ fn create_entry_fn(ccx: @CrateContext,
});
~[
C_null(Type::opaque_box(ccx).ptr_to()),
opaque_rust_main,
llvm::LLVMGetParam(llfn, 0),
llvm::LLVMGetParam(llfn, 1)
@ -1973,7 +1927,6 @@ fn create_entry_fn(ccx: @CrateContext,
} else {
debug!("using user-defined start fn");
let args = ~[
C_null(Type::opaque_box(ccx).ptr_to()),
llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint)
];
@ -1990,18 +1943,6 @@ fn create_entry_fn(ccx: @CrateContext,
}
}
pub fn fill_fn_pair(bcx: &Block,
pair: ValueRef,
llfn: ValueRef,
llenvptr: ValueRef) {
let ccx = bcx.ccx();
let code_cell = GEPi(bcx, pair, [0u, abi::fn_field_code]);
Store(bcx, llfn, code_cell);
let env_cell = GEPi(bcx, pair, [0u, abi::fn_field_box]);
let llenvblobptr = PointerCast(bcx, llenvptr, Type::opaque_box(ccx).ptr_to());
Store(bcx, llenvblobptr, env_cell);
}
pub fn item_path(ccx: &CrateContext, id: &ast::NodeId) -> ast_map::Path {
ty::item_path(ccx.tcx, ast_util::local_def(*id))
}
@ -2049,22 +1990,22 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
// using the current crate's name/version
// information in the hash of the symbol
debug!("making {}", sym);
let sym = {
let (sym, is_local) = {
let external_srcs = ccx.external_srcs
.borrow();
match external_srcs.get().find(&i.id) {
Some(&did) => {
debug!("but found in other crate...");
csearch::get_symbol(ccx.sess.cstore,
did)
(csearch::get_symbol(ccx.sess.cstore,
did), false)
}
None => sym
None => (sym, true)
}
};
// We need the translated value here, because for enums the
// LLVM type is not fully determined by the Rust type.
let (v, inlineable) = consts::const_expr(ccx, expr);
let (v, inlineable) = consts::const_expr(ccx, expr, is_local);
{
let mut const_values = ccx.const_values
.borrow_mut();
@ -2142,7 +2083,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
ast::ItemFn(_, purity, _, _, _) => {
let llfn = if purity != ast::ExternFn {
register_fn(ccx, i.span, sym, i.id, ty, None)
register_fn(ccx, i.span, sym, i.id, ty)
} else {
foreign::register_rust_fn_with_foreign_abi(ccx,
i.span,
@ -2246,7 +2187,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
llfn = match enm.node {
ast::ItemEnum(_, _) => {
register_fn(ccx, (*v).span, sym, id, ty, None)
register_fn(ccx, (*v).span, sym, id, ty)
}
_ => fail!("NodeVariant, shouldn't happen")
};
@ -2271,7 +2212,7 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef {
let sym = exported_name(ccx, (*struct_path).clone(), ty,
struct_item.attrs);
let llfn = register_fn(ccx, struct_item.span,
sym, ctor_id, ty, None);
sym, ctor_id, ty);
set_inline_hint(llfn);
llfn
}
@ -2312,11 +2253,7 @@ fn register_method(ccx: @CrateContext,
let sym = exported_name(ccx, path, mty, m.attrs);
let self_ty = match m.explicit_self.node {
ast::SelfStatic => None,
_ => Some(ty::node_id_to_type(ccx.tcx, m.self_id))
};
let llfn = register_fn(ccx, m.span, sym, id, mty, self_ty);
let llfn = register_fn(ccx, m.span, sym, id, mty);
set_llvm_fn_attrs(m.attrs, llfn);
llfn
}

View file

@ -797,6 +797,11 @@ pub fn inline_asm_call(&self, asm: *c_char, cons: *c_char,
pub fn call(&self, llfn: ValueRef, args: &[ValueRef],
attributes: &[(uint, lib::llvm::Attribute)]) -> ValueRef {
self.count_insn("call");
debug!("Call {} with args ({})",
self.ccx.tn.val_to_str(llfn),
args.map(|&v| self.ccx.tn.val_to_str(v)).connect(", "));
unsafe {
let v = llvm::LLVMBuildCall(self.llbuilder, llfn, args.as_ptr(),
args.len() as c_uint, noname());

View file

@ -52,13 +52,6 @@
use syntax::abi::AbiSet;
use syntax::ast_map;
// Represents a (possibly monomorphized) top-level fn item or method
// item. Note that this is just the fn-ptr and is not a Rust closure
// value (which is a pair).
pub struct FnData {
llfn: ValueRef,
}
pub struct MethodData {
llfn: ValueRef,
llself: ValueRef,
@ -66,8 +59,13 @@ pub struct MethodData {
pub enum CalleeData {
Closure(Datum<Lvalue>),
Fn(FnData),
Method(MethodData)
// Represents a (possibly monomorphized) top-level fn item or method
// item. Note that this is just the fn-ptr and is not a Rust closure
// value (which is a pair).
Fn(/* llfn */ ValueRef),
TraitMethod(MethodData)
}
pub struct Callee<'a> {
@ -95,7 +93,7 @@ fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
match ty::get(datum.ty).sty {
ty::ty_bare_fn(..) => {
let llval = datum.to_llscalarish(bcx);
return Callee {bcx: bcx, data: Fn(FnData {llfn: llval})};
return Callee {bcx: bcx, data: Fn(llval)};
}
ty::ty_closure(..) => {
let datum = unpack_datum!(
@ -111,8 +109,8 @@ fn datum_callee<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
}
}
fn fn_callee<'a>(bcx: &'a Block<'a>, fd: FnData) -> Callee<'a> {
return Callee {bcx: bcx, data: Fn(fd)};
fn fn_callee<'a>(bcx: &'a Block<'a>, llfn: ValueRef) -> Callee<'a> {
return Callee {bcx: bcx, data: Fn(llfn)};
}
fn trans_def<'a>(bcx: &'a Block<'a>, def: ast::Def, ref_expr: &ast::Expr)
@ -143,8 +141,7 @@ fn trans_def<'a>(bcx: &'a Block<'a>, def: ast::Def, ref_expr: &ast::Expr)
ast::DefArg(..) |
ast::DefLocal(..) |
ast::DefBinding(..) |
ast::DefUpvar(..) |
ast::DefSelf(..) => {
ast::DefUpvar(..) => {
datum_callee(bcx, ref_expr)
}
ast::DefMod(..) | ast::DefForeignMod(..) | ast::DefTrait(..) |
@ -171,7 +168,7 @@ pub fn trans_fn_ref_to_callee<'a>(
}
pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
-> FnData {
-> ValueRef {
/*!
*
* Translates a reference (with id `ref_id`) to the fn/method
@ -248,7 +245,7 @@ pub fn trans_fn_ref_with_vtables(
ref_id: ast::NodeId, // 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>) // vtables for the call
-> FnData {
-> ValueRef {
/*!
* Translates a reference to a fn/method item, monomorphizing and
* inlining as it goes.
@ -399,9 +396,9 @@ pub fn trans_fn_ref_with_vtables(
let ref_ty = common::node_id_type(bcx, ref_id);
val = PointerCast(
bcx, val, type_of::type_of_fn_from_ty(ccx, None, ref_ty).ptr_to());
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
}
return FnData {llfn: val};
return val;
}
// Find the actual function pointer.
@ -438,13 +435,13 @@ pub fn trans_fn_ref_with_vtables(
// This can occur on either a crate-local or crate-external
// reference. It also occurs when testing libcore and in some
// other weird situations. Annoying.
let llty = type_of::type_of_fn_from_ty(ccx, None, fn_tpt.ty);
let llty = type_of::type_of_fn_from_ty(ccx, fn_tpt.ty);
let llptrty = llty.ptr_to();
if val_ty(val) != llptrty {
val = BitCast(bcx, val, llptrty);
}
return FnData {llfn: val};
val
}
// ______________________________________________________________________
@ -465,8 +462,7 @@ pub fn trans_call<'a>(
node_id_type(in_cx, id),
|cx, _| trans(cx, f),
args,
Some(dest),
DontAutorefArg).bcx
Some(dest)).bcx
}
pub fn trans_method_call<'a>(
@ -478,9 +474,7 @@ pub fn trans_method_call<'a>(
dest: expr::Dest)
-> &'a Block<'a> {
let _icx = push_ctxt("trans_method_call");
debug!("trans_method_call(call_ex={}, rcvr={})",
call_ex.repr(in_cx.tcx()),
rcvr.repr(in_cx.tcx()));
debug!("trans_method_call(call_ex={})", call_ex.repr(in_cx.tcx()));
trans_call_inner(
in_cx,
Some(common::expr_info(call_ex)),
@ -509,8 +503,7 @@ pub fn trans_method_call<'a>(
}
},
args,
Some(dest),
DontAutorefArg).bcx
Some(dest)).bcx
}
pub fn trans_lang_call<'a>(
@ -537,8 +530,7 @@ pub fn trans_lang_call<'a>(
None)
},
ArgVals(args),
dest,
DontAutorefArg)
dest)
}
pub fn trans_lang_call_with_type_params<'a>(
@ -569,20 +561,20 @@ pub fn trans_lang_call_with_type_params<'a>(
let new_llval;
match callee.data {
Fn(fn_data) => {
Fn(llfn) => {
let substituted = ty::subst_tps(callee.bcx.tcx(),
type_params,
None,
fty);
let llfnty = type_of::type_of(callee.bcx.ccx(),
substituted);
new_llval = PointerCast(callee.bcx, fn_data.llfn, llfnty);
new_llval = PointerCast(callee.bcx, llfn, llfnty);
}
_ => fail!()
}
Callee { bcx: callee.bcx, data: Fn(FnData { llfn: new_llval }) }
Callee { bcx: callee.bcx, data: Fn(new_llval) }
},
ArgVals(args), Some(dest), DontAutorefArg).bcx;
ArgVals(args), Some(dest)).bcx;
}
pub fn trans_call_inner<'a>(
@ -594,8 +586,7 @@ pub fn trans_call_inner<'a>(
arg_cleanup_scope: cleanup::ScopeId|
-> Callee<'a>,
args: CallArgs,
dest: Option<expr::Dest>,
autoref_arg: AutorefArg)
dest: Option<expr::Dest>)
-> Result<'a> {
/*!
* This behemoth of a function translates function calls.
@ -627,25 +618,22 @@ pub fn trans_call_inner<'a>(
let callee = get_callee(bcx, cleanup::CustomScope(arg_cleanup_scope));
let mut bcx = callee.bcx;
let (llfn, llenv) = unsafe {
match callee.data {
Fn(d) => {
(d.llfn, llvm::LLVMGetUndef(Type::opaque_box(ccx).ptr_to().to_ref()))
}
Method(d) => {
// Weird but true: we pass self in the *environment* slot!
(d.llfn, d.llself)
}
Closure(d) => {
// Closures are represented as (llfn, llclosure) pair:
// load the requisite values out.
let pair = d.to_llref();
let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
let llfn = Load(bcx, llfn);
let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
let llenv = Load(bcx, llenv);
(llfn, llenv)
}
let (llfn, llenv, llself) = match callee.data {
Fn(llfn) => {
(llfn, None, None)
}
TraitMethod(d) => {
(d.llfn, None, Some(d.llself))
}
Closure(d) => {
// Closures are represented as (llfn, llclosure) pair:
// load the requisite values out.
let pair = d.to_llref();
let llfn = GEPi(bcx, pair, [0u, abi::fn_field_code]);
let llfn = Load(bcx, llfn);
let llenv = GEPi(bcx, pair, [0u, abi::fn_field_box]);
let llenv = Load(bcx, llenv);
(llfn, Some(llenv), None)
}
};
@ -694,13 +682,17 @@ pub fn trans_call_inner<'a>(
llargs.push(opt_llretslot.unwrap());
}
// Push the environment.
llargs.push(llenv);
// Push the environment (or a trait object's self).
match (llenv, llself) {
(Some(llenv), None) => llargs.push(llenv),
(None, Some(llself)) => llargs.push(llself),
_ => {}
}
// Push the arguments.
bcx = trans_args(bcx, args, callee_ty,
autoref_arg, &mut llargs,
cleanup::CustomScope(arg_cleanup_scope));
bcx = trans_args(bcx, args, callee_ty, &mut llargs,
cleanup::CustomScope(arg_cleanup_scope),
llself.is_some());
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
@ -718,11 +710,10 @@ pub fn trans_call_inner<'a>(
match ty::get(ret_ty).sty {
// `~` pointer return values never alias because ownership
// is transferred
ty::ty_uniq(..) |
ty::ty_vec(_, ty::vstore_uniq) => {
ty::ty_uniq(..) | ty::ty_vec(_, ty::vstore_uniq) => {
attrs.push((0, NoAliasAttribute));
}
_ => ()
_ => {}
}
// Invoke the actual rust fn and update bcx/llresult.
@ -748,13 +739,12 @@ pub fn trans_call_inner<'a>(
assert!(dest.is_some());
let mut llargs = ~[];
bcx = trans_args(bcx, args, callee_ty,
autoref_arg, &mut llargs,
cleanup::CustomScope(arg_cleanup_scope));
bcx = trans_args(bcx, args, callee_ty, &mut llargs,
cleanup::CustomScope(arg_cleanup_scope), false);
fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
let arg_tys = match args {
ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, *x)).collect(),
ArgVals(_) => fail!("expected arg exprs.")
_ => fail!("expected arg exprs.")
};
bcx = foreign::trans_native_call(bcx, callee_ty,
llfn, opt_llretslot.unwrap(), llargs, arg_tys);
@ -782,18 +772,18 @@ pub fn trans_call_inner<'a>(
pub enum CallArgs<'a> {
ArgExprs(&'a [@ast::Expr]),
// HACK used only by trans_overloaded_op.
ArgAutorefSecond(&'a ast::Expr, Option<&'a ast::Expr>),
ArgVals(&'a [ValueRef])
}
pub fn trans_args<'a>(
cx: &'a Block<'a>,
fn trans_args<'a>(cx: &'a Block<'a>,
args: CallArgs,
fn_ty: ty::t,
autoref_arg: AutorefArg,
llargs: &mut ~[ValueRef],
arg_cleanup_scope: cleanup::ScopeId)
-> &'a Block<'a>
{
arg_cleanup_scope: cleanup::ScopeId,
ignore_self: bool)
-> &'a Block<'a> {
let _icx = push_ctxt("trans_args");
let arg_tys = ty::ty_fn_args(fn_ty);
let variadic = ty::fn_is_variadic(fn_ty);
@ -804,28 +794,50 @@ pub fn trans_args<'a>(
// This will be needed if this is a generic call, because the callee has
// to cast her view of the arguments to the caller's view.
match args {
ArgExprs(arg_exprs) => {
let num_formal_args = arg_tys.len();
for (i, arg_expr) in arg_exprs.iter().enumerate() {
let arg_ty = if i >= num_formal_args {
assert!(variadic);
expr_ty_adjusted(cx, *arg_expr)
} else {
arg_tys[i]
};
let arg_val = unpack_result!(bcx, {
trans_arg_expr(bcx,
arg_ty,
*arg_expr,
arg_cleanup_scope,
autoref_arg)
});
llargs.push(arg_val);
ArgExprs(arg_exprs) => {
let num_formal_args = arg_tys.len();
for (i, arg_expr) in arg_exprs.iter().enumerate() {
if i == 0 && ignore_self {
continue;
}
let arg_ty = if i >= num_formal_args {
assert!(variadic);
expr_ty_adjusted(cx, *arg_expr)
} else {
arg_tys[i]
};
llargs.push(unpack_result!(bcx, {
trans_arg_expr(bcx, arg_ty, *arg_expr,
arg_cleanup_scope,
DontAutorefArg)
}));
}
}
ArgAutorefSecond(arg_expr, arg2) => {
assert!(!variadic);
llargs.push(unpack_result!(bcx, {
trans_arg_expr(bcx, arg_tys[0], arg_expr,
arg_cleanup_scope,
DontAutorefArg)
}));
match arg2 {
Some(arg2_expr) => {
assert_eq!(arg_tys.len(), 2);
llargs.push(unpack_result!(bcx, {
trans_arg_expr(bcx, arg_tys[1], arg2_expr,
arg_cleanup_scope,
DoAutorefArg)
}));
}
None => assert_eq!(arg_tys.len(), 1)
}
}
ArgVals(vs) => {
llargs.push_all(vs);
}
}
ArgVals(vs) => {
llargs.push_all(vs);
}
}
bcx

View file

@ -680,7 +680,7 @@ fn get_or_create_landing_pad(&self) -> BasicBlockRef {
// The exception handling personality function.
let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0).llfn;
let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0);
// The only landing pad clause will be 'cleanup'
let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u);

View file

@ -10,18 +10,19 @@
use back::abi;
use back::link::{mangle_internal_name_by_path_and_seq};
use back::link::mangle_internal_name_by_path_and_seq;
use lib::llvm::ValueRef;
use middle::moves;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::datum::{Datum, Lvalue};
use middle::trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
use middle::trans::debuginfo;
use middle::trans::expr;
use middle::trans::glue;
use middle::trans::type_of::*;
use middle::trans::type_::Type;
use middle::ty;
use util::ppaux::Repr;
use util::ppaux::ty_to_str;
use std::vec;
@ -69,9 +70,9 @@
// closure".
//
// Typically an opaque closure suffices because we only manipulate it
// by ptr. The routine Type::opaque_box().ptr_to() returns an
// appropriate type for such an opaque closure; it allows access to
// the box fields, but not the closure_data itself.
// by ptr. The routine Type::at_box().ptr_to() returns an appropriate
// type for such an opaque closure; it allows access to the box fields,
// but not the closure_data itself.
//
// But sometimes, such as when cloning or freeing a closure, we need
// to know the full information. That is where the type descriptor
@ -244,8 +245,7 @@ pub fn store_environment<'a>(
// Given a context and a list of upvars, build a closure. This just
// collects the upvars and packages them up for store_environment.
pub fn build_closure<'a>(
bcx0: &'a Block<'a>,
fn build_closure<'a>(bcx0: &'a Block<'a>,
cap_vars: &[moves::CaptureVar],
sigil: ast::Sigil)
-> ClosureResult<'a> {
@ -282,10 +282,8 @@ pub fn build_closure<'a>(
// Given an enclosing block context, a new function context, a closure type,
// and a list of upvars, generate code to load and populate the environment
// with the upvars and type descriptors.
pub fn load_environment(fcx: &FunctionContext,
cdata_ty: ty::t,
cap_vars: &[moves::CaptureVar],
sigil: ast::Sigil) {
fn load_environment(fcx: &FunctionContext, cdata_ty: ty::t,
cap_vars: &[moves::CaptureVar], sigil: ast::Sigil) {
let _icx = push_ctxt("closure::load_environment");
// Don't bother to create the block if there's nothing to load
@ -296,7 +294,7 @@ pub fn load_environment(fcx: &FunctionContext,
let bcx = fcx.entry_bcx.get().unwrap();
// Load a pointer to the closure data, skipping over the box header:
let llcdata = opaque_box_body(bcx, cdata_ty, fcx.llenv.get());
let llcdata = at_box_body(bcx, cdata_ty, fcx.llenv.unwrap());
// Store the pointer to closure data in an alloca for debug info because that's what the
// llvm.dbg.declare intrinsic expects
@ -338,6 +336,12 @@ pub fn load_environment(fcx: &FunctionContext,
}
}
fn fill_fn_pair(bcx: &Block, pair: ValueRef, llfn: ValueRef, llenvptr: ValueRef) {
Store(bcx, llfn, GEPi(bcx, pair, [0u, abi::fn_field_code]));
let llenvptr = PointerCast(bcx, llenvptr, Type::i8p());
Store(bcx, llenvptr, GEPi(bcx, pair, [0u, abi::fn_field_box]));
}
pub fn trans_expr_fn<'a>(
bcx: &'a Block<'a>,
sigil: ast::Sigil,
@ -388,115 +392,119 @@ pub fn trans_expr_fn<'a>(
let s = mangle_internal_name_by_path_and_seq(ccx,
sub_path.clone(),
"expr_fn");
let llfn = decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, s);
let llfn = decl_internal_rust_fn(ccx, true, f.sig.inputs, f.sig.output, s);
// set an inline hint for all closures
set_inline_hint(llfn);
let Result {bcx: bcx, val: closure} = match sigil {
ast::BorrowedSigil | ast::ManagedSigil | ast::OwnedSigil => {
let cap_vars = {
let capture_map = ccx.maps.capture_map.borrow();
capture_map.get().get_copy(&user_id)
};
let ClosureResult {llbox, cdata_ty, bcx}
= build_closure(bcx, cap_vars, sigil);
trans_closure(ccx,
sub_path,
decl,
body,
llfn,
None,
bcx.fcx.param_substs,
user_id,
[],
ty::ty_fn_ret(fty),
|fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
rslt(bcx, llbox)
let cap_vars = {
let capture_map = ccx.maps.capture_map.borrow();
capture_map.get().get_copy(&user_id)
};
let ClosureResult {llbox, cdata_ty, bcx} = build_closure(bcx, cap_vars, sigil);
trans_closure(ccx, sub_path, decl, body, llfn,
bcx.fcx.param_substs, user_id,
[], ty::ty_fn_ret(fty),
|fcx| load_environment(fcx, cdata_ty, cap_vars, sigil));
fill_fn_pair(bcx, dest_addr, llfn, llbox);
bcx
}
pub fn get_wrapper_for_bare_fn(ccx: @CrateContext,
closure_ty: ty::t,
def: ast::Def,
fn_ptr: ValueRef,
is_local: bool) -> ValueRef {
let def_id = match def {
ast::DefFn(did, _) | ast::DefStaticMethod(did, _, _) |
ast::DefVariant(_, did, _) | ast::DefStruct(did) => did,
_ => {
ccx.sess.bug(format!("get_wrapper_for_bare_fn: \
expected a statically resolved fn, got {:?}",
def));
}
};
fill_fn_pair(bcx, dest_addr, llfn, closure);
return bcx;
}
pub fn make_closure_glue<'a>(
cx: &'a Block<'a>,
v: ValueRef,
t: ty::t,
glue_fn: |&'a Block<'a>, v: ValueRef, t: ty::t|
-> &'a Block<'a>)
-> &'a Block<'a> {
let _icx = push_ctxt("closure::make_closure_glue");
let bcx = cx;
let tcx = cx.tcx();
let sigil = ty::ty_closure_sigil(t);
match sigil {
ast::BorrowedSigil => bcx,
ast::OwnedSigil | ast::ManagedSigil => {
let box_cell_v = GEPi(cx, v, [0u, abi::fn_field_box]);
let box_ptr_v = Load(cx, box_cell_v);
with_cond(cx, IsNotNull(cx, box_ptr_v), |bcx| {
let closure_ty = ty::mk_opaque_closure_ptr(tcx, sigil);
glue_fn(bcx, box_cell_v, closure_ty)
})
}
}
}
pub fn make_opaque_cbox_drop_glue<'a>(
bcx: &'a Block<'a>,
sigil: ast::Sigil,
cboxptr: ValueRef) // opaque closure ptr
-> &'a Block<'a> {
let _icx = push_ctxt("closure::make_opaque_cbox_drop_glue");
match sigil {
ast::BorrowedSigil => bcx,
ast::ManagedSigil => {
bcx.tcx().sess.bug("trying to trans drop glue of @fn")
}
ast::OwnedSigil => {
glue::make_free_glue(
bcx, cboxptr,
ty::mk_opaque_closure_ptr(bcx.tcx(), sigil))
}
}
}
/// `cbox` is a pointer to a pointer to an opaque closure.
pub fn make_opaque_cbox_free_glue<'a>(
bcx: &'a Block<'a>,
sigil: ast::Sigil,
cbox: ValueRef)
-> &'a Block<'a> {
let _icx = push_ctxt("closure::make_opaque_cbox_free_glue");
match sigil {
ast::BorrowedSigil => {
return bcx;
}
ast::ManagedSigil | ast::OwnedSigil => {
/* hard cases: fallthrough to code below */
{
let cache = ccx.closure_bare_wrapper_cache.borrow();
match cache.get().find(&fn_ptr) {
Some(&llval) => return llval,
None => {}
}
}
let ccx = bcx.ccx();
with_cond(bcx, IsNotNull(bcx, cbox), |bcx| {
// Load the type descr found in the cbox
let lltydescty = ccx.tydesc_type.ptr_to();
let cbox = Load(bcx, cbox);
let tydescptr = GEPi(bcx, cbox, [0u, abi::box_field_tydesc]);
let tydesc = Load(bcx, tydescptr);
let tydesc = PointerCast(bcx, tydesc, lltydescty);
let tcx = ccx.tcx;
// Drop the tuple data then free the descriptor
let cdata = GEPi(bcx, cbox, [0u, abi::box_field_body]);
glue::call_tydesc_glue_full(bcx, cdata, tydesc,
abi::tydesc_field_drop_glue, None);
debug!("get_wrapper_for_bare_fn(closure_ty={})", closure_ty.repr(tcx));
// Free the ty descr (if necc) and the box itself
glue::trans_exchange_free(bcx, cbox);
let f = match ty::get(closure_ty).sty {
ty::ty_closure(ref f) => f,
_ => {
ccx.sess.bug(format!("get_wrapper_for_bare_fn: \
expected a closure ty, got {}",
closure_ty.repr(tcx)));
}
};
bcx
})
let path = ty::item_path(tcx, def_id);
let name = mangle_internal_name_by_path_and_seq(ccx, path, "as_closure");
let llfn = if is_local {
decl_internal_rust_fn(ccx, true, f.sig.inputs, f.sig.output, name)
} else {
decl_rust_fn(ccx, true, f.sig.inputs, f.sig.output, name)
};
{
let mut cache = ccx.closure_bare_wrapper_cache.borrow_mut();
cache.get().insert(fn_ptr, llfn);
}
// This is only used by statics inlined from a different crate.
if !is_local {
// Don't regenerate the wrapper, just reuse the original one.
return llfn;
}
let _icx = push_ctxt("closure::get_wrapper_for_bare_fn");
let fcx = new_fn_ctxt(ccx, ~[], llfn, true, f.sig.output, None);
init_function(&fcx, true, f.sig.output, None);
let bcx = fcx.entry_bcx.get().unwrap();
let args = create_datums_for_fn_args(&fcx, ty::ty_fn_args(closure_ty));
let mut llargs = ~[];
match fcx.llretptr.get() {
Some(llretptr) => {
llargs.push(llretptr);
}
None => {}
}
llargs.extend(&mut args.iter().map(|arg| arg.val));
let retval = Call(bcx, fn_ptr, llargs, []);
if type_is_zero_size(ccx, f.sig.output) || fcx.llretptr.get().is_some() {
RetVoid(bcx);
} else {
Ret(bcx, retval);
}
// HACK(eddyb) finish_fn cannot be used here, we returned directly.
debuginfo::clear_source_location(&fcx);
fcx.cleanup();
llfn
}
pub fn make_closure_from_bare_fn<'a>(bcx: &'a Block<'a>,
closure_ty: ty::t,
def: ast::Def,
fn_ptr: ValueRef)
-> DatumBlock<'a, Expr> {
let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
let wrapper = get_wrapper_for_bare_fn(bcx.ccx(), closure_ty, def, fn_ptr, true);
fill_fn_pair(bcx, scratch.val, wrapper, C_null(Type::i8p()));
DatumBlock(bcx, scratch.to_expr_datum())
}

View file

@ -230,9 +230,8 @@ pub struct FunctionContext<'a> {
// section of the executable we're generating.
llfn: ValueRef,
// The implicit environment argument that arrives in the function we're
// creating.
llenv: Cell<ValueRef>,
// The environment argument in a closure.
llenv: Option<ValueRef>,
// The place to store the return value. If the return type is immediate,
// this is an alloca in the function. Otherwise, it's the hidden first
@ -250,14 +249,6 @@ pub struct FunctionContext<'a> {
alloca_insert_pt: Cell<Option<ValueRef>>,
llreturn: Cell<Option<BasicBlockRef>>,
// The 'self' value currently in use in this function, if there
// is one.
//
// NB: This is the type of the self *variable*, not the self *type*. The
// self type is set only for default methods, while the self variable is
// set for all methods.
llself: Cell<Option<LvalueDatum>>,
// The a value alloca'd for calls to upcalls.rust_personality. Used when
// outputting the resume instruction.
personality: Cell<Option<ValueRef>>,
@ -305,10 +296,11 @@ pub struct FunctionContext<'a> {
impl<'a> FunctionContext<'a> {
pub fn arg_pos(&self, arg: uint) -> uint {
if self.caller_expects_out_pointer {
arg + 2u
let arg = self.env_arg_pos() + arg;
if self.llenv.is_some() {
arg + 1
} else {
arg + 1u
arg
}
}

View file

@ -19,6 +19,7 @@
use middle::trans::adt;
use middle::trans::base;
use middle::trans::base::push_ctxt;
use middle::trans::closure;
use middle::trans::common::*;
use middle::trans::consts;
use middle::trans::expr;
@ -85,11 +86,12 @@ pub fn const_ptrcast(cx: &CrateContext, a: ValueRef, t: Type) -> ValueRef {
}
}
fn const_vec(cx: @CrateContext, e: &ast::Expr, es: &[@ast::Expr]) -> (ValueRef, Type, bool) {
fn const_vec(cx: @CrateContext, e: &ast::Expr,
es: &[@ast::Expr], is_local: bool) -> (ValueRef, Type, bool) {
let vec_ty = ty::expr_ty(cx.tcx, e);
let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty);
let llunitty = type_of::type_of(cx, unit_ty);
let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e)));
let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e, is_local)));
// If the vector contains enums, an LLVM array won't work.
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
C_struct(vs, false)
@ -187,11 +189,12 @@ pub fn get_const_val(cx: @CrateContext,
!non_inlineable_statics.get().contains(&def_id.node))
}
pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
let (llconst, inlineable) = const_expr_unadjusted(cx, e);
pub fn const_expr(cx: @CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef, bool) {
let (llconst, inlineable) = const_expr_unadjusted(cx, e, is_local);
let mut llconst = llconst;
let mut inlineable = inlineable;
let ety = ty::expr_ty(cx.tcx, e);
let ety_adjusted = ty::expr_ty_adjusted(cx.tcx, e);
let adjustment = {
let adjustments = cx.tcx.adjustments.borrow();
adjustments.get().find_copy(&e.id)
@ -201,10 +204,13 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
Some(adj) => {
match *adj {
ty::AutoAddEnv(ty::ReStatic, ast::BorrowedSigil) => {
llconst = C_struct([
llconst,
C_null(Type::opaque_box(cx).ptr_to())
], false)
let def = ty::resolve_expr(cx.tcx, e);
let wrapper = closure::get_wrapper_for_bare_fn(cx,
ety_adjusted,
def,
llconst,
is_local);
llconst = C_struct([wrapper, C_null(Type::i8p())], false)
}
ty::AutoAddEnv(ref r, ref s) => {
cx.sess
@ -277,7 +283,6 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
}
}
let ety_adjusted = ty::expr_ty_adjusted(cx.tcx, e);
let llty = type_of::sizing_type_of(cx, ety_adjusted);
let csize = machine::llsize_of_alloc(cx, val_ty(llconst));
let tsize = machine::llsize_of_alloc(cx, llty);
@ -296,22 +301,21 @@ pub fn const_expr(cx: @CrateContext, e: &ast::Expr) -> (ValueRef, bool) {
// the bool returned is whether this expression can be inlined into other crates
// if it's assigned to a static.
fn const_expr_unadjusted(cx: @CrateContext,
e: &ast::Expr) -> (ValueRef, bool) {
fn map_list(cx: @CrateContext,
exprs: &[@ast::Expr]) -> (~[ValueRef], bool) {
exprs.iter().map(|&e| const_expr(cx, e))
fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
is_local: bool) -> (ValueRef, bool) {
let map_list = |exprs: &[@ast::Expr]| {
exprs.iter().map(|&e| const_expr(cx, e, is_local))
.fold((~[], true), |(L, all_inlineable), (val, inlineable)| {
(vec::append_one(L, val), all_inlineable && inlineable)
(vec::append_one(L, val), all_inlineable && inlineable)
})
}
};
unsafe {
let _icx = push_ctxt("const_expr");
return match e.node {
ast::ExprLit(lit) => (consts::const_lit(cx, e, *lit), true),
ast::ExprBinary(_, b, e1, e2) => {
let (te1, _) = const_expr(cx, e1);
let (te2, _) = const_expr(cx, e2);
let (te1, _) = const_expr(cx, e1, is_local);
let (te2, _) = const_expr(cx, e2, is_local);
let te2 = base::cast_shift_const_rhs(b, te1, te2);
@ -392,7 +396,7 @@ fn map_list(cx: @CrateContext,
}, true)
},
ast::ExprUnary(_, u, e) => {
let (te, _) = const_expr(cx, e);
let (te, _) = const_expr(cx, e, is_local);
let ty = ty::expr_ty(cx.tcx, e);
let is_float = ty::type_is_fp(ty);
return (match u {
@ -421,7 +425,7 @@ fn map_list(cx: @CrateContext,
ast::ExprField(base, field, _) => {
let bt = ty::expr_ty_adjusted(cx.tcx, base);
let brepr = adt::represent_type(cx, bt);
let (bv, inlineable) = const_expr(cx, base);
let (bv, inlineable) = const_expr(cx, base, is_local);
expr::with_field_tys(cx.tcx, bt, None, |discr, field_tys| {
let ix = ty::field_idx_strict(cx.tcx, field.name, field_tys);
(adt::const_get_field(cx, brepr, bv, discr, ix), inlineable)
@ -430,7 +434,7 @@ fn map_list(cx: @CrateContext,
ast::ExprIndex(_, base, index) => {
let bt = ty::expr_ty_adjusted(cx.tcx, base);
let (bv, inlineable) = const_expr(cx, base);
let (bv, inlineable) = const_expr(cx, base, is_local);
let iv = match const_eval::eval_const_expr(cx.tcx, index) {
const_eval::const_int(i) => i as u64,
const_eval::const_uint(u) => u,
@ -471,7 +475,7 @@ fn map_list(cx: @CrateContext,
let ety = ty::expr_ty(cx.tcx, e);
let llty = type_of::type_of(cx, ety);
let basety = ty::expr_ty(cx.tcx, base);
let (v, inlineable) = const_expr(cx, base);
let (v, inlineable) = const_expr(cx, base, is_local);
return (match (expr::cast_type_kind(basety),
expr::cast_type_kind(ety)) {
@ -522,13 +526,13 @@ fn map_list(cx: @CrateContext,
}, inlineable)
}
ast::ExprAddrOf(ast::MutImmutable, sub) => {
let (e, _) = const_expr(cx, sub);
let (e, _) = const_expr(cx, sub, is_local);
(const_addr_of(cx, e), false)
}
ast::ExprTup(ref es) => {
let ety = ty::expr_ty(cx.tcx, e);
let repr = adt::represent_type(cx, ety);
let (vals, inlineable) = map_list(cx, *es);
let (vals, inlineable) = map_list(*es);
(adt::trans_const(cx, repr, 0, vals), inlineable)
}
ast::ExprStruct(_, ref fs, ref base_opt) => {
@ -537,7 +541,7 @@ fn map_list(cx: @CrateContext,
let tcx = cx.tcx;
let base_val = match *base_opt {
Some(base) => Some(const_expr(cx, base)),
Some(base) => Some(const_expr(cx, base, is_local)),
None => None
};
@ -545,7 +549,7 @@ fn map_list(cx: @CrateContext,
let cs = field_tys.iter().enumerate()
.map(|(ix, &field_ty)| {
match fs.iter().find(|f| field_ty.ident.name == f.ident.node.name) {
Some(f) => const_expr(cx, (*f).expr),
Some(f) => const_expr(cx, (*f).expr, is_local),
None => {
match base_val {
Some((bv, inlineable)) => {
@ -563,19 +567,19 @@ fn map_list(cx: @CrateContext,
})
}
ast::ExprVec(ref es, ast::MutImmutable) => {
let (v, _, inlineable) = const_vec(cx, e, *es);
let (v, _, inlineable) = const_vec(cx, e, *es, is_local);
(v, inlineable)
}
ast::ExprVstore(sub, ast::ExprVstoreSlice) => {
match sub.node {
ast::ExprLit(ref lit) => {
match lit.node {
ast::LitStr(..) => { const_expr(cx, sub) }
ast::LitStr(..) => { const_expr(cx, sub, is_local) }
_ => { cx.sess.span_bug(e.span, "bad const-slice lit") }
}
}
ast::ExprVec(ref es, ast::MutImmutable) => {
let (cv, llunitty, _) = const_vec(cx, e, *es);
let (cv, llunitty, _) = const_vec(cx, e, *es, is_local);
let llty = val_ty(cv);
let gv = "const".with_c_str(|name| {
llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name)
@ -598,7 +602,7 @@ fn map_list(cx: @CrateContext,
const_eval::const_uint(i) => i as uint,
_ => cx.sess.span_bug(count.span, "count must be integral const expression.")
};
let vs = vec::from_elem(n, const_expr(cx, elem).first());
let vs = vec::from_elem(n, const_expr(cx, elem, is_local).first());
let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
C_struct(vs, false)
} else {
@ -656,7 +660,7 @@ fn map_list(cx: @CrateContext,
Some(ast::DefStruct(_)) => {
let ety = ty::expr_ty(cx.tcx, e);
let repr = adt::represent_type(cx, ety);
let (arg_vals, inlineable) = map_list(cx, *args);
let (arg_vals, inlineable) = map_list(*args);
(adt::trans_const(cx, repr, 0, arg_vals), inlineable)
}
Some(ast::DefVariant(enum_did, variant_did, _)) => {
@ -665,14 +669,14 @@ fn map_list(cx: @CrateContext,
let vinfo = ty::enum_variant_with_id(cx.tcx,
enum_did,
variant_did);
let (arg_vals, inlineable) = map_list(cx, *args);
let (arg_vals, inlineable) = map_list(*args);
(adt::trans_const(cx, repr, vinfo.disr_val, arg_vals),
inlineable)
}
_ => cx.sess.span_bug(e.span, "expected a struct or variant def")
}
}
ast::ExprParen(e) => { const_expr(cx, e) }
ast::ExprParen(e) => { const_expr(cx, e, is_local) }
_ => cx.sess.span_bug(e.span,
"bad constant expression type in consts::const_expr")
};

View file

@ -91,6 +91,9 @@ pub struct CrateContext {
impl_method_cache: RefCell<HashMap<(ast::DefId, ast::Name), ast::DefId>>,
// Cache of closure wrappers for bare fn's.
closure_bare_wrapper_cache: RefCell<HashMap<ValueRef, ValueRef>>,
module_data: RefCell<HashMap<~str, ValueRef>>,
lltypes: RefCell<HashMap<ty::t, Type>>,
llsizingtypes: RefCell<HashMap<ty::t, Type>>,
@ -201,6 +204,7 @@ pub fn new(sess: session::Session,
const_values: RefCell::new(HashMap::new()),
extern_const_values: RefCell::new(HashMap::new()),
impl_method_cache: RefCell::new(HashMap::new()),
closure_bare_wrapper_cache: RefCell::new(HashMap::new()),
module_data: RefCell::new(HashMap::new()),
lltypes: RefCell::new(HashMap::new()),
llsizingtypes: RefCell::new(HashMap::new()),

View file

@ -309,7 +309,7 @@ pub fn trans_ret<'a>(bcx: &'a Block<'a>,
Some(x) => {
bcx = expr::trans_into(bcx, x, dest);
}
_ => ()
_ => {}
}
let cleanup_llbb = fcx.return_exit_block();
Br(bcx, cleanup_llbb);

View file

@ -130,8 +130,6 @@ struct List {
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
use lib::llvm::debuginfo::*;
use middle::trans::adt;
use middle::trans::base;
use middle::trans::build;
use middle::trans::common::*;
use middle::trans::datum::{Datum, Lvalue};
use middle::trans::machine;
@ -328,8 +326,7 @@ pub fn create_captured_var_metadata(bcx: &Block,
None => {
cx.sess.span_bug(span, "debuginfo::create_captured_var_metadata() - NodeId not found");
}
Some(ast_map::NodeLocal(ident, _)) => ident,
Some(ast_map::NodeArg(pat)) => {
Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
match pat.node {
ast::PatIdent(_, ref path, _) => {
ast_util::path_to_ident(path)
@ -410,83 +407,6 @@ pub fn create_match_binding_metadata(bcx: &Block,
span);
}
/// Creates debug information for the self argument of a method.
///
/// Adds the created metadata nodes directly to the crate's IR.
pub fn create_self_argument_metadata(bcx: &Block,
type_of_self: ty::t,
llptr: ValueRef) {
if fn_should_be_ignored(bcx.fcx) {
return;
}
// Extract the span of the self argument from the method's AST
let fnitem = bcx.ccx().tcx.items.get(bcx.fcx.id);
let span = match fnitem {
ast_map::NodeMethod(method, _, _) => {
method.explicit_self.span
}
ast_map::NodeTraitMethod(trait_method, _, _) => {
match *trait_method {
ast::Provided(method) => method.explicit_self.span,
_ => {
bcx.ccx()
.sess
.bug(format!("create_self_argument_metadata: \
unexpected sort of node: {:?}",
fnitem))
}
}
}
_ => bcx.ccx().sess.bug(
format!("create_self_argument_metadata: unexpected sort of node: {:?}", fnitem))
};
let scope_metadata = bcx.fcx.debug_context.get_ref(bcx.ccx(), span).fn_metadata;
let argument_index = {
let counter = &bcx.fcx.debug_context.get_ref(bcx.ccx(), span).argument_counter;
let argument_index = counter.get();
counter.set(argument_index + 1);
argument_index
};
let address_operations = &[unsafe { llvm::LLVMDIBuilderCreateOpDeref(Type::i64().to_ref()) }];
// The self argument comes in one of two forms:
// (1) For `&self`, `~self`, and `@self` it is an alloca containing a pointer to the data. That
// is the `{&~@}self` pointer is contained by value in the alloca, and `type_of_self` will
// be `{&~@}Self`
// (2) For by-value `self`, `llptr` will not be an alloca, but a pointer to the self-value. That
// is by-value `self` is always implicitly passed by reference (sic!). So we have a couple
// of problems here:
// (a) There is no alloca to give to `llvm.dbg.declare` and
// (b) `type_of_self` is `Self`, but `llptr` is of type `*Self`
// In order to solve this problem, the else branch below creates a helper alloca which
// contains a copy of `llptr`. We then describe the `self` parameter by pointing
// `llvm.dbg.declare` to this helper alloca and tell it that the pointer there needs to be
// dereferenced once to get to the actual data (similar to non-immediate by-value args).
let variable_access = if unsafe { llvm::LLVMIsAAllocaInst(llptr) } != ptr::null() {
DirectVariable { alloca: llptr }
} else {
// Create a helper alloca that allows us to track the self-argument properly. The alloca
// contains a pointer to the self-value.
let ptr_type = ty::mk_mut_ptr(bcx.tcx(), type_of_self);
let helper_alloca = base::alloc_ty(bcx, ptr_type, "__self");
build::Store(bcx, llptr, helper_alloca);
IndirectVariable { alloca: helper_alloca, address_operations: address_operations }
};
declare_local(bcx,
special_idents::self_,
type_of_self,
scope_metadata,
variable_access,
ArgumentVariable(argument_index),
span);
}
/// Creates debug information for the given function argument.
///
/// Adds the created metadata nodes directly to the crate's IR.
@ -1768,7 +1688,7 @@ fn boxed_type_metadata(cx: &CrateContext,
None => ~"BoxedType"
};
let box_llvm_type = Type::smart_ptr(cx, &content_llvm_type);
let box_llvm_type = Type::at_box(cx, content_llvm_type);
let member_llvm_types = box_llvm_type.field_types();
assert!(box_layout_is_correct(cx, member_llvm_types, content_llvm_type));
@ -2584,11 +2504,10 @@ fn walk_expr(cx: &CrateContext,
match exp.node {
ast::ExprLogLevel |
ast::ExprSelf |
ast::ExprLit(_) |
ast::ExprBreak(_) |
ast::ExprAgain(_) |
ast::ExprPath(_) => (),
ast::ExprPath(_) => {}
ast::ExprVstore(sub_exp, _) |
ast::ExprCast(sub_exp, _) |
@ -2697,8 +2616,7 @@ fn walk_expr(cx: &CrateContext,
})
}
// ast::expr_loop_body(inner_exp) |
ast::ExprDoBody(inner_exp) => {
ast::ExprDoBody(inner_exp) => {
let inner_expr_is_expr_fn_block = match *inner_exp {
ast::Expr { node: ast::ExprFnBlock(..), .. } => true,
_ => false
@ -2720,9 +2638,8 @@ fn walk_expr(cx: &CrateContext,
}
}
ast::ExprMethodCall(node_id, receiver_exp, _, _, ref args, _) => {
ast::ExprMethodCall(node_id, _, _, ref args, _) => {
scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
walk_expr(cx, receiver_exp, scope_stack, scope_map);
for arg_exp in args.iter() {
walk_expr(cx, *arg_exp, scope_stack, scope_map);

View file

@ -42,7 +42,6 @@
use middle::trans::base::*;
use middle::trans::base;
use middle::trans::build::*;
use middle::trans::callee::DoAutorefArg;
use middle::trans::callee;
use middle::trans::cleanup;
use middle::trans::cleanup::CleanupMethods;
@ -316,16 +315,10 @@ fn add_env<'a>(bcx: &'a Block<'a>,
// code and keep it DRY that accommodates that use case at the
// moment.
let tcx = bcx.tcx();
let closure_ty = expr_ty_adjusted(bcx, expr);
debug!("add_env(closure_ty={})", closure_ty.repr(tcx));
let scratch = rvalue_scratch_datum(bcx, closure_ty, "__adjust");
let llfn = GEPi(bcx, scratch.val, [0u, abi::fn_field_code]);
let llval = datum.to_llscalarish(bcx);
Store(bcx, llval, llfn);
let llenv = GEPi(bcx, scratch.val, [0u, abi::fn_field_box]);
Store(bcx, base::null_env_ptr(bcx.ccx()), llenv);
DatumBlock(bcx, scratch.to_expr_datum())
let fn_ptr = datum.to_llscalarish(bcx);
let def = ty::resolve_expr(bcx.tcx(), expr);
closure::make_closure_from_bare_fn(bcx, closure_ty, def, fn_ptr)
}
fn auto_slice_and_ref<'a>(
@ -517,7 +510,7 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
ast::ExprParen(e) => {
trans(bcx, e)
}
ast::ExprPath(_) | ast::ExprSelf => {
ast::ExprPath(_) => {
trans_def(bcx, expr, bcx.def(expr.id))
}
ast::ExprField(base, ident, _) => {
@ -669,7 +662,8 @@ fn trans_def<'a>(bcx: &'a Block<'a>,
let _icx = push_ctxt("trans_def_lvalue");
match def {
ast::DefFn(..) | ast::DefStaticMethod(..) => {
ast::DefFn(..) | ast::DefStaticMethod(..) |
ast::DefStruct(_) | ast::DefVariant(..) => {
trans_def_fn_unadjusted(bcx, ref_expr, def)
}
ast::DefStatic(did, _) => {
@ -817,34 +811,33 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
match expr.node {
ast::ExprParen(e) => {
return trans_into(bcx, e, dest);
trans_into(bcx, e, dest)
}
ast::ExprPath(_) | ast::ExprSelf => {
return trans_def_dps_unadjusted(bcx, expr,
bcx.def(expr.id), dest);
ast::ExprPath(_) => {
trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
}
ast::ExprIf(cond, thn, els) => {
return controlflow::trans_if(bcx, expr.id, cond, thn, els, dest);
controlflow::trans_if(bcx, expr.id, cond, thn, els, dest)
}
ast::ExprMatch(discr, ref arms) => {
return _match::trans_match(bcx, expr, discr, *arms, dest);
_match::trans_match(bcx, expr, discr, *arms, dest)
}
ast::ExprBlock(blk) => {
controlflow::trans_block(bcx, blk, dest)
}
ast::ExprStruct(_, ref fields, base) => {
return trans_rec_or_struct(bcx, (*fields), base, expr.span, expr.id, dest);
trans_rec_or_struct(bcx, (*fields), base, expr.span, expr.id, dest)
}
ast::ExprTup(ref args) => {
let repr = adt::represent_type(bcx.ccx(), expr_ty(bcx, expr));
let numbered_fields: ~[(uint, @ast::Expr)] =
args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
return trans_adt(bcx, repr, 0, numbered_fields, None, dest);
trans_adt(bcx, repr, 0, numbered_fields, None, dest)
}
ast::ExprLit(lit) => {
match lit.node {
ast::LitStr(s, _) => {
return tvec::trans_lit_str(bcx, expr, s, dest);
tvec::trans_lit_str(bcx, expr, s, dest)
}
_ => {
bcx.tcx()
@ -859,10 +852,10 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
ast::ExprVstore(contents, ast::ExprVstoreMutSlice) => {
fcx.push_ast_cleanup_scope(contents.id);
bcx = tvec::trans_slice_vstore(bcx, expr, contents, dest);
return fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id)
}
ast::ExprVec(..) | ast::ExprRepeat(..) => {
return tvec::trans_fixed_vstore(bcx, expr, expr, dest);
tvec::trans_fixed_vstore(bcx, expr, expr, dest)
}
ast::ExprFnBlock(decl, body) |
ast::ExprProc(decl, body) => {
@ -871,60 +864,41 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
debug!("translating block function {} with type {}",
expr_to_str(expr, tcx.sess.intr()),
expr_ty.repr(tcx));
return closure::trans_expr_fn(bcx, sigil, decl, body,
expr.id, expr.id, dest);
closure::trans_expr_fn(bcx, sigil, decl, body,
expr.id, expr.id, dest)
}
ast::ExprDoBody(blk) => {
return trans_into(bcx, blk, dest);
trans_into(bcx, blk, dest)
}
ast::ExprCall(f, ref args, _) => {
return callee::trans_call(
bcx, expr, f, callee::ArgExprs(*args), expr.id, dest);
callee::trans_call(bcx, expr, f,
callee::ArgExprs(*args), expr.id, dest)
}
ast::ExprMethodCall(callee_id, rcvr, _, _, ref args, _) => {
return callee::trans_method_call(bcx,
expr,
callee_id,
rcvr,
callee::ArgExprs(*args),
dest);
ast::ExprMethodCall(callee_id, _, _, ref args, _) => {
callee::trans_method_call(bcx, expr, callee_id, args[0],
callee::ArgExprs(*args), dest)
}
ast::ExprBinary(callee_id, _, lhs, rhs) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx,
expr,
callee_id,
lhs,
~[rhs],
expr_ty(bcx, expr),
dest);
trans_overloaded_op(bcx, expr, callee_id, lhs,
Some(&*rhs), expr_ty(bcx, expr), dest)
}
ast::ExprUnary(callee_id, _, subexpr) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx,
expr,
callee_id,
subexpr,
~[],
expr_ty(bcx, expr),
dest);
trans_overloaded_op(bcx, expr, callee_id, subexpr,
None, expr_ty(bcx, expr), dest)
}
ast::ExprIndex(callee_id, base, idx) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx,
expr,
callee_id,
base,
~[idx],
expr_ty(bcx, expr),
dest);
trans_overloaded_op(bcx, expr, callee_id, base,
Some(&*idx), expr_ty(bcx, expr), dest)
}
ast::ExprCast(val, _) => {
// DPS output mode means this is a trait cast:
match ty::get(node_id_type(bcx, expr.id)).sty {
ty::ty_trait(..) => {
let datum = unpack_datum!(bcx, trans(bcx, val));
return meth::trans_trait_cast(bcx, datum, expr.id, dest);
meth::trans_trait_cast(bcx, datum, expr.id, dest)
}
_ => {
bcx.tcx().sess.span_bug(expr.span,
@ -933,12 +907,12 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
}
}
ast::ExprAssignOp(callee_id, op, dst, src) => {
return trans_assign_op(bcx, expr, callee_id, op, dst, src);
trans_assign_op(bcx, expr, callee_id, op, dst, src)
}
ast::ExprBox(_, contents) => {
// Special case for `Gc<T>` for now. The other case, for unique
// pointers, is handled in `trans_rvalue_datum_unadjusted`.
return trans_gc(bcx, expr, contents, dest)
trans_gc(bcx, expr, contents, dest)
}
_ => {
bcx.tcx().sess.span_bug(
@ -968,8 +942,8 @@ fn trans_def_dps_unadjusted<'a>(
let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
if variant_info.args.len() > 0u {
// N-ary variant.
let fn_data = callee::trans_fn_ref(bcx, vid, ref_expr.id);
Store(bcx, fn_data.llfn, lldest);
let llfn = callee::trans_fn_ref(bcx, vid, ref_expr.id);
Store(bcx, llfn, lldest);
return bcx;
} else {
// Nullary variant.
@ -980,20 +954,16 @@ fn trans_def_dps_unadjusted<'a>(
return bcx;
}
}
ast::DefStruct(def_id) => {
ast::DefStruct(_) => {
let ty = expr_ty(bcx, ref_expr);
match ty::get(ty).sty {
ty::ty_struct(did, _) if ty::has_dtor(ccx.tcx, did) => {
let repr = adt::represent_type(ccx, ty);
adt::trans_start_init(bcx, repr, lldest, 0);
}
ty::ty_bare_fn(..) => {
let fn_data = callee::trans_fn_ref(bcx, def_id, ref_expr.id);
Store(bcx, fn_data.llfn, lldest);
}
_ => ()
_ => {}
}
return bcx;
bcx
}
_ => {
bcx.tcx().sess.span_bug(ref_expr.span, format!(
@ -1009,16 +979,15 @@ fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
{
let _icx = push_ctxt("trans_def_datum_unadjusted");
let fn_data = match def {
let llfn = match def {
ast::DefFn(did, _) |
ast::DefStruct(did) | ast::DefVariant(_, did, _) |
ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
callee::trans_fn_ref(bcx, did, ref_expr.id)
}
ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => {
meth::trans_static_method_callee(bcx,
impl_did,
trait_did,
ref_expr.id)
meth::trans_static_method_callee(bcx, impl_did,
trait_did, ref_expr.id)
}
_ => {
bcx.tcx().sess.span_bug(ref_expr.span, format!(
@ -1029,7 +998,7 @@ fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
};
let fn_ty = expr_ty(bcx, ref_expr);
DatumBlock(bcx, Datum(fn_data.llfn, fn_ty, RvalueExpr(Rvalue(ByValue))))
DatumBlock(bcx, Datum(llfn, fn_ty, RvalueExpr(Rvalue(ByValue))))
}
pub fn trans_local_var<'a>(bcx: &'a Block<'a>,
@ -1063,21 +1032,6 @@ pub fn trans_local_var<'a>(bcx: &'a Block<'a>,
let lllocals = bcx.fcx.lllocals.borrow();
take_local(bcx, lllocals.get(), nid)
}
ast::DefSelf(nid, _) => {
let self_info = match bcx.fcx.llself.get() {
Some(self_info) => self_info,
None => {
bcx.sess().bug(format!(
"trans_local_var: reference to self \
out of context with id {:?}", nid));
}
};
debug!("def_self() reference, self_info.ty={}",
self_info.ty.repr(bcx.tcx()));
self_info
}
_ => {
bcx.sess().unimpl(format!(
"unsupported def type in trans_local_var: {:?}", def));
@ -1630,12 +1584,12 @@ fn trans_binary<'a>(
}
}
fn trans_overloaded_op<'a>(
fn trans_overloaded_op<'a, 'b>(
bcx: &'a Block<'a>,
expr: &ast::Expr,
callee_id: ast::NodeId,
rcvr: &ast::Expr,
args: ~[@ast::Expr],
rcvr: &'b ast::Expr,
arg: Option<&'b ast::Expr>,
ret_ty: ty::t,
dest: Dest)
-> &'a Block<'a> {
@ -1655,9 +1609,8 @@ fn trans_overloaded_op<'a>(
origin,
arg_cleanup_scope)
},
callee::ArgExprs(args),
Some(dest),
DoAutorefArg).bcx
callee::ArgAutorefSecond(rcvr, arg),
Some(dest)).bcx
}
fn int_cast(bcx: &Block,

View file

@ -480,18 +480,10 @@ fn build_rust_fn(ccx: @CrateContext,
id,
t.repr(tcx));
let llfndecl = base::decl_internal_rust_fn(ccx, None, f.sig.inputs, f.sig.output, ps);
base::set_llvm_fn_attrs(attrs, llfndecl);
base::trans_fn(ccx,
(*path).clone(),
decl,
body,
llfndecl,
None,
None,
id,
[]);
return llfndecl;
let llfn = base::decl_internal_rust_fn(ccx, false, f.sig.inputs, f.sig.output, ps);
base::set_llvm_fn_attrs(attrs, llfn);
base::trans_fn(ccx, (*path).clone(), decl, body, llfn, None, id, []);
llfn
}
unsafe fn build_wrap_fn(ccx: @CrateContext,
@ -597,11 +589,6 @@ unsafe fn build_wrap_fn(ccx: @CrateContext,
return_alloca = None;
};
// Push an (null) env pointer
let env_pointer = base::null_env_ptr(ccx);
debug!("env pointer={}", ccx.tn.val_to_str(env_pointer));
llrust_args.push(env_pointer);
// Build up the arguments to the call to the rust function.
// Careful to adapt for cases where the native convention uses
// a pointer and Rust does not or vice versa.

View file

@ -23,7 +23,6 @@
use middle::trans::callee;
use middle::trans::cleanup;
use middle::trans::cleanup::CleanupMethods;
use middle::trans::closure;
use middle::trans::common::*;
use middle::trans::build::*;
use middle::trans::expr;
@ -202,11 +201,8 @@ fn lazily_emit_tydesc_glue(ccx: @CrateContext, field: uint, ti: @tydesc_info) {
}
// See [Note-arg-mode]
pub fn call_tydesc_glue_full(bcx: &Block,
v: ValueRef,
tydesc: ValueRef,
field: uint,
static_ti: Option<@tydesc_info>) {
pub fn call_tydesc_glue_full(bcx: &Block, v: ValueRef, tydesc: ValueRef,
field: uint, static_ti: Option<@tydesc_info>) {
let _icx = push_ctxt("call_tydesc_glue_full");
let ccx = bcx.ccx();
// NB: Don't short-circuit even if this block is unreachable because
@ -214,25 +210,25 @@ pub fn call_tydesc_glue_full(bcx: &Block,
if bcx.unreachable.get() && !ccx.sess.no_landing_pads() { return; }
let static_glue_fn = match static_ti {
None => None,
Some(sti) => {
lazily_emit_tydesc_glue(ccx, field, sti);
if field == abi::tydesc_field_take_glue {
sti.take_glue.get()
} else if field == abi::tydesc_field_drop_glue {
sti.drop_glue.get()
} else if field == abi::tydesc_field_visit_glue {
sti.visit_glue.get()
} else {
None
None => None,
Some(sti) => {
lazily_emit_tydesc_glue(ccx, field, sti);
if field == abi::tydesc_field_take_glue {
sti.take_glue.get()
} else if field == abi::tydesc_field_drop_glue {
sti.drop_glue.get()
} else if field == abi::tydesc_field_visit_glue {
sti.visit_glue.get()
} else {
None
}
}
}
};
// When static type info is available, avoid casting parameter unless the
// glue is using a simplified type, because the function already has the
// right type. Otherwise cast to generic pointer.
let llrawptr = if static_ti.is_none() || static_glue_fn.is_none() {
let llrawptr = if static_glue_fn.is_none() {
PointerCast(bcx, v, Type::i8p())
} else {
let ty = static_ti.unwrap().ty;
@ -246,16 +242,16 @@ pub fn call_tydesc_glue_full(bcx: &Block,
let llfn = {
match static_glue_fn {
None => {
// Select out the glue function to call from the tydesc
let llfnptr = GEPi(bcx, tydesc, [0u, field]);
Load(bcx, llfnptr)
}
Some(sgf) => sgf
None => {
// Select out the glue function to call from the tydesc
let llfnptr = GEPi(bcx, tydesc, [0u, field]);
Load(bcx, llfnptr)
}
Some(sgf) => sgf
}
};
Call(bcx, llfn, [C_null(Type::nil().ptr_to()), llrawptr], []);
Call(bcx, llfn, [llrawptr], []);
}
// See [Note-arg-mode]
@ -283,43 +279,7 @@ fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t)
bcx
}
pub fn make_free_glue<'a>(bcx: &'a Block<'a>,
v: ValueRef,
t: ty::t)
-> &'a Block<'a> {
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_free_glue");
match ty::get(t).sty {
ty::ty_box(body_ty) => {
let v = Load(bcx, v);
let body = GEPi(bcx, v, [0u, abi::box_field_body]);
let bcx = drop_ty(bcx, body, body_ty);
trans_free(bcx, v)
}
ty::ty_uniq(content_ty) => {
let llbox = Load(bcx, v);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, llbox, content_ty);
trans_exchange_free(bcx, llbox)
})
}
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
}
ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v, t, make_free_glue)
}
ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_free_glue(bcx, ck, v)
}
_ => bcx
}
}
pub fn trans_struct_drop_flag<'a>(
bcx: &'a Block<'a>,
fn trans_struct_drop_flag<'a>(bcx: &'a Block<'a>,
t: ty::t,
v0: ValueRef,
dtor_did: ast::DefId,
@ -333,8 +293,7 @@ pub fn trans_struct_drop_flag<'a>(
})
}
pub fn trans_struct_drop<'a>(
bcx: &'a Block<'a>,
fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
t: ty::t,
v0: ValueRef,
dtor_did: ast::DefId,
@ -380,72 +339,99 @@ pub fn trans_struct_drop<'a>(
bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, field_scope)
}
pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t)
-> &'a Block<'a> {
fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'a> {
// NB: v0 is an *alias* of type t here, not a direct value.
let _icx = push_ctxt("make_drop_glue");
let ccx = bcx.ccx();
match ty::get(t).sty {
ty::ty_box(_) |
ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
decr_refcnt_maybe_free(bcx, v0, Some(t))
}
ty::ty_uniq(_) |
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
make_free_glue(bcx, v0, t)
}
ty::ty_unboxed_vec(_) => {
tvec::make_drop_glue_unboxed(bcx, v0, t)
}
ty::ty_struct(did, ref substs) => {
let tcx = bcx.tcx();
match ty::ty_dtor(tcx, did) {
ty::TraitDtor(dtor, true) => {
trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
}
ty::TraitDtor(dtor, false) => {
trans_struct_drop(bcx, t, v0, dtor, did, substs)
}
ty::NoDtor => {
// No dtor? Just the default case
iter_structural_ty(bcx, v0, t, drop_ty)
}
ty::ty_box(body_ty) => {
decr_refcnt_maybe_free(bcx, v0, Some(body_ty))
}
}
ty::ty_closure(_) => {
closure::make_closure_glue(bcx, v0, t, drop_ty)
}
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]);
decr_refcnt_maybe_free(bcx, llbox_ptr, None)
}
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
// Only drop the value when it is non-null
with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => {
let unit_ty = ty::sequence_element_type(ccx.tcx, t);
let unboxed_vec_ty = ty::mk_mut_unboxed_vec(ccx.tcx, unit_ty);
decr_refcnt_maybe_free(bcx, v0, Some(unboxed_vec_ty))
}
ty::ty_uniq(content_ty) => {
let llbox = Load(bcx, v0);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = drop_ty(bcx, llbox, content_ty);
trans_exchange_free(bcx, llbox)
})
}
ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => {
make_drop_glue(bcx, v0, tvec::expand_boxed_vec_ty(bcx.tcx(), t))
}
ty::ty_unboxed_vec(_) => {
tvec::make_drop_glue_unboxed(bcx, v0, t)
}
ty::ty_struct(did, ref substs) => {
let tcx = bcx.tcx();
match ty::ty_dtor(tcx, did) {
ty::TraitDtor(dtor, true) => {
trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
}
ty::TraitDtor(dtor, false) => {
trans_struct_drop(bcx, t, v0, dtor, did, substs)
}
ty::NoDtor => {
// No dtor? Just the default case
iter_structural_ty(bcx, v0, t, drop_ty)
}
}
}
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]);
decr_refcnt_maybe_free(bcx, llbox_ptr, None)
}
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
// Only drop the value when it is non-null
with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
let llvtable = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
// Cast the vtable to a pointer to a pointer to a tydesc.
let llvtable = PointerCast(bcx, llvtable,
ccx.tydesc_type.ptr_to().ptr_to());
let lltydesc = Load(bcx, llvtable);
call_tydesc_glue_full(bcx,
lluniquevalue,
lltydesc,
abi::tydesc_field_drop_glue,
None);
bcx
})
}
ty::ty_opaque_closure_ptr(ck) => {
closure::make_opaque_cbox_drop_glue(bcx, ck, v0)
}
_ => {
if ty::type_needs_drop(ccx.tcx, t) &&
ty::type_is_structural(t) {
iter_structural_ty(bcx, v0, t, drop_ty)
} else { bcx }
}
// Cast the vtable to a pointer to a pointer to a tydesc.
let llvtable = PointerCast(bcx, llvtable,
ccx.tydesc_type.ptr_to().ptr_to());
let lltydesc = Load(bcx, llvtable);
call_tydesc_glue_full(bcx,
lluniquevalue,
lltydesc,
abi::tydesc_field_drop_glue,
None);
bcx
})
}
ty::ty_closure(ref f) if f.sigil == ast::OwnedSigil => {
let box_cell_v = GEPi(bcx, v0, [0u, abi::fn_field_box]);
let env = Load(bcx, box_cell_v);
let env_ptr_ty = Type::at_box(ccx, Type::i8()).ptr_to();
let env = PointerCast(bcx, env, env_ptr_ty);
with_cond(bcx, IsNotNull(bcx, env), |bcx| {
// Load the type descr found in the env
let lltydescty = ccx.tydesc_type.ptr_to();
let tydescptr = GEPi(bcx, env, [0u, abi::box_field_tydesc]);
let tydesc = Load(bcx, tydescptr);
let tydesc = PointerCast(bcx, tydesc, lltydescty);
// Drop the tuple data then free the descriptor
let cdata = GEPi(bcx, env, [0u, abi::box_field_body]);
call_tydesc_glue_full(bcx, cdata, tydesc,
abi::tydesc_field_drop_glue, None);
// Free the ty descr (if necc) and the env itself
trans_exchange_free(bcx, env)
})
}
_ => {
if ty::type_needs_drop(ccx.tcx, t) &&
ty::type_is_structural(t) {
iter_structural_ty(bcx, v0, t, drop_ty)
} else {
bcx
}
}
}
}
@ -468,18 +454,19 @@ fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
Store(decr_bcx, rc, rc_ptr);
CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb);
let v = Load(free_bcx, box_ptr_ptr);
let body = GEPi(free_bcx, v, [0u, abi::box_field_body]);
let free_bcx = match t {
Some(t) => make_free_glue(free_bcx, box_ptr_ptr, t),
Some(t) => drop_ty(free_bcx, body, t),
None => {
let v = Load(free_bcx, box_ptr_ptr);
let td = Load(free_bcx, GEPi(free_bcx, v, [0u, abi::box_field_tydesc]));
let valptr = GEPi(free_bcx, v, [0u, abi::box_field_body]);
// Generate code that, dynamically, indexes into the
// tydesc and calls the drop glue that got set dynamically
call_tydesc_glue_full(free_bcx, valptr, td, abi::tydesc_field_drop_glue, None);
trans_free(free_bcx, v)
let td = Load(free_bcx, GEPi(free_bcx, v, [0u, abi::box_field_tydesc]));
call_tydesc_glue_full(free_bcx, body, td, abi::tydesc_field_drop_glue, None);
free_bcx
}
};
let free_bcx = trans_free(free_bcx, v);
Br(free_bcx, next_bcx.llbb);
next_bcx
@ -489,40 +476,39 @@ fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a
let _icx = push_ctxt("make_take_glue");
// NB: v is a *pointer* to type t here, not a direct value.
match ty::get(t).sty {
ty::ty_box(_) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
}
ty::ty_vec(_, ty::vstore_slice(_))
| ty::ty_str(ty::vstore_slice(_)) => {
bcx
}
ty::ty_closure(_) => bcx,
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
incr_refcnt_of_boxed(bcx, llbox);
bcx
}
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]);
let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable]));
ty::ty_box(_) |
ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => {
incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx
}
ty::ty_vec(_, ty::vstore_slice(_))
| ty::ty_str(ty::vstore_slice(_)) => {
bcx
}
ty::ty_closure(_) => bcx,
ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => {
let llbox = Load(bcx, GEPi(bcx, v, [0u, abi::trt_field_box]));
incr_refcnt_of_boxed(bcx, llbox);
bcx
}
ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => {
let lluniquevalue = GEPi(bcx, v, [0, abi::trt_field_box]);
let llvtable = Load(bcx, GEPi(bcx, v, [0, abi::trt_field_vtable]));
// Cast the vtable to a pointer to a pointer to a tydesc.
let llvtable = PointerCast(bcx, llvtable,
bcx.ccx().tydesc_type.ptr_to().ptr_to());
let lltydesc = Load(bcx, llvtable);
call_tydesc_glue_full(bcx,
lluniquevalue,
lltydesc,
abi::tydesc_field_take_glue,
None);
bcx
}
ty::ty_opaque_closure_ptr(_) => bcx,
_ if ty::type_is_structural(t) => {
iter_structural_ty(bcx, v, t, take_ty)
}
_ => bcx
// Cast the vtable to a pointer to a pointer to a tydesc.
let llvtable = PointerCast(bcx, llvtable,
bcx.ccx().tydesc_type.ptr_to().ptr_to());
let lltydesc = Load(bcx, llvtable);
call_tydesc_glue_full(bcx,
lluniquevalue,
lltydesc,
abi::tydesc_field_take_glue,
None);
bcx
}
_ if ty::type_is_structural(t) => {
iter_structural_ty(bcx, v, t, take_ty)
}
_ => bcx
}
}
@ -595,7 +581,7 @@ fn make_generic_glue(ccx: @CrateContext, t: ty::t, llfn: ValueRef,
let glue_name = format!("glue {} {}", name, ty_to_short_str(ccx.tcx, t));
let _s = StatRecorder::new(ccx, glue_name);
let fcx = new_fn_ctxt(ccx, ~[], llfn, ty::mk_nil(), None);
let fcx = new_fn_ctxt(ccx, ~[], llfn, false, ty::mk_nil(), None);
init_function(&fcx, false, ty::mk_nil(), None);
lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage);

View file

@ -14,7 +14,6 @@
use middle::trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
use middle::trans::common::*;
use middle::ty;
use util::ppaux::ty_to_str;
use std::vec;
use syntax::ast;
@ -160,25 +159,7 @@ pub fn maybe_instantiate_inline(ccx: @CrateContext, fn_id: ast::DefId)
let llfn = get_item_val(ccx, mth.id);
let path = vec::append_one(
ty::item_path(ccx.tcx, impl_did), PathName(mth.ident));
let self_kind = match mth.explicit_self.node {
ast::SelfStatic => None,
_ => {
let self_ty = ty::node_id_to_type(ccx.tcx,
mth.self_id);
debug!("calling inline trans_fn with self_ty {}",
ty_to_str(ccx.tcx, self_ty));
Some(self_ty)
}
};
trans_fn(ccx,
path,
mth.decl,
mth.body,
llfn,
self_kind,
None,
mth.id,
[]);
trans_fn(ccx, path, mth.decl, mth.body, llfn, None, mth.id, []);
}
local_def(mth.id)
}

View file

@ -153,13 +153,8 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
let output_type = ty::ty_fn_ret(ty::node_id_to_type(ccx.tcx, item.id));
let fcx = new_fn_ctxt_detailed(ccx,
path,
decl,
item.id,
output_type,
Some(substs),
Some(item.span));
let fcx = new_fn_ctxt_detailed(ccx, path, decl, item.id, false, output_type,
Some(substs), Some(item.span));
init_function(&fcx, true, output_type, Some(substs));
set_always_inline(fcx.llfn);
@ -420,7 +415,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
// FIXME This is a hack to grab the address of this particular
// native function. There should be a general in-language
// way to do this
let llfty = type_of_rust_fn(bcx.ccx(), None, [], ty::mk_nil());
let llfty = type_of_rust_fn(bcx.ccx(), false, [], ty::mk_nil());
let morestack_addr = decl_cdecl_fn(bcx.ccx().llmod, "__morestack",
llfty, ty::mk_nil());
let morestack_addr = PointerCast(bcx, morestack_addr,

View file

@ -51,7 +51,7 @@ pub fn trans_impl(ccx: @CrateContext,
methods: &[@ast::Method],
generics: &ast::Generics,
id: ast::NodeId) {
let _icx = push_ctxt("impl::trans_impl");
let _icx = push_ctxt("meth::trans_impl");
let tcx = ccx.tcx;
debug!("trans_impl(path={}, name={}, id={:?})",
@ -73,11 +73,8 @@ pub fn trans_impl(ccx: @CrateContext,
let path = vec::append_one(sub_path.clone(),
PathName(method.ident));
trans_method(ccx,
path,
*method,
None,
|_| llfn);
trans_fn(ccx, path, method.decl, method.body,
llfn, None, method.id, []);
} else {
let mut v = TransItemVisitor{ ccx: ccx };
visit::walk_method_helper(&mut v, *method, ());
@ -91,49 +88,15 @@ pub fn trans_impl(ccx: @CrateContext,
/// * `path`: the path to the method
/// * `method`: the AST node for the method
/// * `param_substs`: if this is a generic method, the current values for
/// type parameters and so forth, else none
/// * `llfn`: a closure returning the LLVM ValueRef for the method
/// * `impl_id`: the node ID of the impl this method is inside
/// type parameters and so forth, else None
/// * `llfn`: the LLVM ValueRef for the method
///
/// FIXME(pcwalton) Can we take `path` by reference?
pub fn trans_method(ccx: @CrateContext,
path: Path,
method: &ast::Method,
pub fn trans_method(ccx: @CrateContext, path: Path, method: &ast::Method,
param_substs: Option<@param_substs>,
llfn_with_self: |Option<ty::t>| -> ValueRef) -> ValueRef {
// figure out how self is being passed
let self_ty = match method.explicit_self.node {
ast::SelfStatic => None,
_ => {
// determine the (monomorphized) type that `self` maps to for
// this method
let self_ty = ty::node_id_to_type(ccx.tcx, method.self_id);
let self_ty = match param_substs {
None => self_ty,
Some(param_substs) => {
ty::subst_tps(ccx.tcx,
param_substs.tys,
param_substs.self_ty,
self_ty)
}
};
debug!("calling trans_fn with self_ty {}", self_ty.repr(ccx.tcx));
Some(self_ty)
}
};
let llfn = llfn_with_self(self_ty);
// generate the actual code
trans_fn(ccx,
path,
method.decl,
method.body,
llfn,
self_ty,
param_substs,
method.id,
[]);
llfn: ValueRef) -> ValueRef {
trans_fn(ccx, path, method.decl, method.body,
llfn, param_substs, method.id, []);
llfn
}
@ -144,31 +107,17 @@ pub fn trans_method_callee<'a>(
mentry: typeck::method_map_entry,
arg_cleanup_scope: cleanup::ScopeId)
-> Callee<'a> {
let _icx = push_ctxt("impl::trans_method_callee");
let _icx = push_ctxt("meth::trans_method_callee");
debug!("trans_method_callee(callee_id={:?}, this={}, mentry={})",
debug!("trans_method_callee(callee_id={:?}, mentry={})",
callee_id,
bcx.expr_to_str(this),
mentry.repr(bcx.tcx()));
match mentry.origin {
typeck::method_static(did) => {
let self_ty = monomorphize_type(bcx, mentry.self_ty);
let Result {bcx, val} = trans_arg_expr(bcx, self_ty, this,
arg_cleanup_scope,
DontAutorefArg);
// HACK should not need the pointer cast, eventually trans_fn_ref
// should return a function type with the right type for self.
let callee_fn = callee::trans_fn_ref(bcx, did, callee_id);
let fn_ty = node_id_type(bcx, callee_id);
let llfn_ty = type_of_fn_from_ty(bcx.ccx(), Some(self_ty), fn_ty).ptr_to();
let llfn_val = PointerCast(bcx, callee_fn.llfn, llfn_ty);
Callee {
bcx: bcx,
data: Method(MethodData {
llfn: llfn_val,
llself: val,
})
data: Fn(callee::trans_fn_ref(bcx, did, callee_id))
}
}
typeck::method_param(typeck::method_param {
@ -184,9 +133,8 @@ pub fn trans_method_callee<'a>(
trait_id);
let vtbl = find_vtable(bcx.tcx(), substs, p, b);
trans_monomorphized_callee(bcx, callee_id, this, mentry,
trait_id, off, vtbl,
arg_cleanup_scope)
trans_monomorphized_callee(bcx, callee_id,
trait_id, off, vtbl)
}
// how to get rid of this?
None => fail!("trans_method_callee: missing param_substs")
@ -207,8 +155,8 @@ pub fn trans_static_method_callee(bcx: &Block,
method_id: ast::DefId,
trait_id: ast::DefId,
callee_id: ast::NodeId)
-> FnData {
let _icx = push_ctxt("impl::trans_static_method_callee");
-> ValueRef {
let _icx = push_ctxt("meth::trans_static_method_callee");
let ccx = bcx.ccx();
debug!("trans_static_method_callee(method_id={:?}, trait_id={}, \
@ -271,16 +219,13 @@ pub fn trans_static_method_callee(bcx: &Block,
bcx, mth_id, callee_id,
*rcvr_substs, rcvr_origins);
let FnData {llfn: lval} =
trans_fn_ref_with_vtables(bcx,
mth_id,
callee_id,
callee_substs,
Some(callee_origins));
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, callee_id,
callee_substs,
Some(callee_origins));
let callee_ty = node_id_type(bcx, callee_id);
let llty = type_of_fn_from_ty(ccx, None, callee_ty).ptr_to();
FnData {llfn: PointerCast(bcx, lval, llty)}
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
PointerCast(bcx, llfn, llty)
}
_ => {
fail!("vtable_param left in monomorphized \
@ -312,29 +257,19 @@ pub fn method_with_name(ccx: &CrateContext,
meth.def_id
}
pub fn trans_monomorphized_callee<'a>(
bcx: &'a Block<'a>,
fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
callee_id: ast::NodeId,
base: &ast::Expr,
mentry: typeck::method_map_entry,
trait_id: ast::DefId,
n_method: uint,
vtbl: typeck::vtable_origin,
arg_cleanup_scope: cleanup::ScopeId)
vtbl: typeck::vtable_origin)
-> Callee<'a> {
let _icx = push_ctxt("impl::trans_monomorphized_callee");
let _icx = push_ctxt("meth::trans_monomorphized_callee");
return match vtbl {
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
let ccx = bcx.ccx();
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
let mth_id = method_with_name(bcx.ccx(), impl_did, mname.name);
// obtain the `self` value:
let self_ty = monomorphize_type(bcx, mentry.self_ty);
let Result {bcx, val} = trans_arg_expr(bcx, self_ty, base,
arg_cleanup_scope,
DontAutorefArg);
// create a concatenated set of substitutions which includes
// those from the impl and those from the method:
let (callee_substs, callee_origins) =
@ -343,26 +278,13 @@ pub fn trans_monomorphized_callee<'a>(
*rcvr_substs, rcvr_origins);
// translate the function
let callee = trans_fn_ref_with_vtables(bcx,
mth_id,
callee_id,
callee_substs,
Some(callee_origins));
let llfn = trans_fn_ref_with_vtables(bcx,
mth_id,
callee_id,
callee_substs,
Some(callee_origins));
// create a llvalue that represents the fn ptr
// HACK should not need the pointer cast (add self in trans_fn_ref_with_vtables).
let fn_ty = node_id_type(bcx, callee_id);
let llfn_ty = type_of_fn_from_ty(ccx, Some(self_ty), fn_ty).ptr_to();
let llfn_val = PointerCast(bcx, callee.llfn, llfn_ty);
// combine the self environment with the rest
Callee {
bcx: bcx,
data: Method(MethodData {
llfn: llfn_val,
llself: val,
})
}
Callee { bcx: bcx, data: Fn(llfn) }
}
typeck::vtable_param(..) => {
fail!("vtable_param left in monomorphized function's vtable substs");
@ -420,8 +342,7 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
return (ty_substs, vtables);
}
pub fn trans_trait_callee<'a>(
bcx: &'a Block<'a>,
fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
callee_id: ast::NodeId,
n_method: uint,
self_expr: &ast::Expr,
@ -436,7 +357,7 @@ pub fn trans_trait_callee<'a>(
* pair.
*/
let _icx = push_ctxt("impl::trans_trait_callee");
let _icx = push_ctxt("meth::trans_trait_callee");
let mut bcx = bcx;
// Translate self_datum and take ownership of the value by
@ -469,18 +390,26 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
* a by-ref pointer to the object pair.
*/
let _icx = push_ctxt("impl::trans_trait_callee");
let _icx = push_ctxt("meth::trans_trait_callee");
let ccx = bcx.ccx();
// Load the data pointer from the object.
debug!("(translating trait callee) loading second index from pair");
let llboxptr = GEPi(bcx, llpair, [0u, abi::trt_field_box]);
let llbox = Load(bcx, llboxptr);
let llself = PointerCast(bcx, llbox, Type::opaque_box(ccx).ptr_to());
let llself = PointerCast(bcx, llbox, Type::i8p());
// Load the function from the vtable and cast it to the expected type.
debug!("(translating trait callee) loading method");
let llcallee_ty = type_of_fn_from_ty(ccx, None, callee_ty);
// Replace the self type (&Self or ~Self) with an opaque pointer.
let llcallee_ty = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) if f.abis.is_rust() => {
type_of_rust_fn(ccx, true, f.sig.inputs.slice_from(1), f.sig.output)
}
_ => {
ccx.sess.bug("meth::trans_trait_callee given non-bare-rust-fn");
}
};
let llvtable = Load(bcx,
PointerCast(bcx,
GEPi(bcx, llpair,
@ -491,7 +420,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
return Callee {
bcx: bcx,
data: Method(MethodData {
data: TraitMethod(MethodData {
llfn: mptr,
llself: llself,
})
@ -528,7 +457,7 @@ pub fn get_vtable(bcx: &Block,
origins: typeck::vtable_param_res)
-> ValueRef {
let ccx = bcx.ccx();
let _icx = push_ctxt("impl::get_vtable");
let _icx = push_ctxt("meth::get_vtable");
// Check the cache.
let hash_id = (self_ty, vtable_id(ccx, &origins[0]));
@ -567,7 +496,7 @@ pub fn make_vtable(ccx: &CrateContext,
ptrs: &[ValueRef])
-> ValueRef {
unsafe {
let _icx = push_ctxt("impl::make_vtable");
let _icx = push_ctxt("meth::make_vtable");
let mut components = ~[ tydesc.tydesc ];
for &ptr in ptrs.iter() {
@ -618,8 +547,7 @@ fn emit_vtable_methods(bcx: &Block,
tcx.sess.str_of(ident));
C_null(Type::nil().ptr_to())
} else {
trans_fn_ref_with_vtables(bcx, m_id, 0,
substs, Some(vtables)).llfn
trans_fn_ref_with_vtables(bcx, m_id, 0, substs, Some(vtables))
}
})
}
@ -637,7 +565,7 @@ pub fn trans_trait_cast<'a>(bcx: &'a Block<'a>,
*/
let mut bcx = bcx;
let _icx = push_ctxt("impl::trans_cast");
let _icx = push_ctxt("meth::trans_cast");
let lldest = match dest {
Ignore => {

View file

@ -213,8 +213,10 @@ pub fn monomorphic_fn(ccx: @CrateContext,
let s = mangle_exported_name(ccx, pt.clone(), mono_ty);
debug!("monomorphize_fn mangled to {}", s);
let mk_lldecl = |self_ty| {
let lldecl = decl_internal_rust_fn(ccx, self_ty, f.sig.inputs, f.sig.output, s);
let mk_lldecl = || {
let lldecl = decl_internal_rust_fn(ccx, false,
f.sig.inputs,
f.sig.output, s);
let mut monomorphized = ccx.monomorphized.borrow_mut();
monomorphized.get().insert(hash_id, lldecl);
lldecl
@ -227,17 +229,9 @@ pub fn monomorphic_fn(ccx: @CrateContext,
node: ast::ItemFn(decl, _, _, _, body),
..
} => {
let d = mk_lldecl(None);
let d = mk_lldecl();
set_llvm_fn_attrs(i.attrs, d);
trans_fn(ccx,
pt,
decl,
body,
d,
None,
Some(psubsts),
fn_id.node,
[]);
trans_fn(ccx, pt, decl, body, d, Some(psubsts), fn_id.node, []);
d
}
_ => {
@ -246,7 +240,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
}
}
ast_map::NodeForeignItem(i, _, _, _) => {
let d = mk_lldecl(None);
let d = mk_lldecl();
intrinsic::trans_intrinsic(ccx, d, i, pt, psubsts, i.attrs,
ref_id);
d
@ -254,7 +248,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
ast_map::NodeVariant(v, enum_item, _) => {
let tvs = ty::enum_variants(ccx.tcx, local_def(enum_item.id));
let this_tv = *tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
let d = mk_lldecl(None);
let d = mk_lldecl();
set_inline_hint(d);
match v.node.kind {
ast::TupleVariantKind(ref args) => {
@ -272,24 +266,19 @@ pub fn monomorphic_fn(ccx: @CrateContext,
d
}
ast_map::NodeMethod(mth, _, _) => {
meth::trans_method(ccx, pt, mth, Some(psubsts), |self_ty| {
let d = mk_lldecl(self_ty);
set_llvm_fn_attrs(mth.attrs, d);
d
})
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs, d);
trans_fn(ccx, pt, mth.decl, mth.body, d, Some(psubsts), mth.id, []);
d
}
ast_map::NodeTraitMethod(method, _, pt) => {
match *method {
ast::Provided(mth) => {
meth::trans_method(ccx,
(*pt).clone(),
mth,
Some(psubsts),
|self_ty| {
let d = mk_lldecl(self_ty);
set_llvm_fn_attrs(mth.attrs, d);
d
})
let d = mk_lldecl();
set_llvm_fn_attrs(mth.attrs, d);
trans_fn(ccx, (*pt).clone(), mth.decl, mth.body,
d, Some(psubsts), mth.id, []);
d
}
_ => {
ccx.tcx.sess.bug(format!("Can't monomorphize a {:?}",
@ -298,7 +287,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
}
}
ast_map::NodeStructCtor(struct_def, _, _) => {
let d = mk_lldecl(None);
let d = mk_lldecl();
set_inline_hint(d);
base::trans_tuple_struct(ccx,
struct_def.fields,

View file

@ -13,7 +13,7 @@
use middle::trans::adt;
use middle::trans::base::*;
use middle::trans::build::*;
use middle::trans::callee::{ArgVals, DontAutorefArg};
use middle::trans::callee::ArgVals;
use middle::trans::callee;
use middle::trans::common::*;
use middle::trans::datum::*;
@ -111,7 +111,7 @@ pub fn visit(&mut self, ty_name: &str, args: &[ValueRef]) {
mth_ty,
mth_idx,
v),
ArgVals(args), None, DontAutorefArg));
ArgVals(args), None));
let result = bool_to_i1(bcx, result);
let next_bcx = fcx.new_temp_block("next");
CondBr(bcx, result, next_bcx.llbb, self.final_bcx.llbb);
@ -292,12 +292,10 @@ pub fn visit_ty(&mut self, t: ty::t) {
sub_path,
"get_disr");
let llfdecl = decl_internal_rust_fn(ccx, None, [opaqueptrty], ty::mk_u64(), sym);
let fcx = new_fn_ctxt(ccx,
~[],
llfdecl,
ty::mk_u64(),
None);
let llfdecl = decl_internal_rust_fn(ccx, false,
[opaqueptrty],
ty::mk_u64(), sym);
let fcx = new_fn_ctxt(ccx, ~[], llfdecl, false, ty::mk_u64(), None);
init_function(&fcx, false, ty::mk_u64(), None);
let arg = unsafe {
@ -358,12 +356,7 @@ pub fn visit_ty(&mut self, t: ty::t) {
self.visit("param", extra)
}
ty::ty_self(..) => self.leaf("self"),
ty::ty_type => self.leaf("type"),
ty::ty_opaque_closure_ptr(ck) => {
let ckval = ast_sigil_constant(ck);
let extra = ~[self.c_uint(ckval)];
self.visit("closure_ptr", extra)
}
ty::ty_type => self.leaf("type")
}
}

View file

@ -160,10 +160,6 @@ pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
args.len() as c_uint, True))
}
pub fn func_pair(cx: &CrateContext, fn_ty: &Type) -> Type {
Type::struct_([fn_ty.ptr_to(), Type::opaque_cbox_ptr(cx)], false)
}
pub fn ptr(ty: Type) -> Type {
ty!(llvm::LLVMPointerType(ty.to_ref(), 0 as c_uint))
}
@ -200,8 +196,7 @@ pub fn generic_glue_fn(cx: &CrateContext) -> Type {
}
pub fn glue_fn(t: Type) -> Type {
Type::func([ Type::nil().ptr_to(), t ],
&Type::void())
Type::func([t], &Type::void())
}
pub fn tydesc(arch: Architecture) -> Type {
@ -213,7 +208,6 @@ pub fn tydesc(arch: Architecture) -> Type {
// Must mirror:
//
// std::unstable::intrinsics::TyDesc
// type_desc in rt
let elems = [int_ty, // size
int_ty, // align
@ -244,38 +238,18 @@ pub fn opaque_vec(arch: Architecture) -> Type {
Type::vec(arch, &Type::i8())
}
#[inline]
pub fn box_header_fields(ctx: &CrateContext) -> ~[Type] {
~[
// The box pointed to by @T.
pub fn at_box(ctx: &CrateContext, ty: Type) -> Type {
Type::struct_([
ctx.int_type, ctx.tydesc_type.ptr_to(),
Type::i8().ptr_to(), Type::i8().ptr_to()
]
}
pub fn box_header(ctx: &CrateContext) -> Type {
Type::struct_(Type::box_header_fields(ctx), false)
}
pub fn smart_ptr(ctx: &CrateContext, ty: &Type) -> Type {
Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
}
pub fn opaque() -> Type {
Type::i8()
}
pub fn opaque_box(ctx: &CrateContext) -> Type {
Type::smart_ptr(ctx, &Type::opaque())
}
pub fn opaque_cbox_ptr(cx: &CrateContext) -> Type {
Type::opaque_box(cx).ptr_to()
Type::i8p(), Type::i8p(), ty
], false)
}
pub fn opaque_trait(ctx: &CrateContext, store: ty::TraitStore) -> Type {
let tydesc_ptr = ctx.tydesc_type.ptr_to();
let box_ty = match store {
ty::BoxTraitStore => Type::opaque_box(ctx),
ty::BoxTraitStore => Type::at_box(ctx, Type::i8()),
ty::UniqTraitStore => Type::i8(),
ty::RegionTraitStore(..) => Type::i8()
};

View file

@ -38,15 +38,8 @@ pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type {
}
}
pub fn type_of_explicit_args(ccx: &CrateContext,
inputs: &[ty::t]) -> ~[Type] {
inputs.map(|&arg_ty| type_of_explicit_arg(ccx, arg_ty))
}
pub fn type_of_rust_fn(cx: &CrateContext,
self_ty: Option<ty::t>,
inputs: &[ty::t],
output: ty::t) -> Type {
pub fn type_of_rust_fn(cx: &CrateContext, has_env: bool,
inputs: &[ty::t], output: ty::t) -> Type {
let mut atys: ~[Type] = ~[];
// Arg 0: Output pointer.
@ -58,14 +51,13 @@ pub fn type_of_rust_fn(cx: &CrateContext,
}
// Arg 1: Environment
let env = match self_ty {
Some(t) => type_of_explicit_arg(cx, t),
None => Type::opaque_box(cx).ptr_to()
};
atys.push(env);
if has_env {
atys.push(Type::i8p());
}
// ... then explicit args.
atys.push_all(type_of_explicit_args(cx, inputs));
let mut input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
atys.extend(&mut input_tys);
// Use the output as the actual return value if it's immediate.
if use_out_pointer || return_type_is_void(cx, output) {
@ -76,14 +68,14 @@ pub fn type_of_rust_fn(cx: &CrateContext,
}
// Given a function type and a count of ty params, construct an llvm type
pub fn type_of_fn_from_ty(cx: &CrateContext, self_ty: Option<ty::t>, fty: ty::t) -> Type {
return match ty::get(fty).sty {
pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type {
match ty::get(fty).sty {
ty::ty_closure(ref f) => {
type_of_rust_fn(cx, None, f.sig.inputs, f.sig.output)
type_of_rust_fn(cx, true, f.sig.inputs, f.sig.output)
}
ty::ty_bare_fn(ref f) => {
if f.abis.is_rust() || f.abis.is_intrinsic() {
type_of_rust_fn(cx, self_ty, f.sig.inputs, f.sig.output)
type_of_rust_fn(cx, false, f.sig.inputs, f.sig.output)
} else {
foreign::lltype_for_foreign_fn(cx, fty)
}
@ -91,7 +83,7 @@ pub fn type_of_fn_from_ty(cx: &CrateContext, self_ty: Option<ty::t>, fty: ty::t)
_ => {
cx.sess.bug("type_of_fn_from_ty given non-closure, non-bare-fn")
}
};
}
}
// A "sizing type" is an LLVM type, the size and alignment of which are
@ -130,8 +122,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
ty::ty_uniq(..) |
ty::ty_ptr(..) |
ty::ty_rptr(..) |
ty::ty_type |
ty::ty_opaque_closure_ptr(..) => Type::i8p(),
ty::ty_type => Type::i8p(),
ty::ty_str(ty::vstore_slice(..)) |
ty::ty_vec(_, ty::vstore_slice(..)) => {
@ -231,18 +222,14 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
adt::incomplete_type_of(cx, repr, name)
}
ty::ty_str(ty::vstore_box) => {
Type::smart_ptr(cx,
&Type::vec(cx.sess.targ_cfg.arch,
&Type::i8())).ptr_to()
Type::at_box(cx, Type::vec(cx.sess.targ_cfg.arch, &Type::i8())).ptr_to()
}
ty::ty_vec(ref mt, ty::vstore_box) => {
let e_ty = type_of(cx, mt.ty);
let v_ty = Type::vec(cx.sess.targ_cfg.arch, &e_ty);
Type::smart_ptr(cx, &v_ty).ptr_to()
Type::at_box(cx, Type::vec(cx.sess.targ_cfg.arch, &e_ty)).ptr_to()
}
ty::ty_box(typ) => {
let ty = type_of(cx, typ);
Type::smart_ptr(cx, &ty).ptr_to()
Type::at_box(cx, type_of(cx, typ)).ptr_to()
}
ty::ty_uniq(typ) => {
type_of(cx, typ).ptr_to()
@ -278,11 +265,11 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
}
ty::ty_bare_fn(_) => {
type_of_fn_from_ty(cx, None, t).ptr_to()
type_of_fn_from_ty(cx, t).ptr_to()
}
ty::ty_closure(_) => {
let ty = type_of_fn_from_ty(cx, None, t);
Type::func_pair(cx, &ty)
let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
Type::struct_([fn_ty, Type::i8p()], false)
}
ty::ty_trait(_, _, store, _, _) => Type::opaque_trait(cx, store),
ty::ty_type => cx.tydesc_type.ptr_to(),
@ -290,7 +277,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
let repr = adt::represent_type(cx, t);
adt::type_of(cx, repr)
}
ty::ty_opaque_closure_ptr(_) => Type::opaque_box(cx).ptr_to(),
ty::ty_struct(did, ref substs) => {
if ty::type_is_simd(cx.tcx, t) {
let et = ty::simd_type(cx.tcx, t);

View file

@ -73,7 +73,6 @@ pub enum MethodContainer {
pub struct Method {
ident: ast::Ident,
generics: ty::Generics,
transformed_self_ty: Option<ty::t>,
fty: BareFnTy,
explicit_self: ast::ExplicitSelf_,
vis: ast::Visibility,
@ -87,7 +86,6 @@ pub struct Method {
impl Method {
pub fn new(ident: ast::Ident,
generics: ty::Generics,
transformed_self_ty: Option<ty::t>,
fty: BareFnTy,
explicit_self: ast::ExplicitSelf_,
vis: ast::Visibility,
@ -95,17 +93,9 @@ pub fn new(ident: ast::Ident,
container: MethodContainer,
provided_source: Option<ast::DefId>)
-> Method {
// Check the invariants.
if explicit_self == ast::SelfStatic {
assert!(transformed_self_ty.is_none());
} else {
assert!(transformed_self_ty.is_some());
}
Method {
ident: ident,
generics: generics,
transformed_self_ty: transformed_self_ty,
fty: fty,
explicit_self: explicit_self,
vis: vis,
@ -650,7 +640,6 @@ pub enum sty {
// "Fake" types, used for trans purposes
ty_type, // type_desc*
ty_opaque_closure_ptr(Sigil), // ptr to env for || and proc
ty_unboxed_vec(mt),
}
@ -1068,7 +1057,7 @@ fn sflags(substs: &substs) -> uint {
flags |= get(mt.ty).flags;
}
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_str(_) | &ty_type | &ty_opaque_closure_ptr(_) => {}
&ty_str(_) | &ty_type => {}
// You might think that we could just return ty_err for
// any type containing ty_err as a component, and get
// rid of the has_ty_err flag -- likewise for ty_bot (with
@ -1333,10 +1322,6 @@ pub fn mk_param(cx: ctxt, n: uint, k: DefId) -> t {
pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
mk_t(cx, ty_opaque_closure_ptr(sigil))
}
pub fn walk_ty(ty: t, f: |t|) {
maybe_walk_ty(ty, |t| { f(t); true });
}
@ -1346,27 +1331,27 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
return;
}
match get(ty).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str(_) | ty_type | ty_self(_) |
ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {}
ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
ty_trait(_, ref substs, _, _, _) => {
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
ty_bare_fn(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
maybe_walk_ty(ft.sig.output, f);
}
ty_closure(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
maybe_walk_ty(ft.sig.output, f);
}
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str(_) | ty_type | ty_self(_) |
ty_infer(_) | ty_param(_) | ty_err => {}
ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
ty_vec(ref tm, _) | ty_unboxed_vec(ref tm) | ty_ptr(ref tm) |
ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
ty_trait(_, ref substs, _, _, _) => {
for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
}
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
ty_bare_fn(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
maybe_walk_ty(ft.sig.output, f);
}
ty_closure(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
maybe_walk_ty(ft.sig.output, f);
}
}
}
@ -1608,11 +1593,8 @@ pub fn type_is_vec(ty: t) -> bool {
pub fn type_is_unique(ty: t) -> bool {
match get(ty).sty {
ty_uniq(_) |
ty_vec(_, vstore_uniq) |
ty_str(vstore_uniq) |
ty_opaque_closure_ptr(ast::OwnedSigil) => true,
_ => return false
ty_uniq(_) | ty_vec(_, vstore_uniq) | ty_str(vstore_uniq) => true,
_ => false
}
}
@ -2118,13 +2100,6 @@ fn tc_ty(cx: ctxt,
TC::All
}
ty_unboxed_vec(mt) => TC::InteriorUnsized | tc_mt(cx, mt, cache),
ty_opaque_closure_ptr(sigil) => {
match sigil {
ast::BorrowedSigil => TC::ReachesBorrowed,
ast::ManagedSigil => TC::Managed,
ast::OwnedSigil => TC::OwnsOwned,
}
}
ty_type => TC::None,
@ -2308,7 +2283,6 @@ fn subtypes_require(cx: ctxt, seen: &mut ~[DefId],
ty_param(_) |
ty_self(_) |
ty_type |
ty_opaque_closure_ptr(_) |
ty_vec(_, _) |
ty_unboxed_vec(_) => {
false
@ -2511,7 +2485,6 @@ pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
result = type_is_pod(cx, mt.ty);
}
ty_param(_) => result = false,
ty_opaque_closure_ptr(_) => result = true,
ty_struct(did, ref substs) => {
let fields = lookup_struct_fields(cx, did);
result = fields.iter().all(|f| {
@ -3139,22 +3112,37 @@ pub fn expr_kind(tcx: ctxt,
}
match expr.node {
ast::ExprPath(..) | ast::ExprSelf => {
ast::ExprPath(..) => {
match resolve_expr(tcx, expr) {
ast::DefVariant(..) | ast::DefStruct(..) => RvalueDpsExpr,
ast::DefVariant(tid, vid, _) => {
let variant_info = enum_variant_with_id(tcx, tid, vid);
if variant_info.args.len() > 0u {
// N-ary variant.
RvalueDatumExpr
} else {
// Nullary variant.
RvalueDpsExpr
}
}
ast::DefStruct(_) => {
match get(expr_ty(tcx, expr)).sty {
ty_bare_fn(..) => RvalueDatumExpr,
_ => RvalueDpsExpr
}
}
// Fn pointers are just scalar values.
ast::DefFn(..) | ast::DefStaticMethod(..) => RvalueDatumExpr,
// Note: there is actually a good case to be made that
// def_args, particularly those of immediate type, ought to
// DefArg's, particularly those of immediate type, ought to
// considered rvalues.
ast::DefStatic(..) |
ast::DefBinding(..) |
ast::DefUpvar(..) |
ast::DefArg(..) |
ast::DefLocal(..) |
ast::DefSelf(..) => LvalueExpr,
ast::DefLocal(..) => LvalueExpr,
def => {
tcx.sess.span_bug(expr.span, format!(
@ -3343,30 +3331,29 @@ fn vars_in_type(ty: t) -> ~[TyVid] {
pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
match get(t).sty {
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str(_) |
ty_type | ty_opaque_closure_ptr(_) => {
::util::ppaux::ty_to_str(cx, t)
}
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str(_) | ty_type => {
::util::ppaux::ty_to_str(cx, t)
}
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_box(_) => ~"@-ptr",
ty_uniq(_) => ~"~-ptr",
ty_vec(_, _) => ~"vector",
ty_unboxed_vec(_) => ~"unboxed vector",
ty_ptr(_) => ~"*-ptr",
ty_rptr(_, _) => ~"&-ptr",
ty_bare_fn(_) => ~"extern fn",
ty_closure(_) => ~"fn",
ty_trait(id, _, _, _, _) => format!("trait {}", item_path_str(cx, id)),
ty_struct(id, _) => format!("struct {}", item_path_str(cx, id)),
ty_tup(_) => ~"tuple",
ty_infer(TyVar(_)) => ~"inferred type",
ty_infer(IntVar(_)) => ~"integral variable",
ty_infer(FloatVar(_)) => ~"floating-point variable",
ty_param(_) => ~"type parameter",
ty_self(_) => ~"self",
ty_err => ~"type error"
ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
ty_box(_) => ~"@-ptr",
ty_uniq(_) => ~"~-ptr",
ty_vec(_, _) => ~"vector",
ty_unboxed_vec(_) => ~"unboxed vector",
ty_ptr(_) => ~"*-ptr",
ty_rptr(_, _) => ~"&-ptr",
ty_bare_fn(_) => ~"extern fn",
ty_closure(_) => ~"fn",
ty_trait(id, _, _, _, _) => format!("trait {}", item_path_str(cx, id)),
ty_struct(id, _) => format!("struct {}", item_path_str(cx, id)),
ty_tup(_) => ~"tuple",
ty_infer(TyVar(_)) => ~"inferred type",
ty_infer(IntVar(_)) => ~"integral variable",
ty_infer(FloatVar(_)) => ~"floating-point variable",
ty_param(_) => ~"type parameter",
ty_self(_) => ~"self",
ty_err => ~"type error"
}
}
@ -4912,12 +4899,8 @@ fn iter<T: IterBytes>(hash: &mut SipState, t: &T) {
ty_infer(_) => unreachable!(),
ty_err => hash.input([23]),
ty_type => hash.input([24]),
ty_opaque_closure_ptr(s) => {
hash.input([25]);
iter(&mut hash, &s);
}
ty_unboxed_vec(m) => {
hash.input([26]);
hash.input([25]);
mt(&mut hash, m);
}
}

View file

@ -189,7 +189,6 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char |
ty::ty_int(_) | ty::ty_uint(_) |
ty::ty_float(_) | ty::ty_type |
ty::ty_opaque_closure_ptr(_) |
ty::ty_err | ty::ty_infer(_) |
ty::ty_param(..) | ty::ty_self(_) => {
(*sty).clone()

View file

@ -589,13 +589,8 @@ fn check_path_args(tcx: ty::ctxt,
return typ;
}
pub fn ty_of_arg<AC:AstConv,
RS:RegionScope>(
this: &AC,
rscope: &RS,
a: &ast::Arg,
expected_ty: Option<ty::t>)
-> ty::t {
pub fn ty_of_arg<AC: AstConv, RS: RegionScope>(this: &AC, rscope: &RS, a: &ast::Arg,
expected_ty: Option<ty::t>) -> ty::t {
match a.ty.node {
ast::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
ast::TyInfer => this.ty_infer(a.ty.span),
@ -614,77 +609,38 @@ pub fn ty_of_method<AC:AstConv>(
purity: ast::Purity,
untransformed_self_ty: ty::t,
explicit_self: ast::ExplicitSelf,
decl: &ast::FnDecl) -> (Option<ty::t>, ty::BareFnTy)
{
let self_info = SelfInfo {
decl: &ast::FnDecl) -> ty::BareFnTy {
ty_of_method_or_bare_fn(this, id, purity, AbiSet::Rust(), Some(SelfInfo {
untransformed_self_ty: untransformed_self_ty,
explicit_self: explicit_self
};
let (a, b) = ty_of_method_or_bare_fn(
this, id, purity, AbiSet::Rust(), Some(&self_info), decl);
(a.unwrap(), b)
}), decl)
}
pub fn ty_of_bare_fn<AC:AstConv>(
this: &AC,
id: ast::NodeId,
purity: ast::Purity,
abi: AbiSet,
decl: &ast::FnDecl) -> ty::BareFnTy
{
let (_, b) = ty_of_method_or_bare_fn(this, id, purity,
abi, None, decl);
b
pub fn ty_of_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
purity: ast::Purity, abi: AbiSet,
decl: &ast::FnDecl) -> ty::BareFnTy {
ty_of_method_or_bare_fn(this, id, purity, abi, None, decl)
}
fn ty_of_method_or_bare_fn<AC:AstConv>(
this: &AC,
id: ast::NodeId,
purity: ast::Purity,
abi: AbiSet,
opt_self_info: Option<&SelfInfo>,
decl: &ast::FnDecl) -> (Option<Option<ty::t>>, ty::BareFnTy)
{
fn ty_of_method_or_bare_fn<AC:AstConv>(this: &AC, id: ast::NodeId,
purity: ast::Purity, abi: AbiSet,
opt_self_info: Option<SelfInfo>,
decl: &ast::FnDecl) -> ty::BareFnTy {
debug!("ty_of_method_or_bare_fn");
// new region names that appear inside of the fn decl are bound to
// that function type
let rb = rscope::BindingRscope::new(id);
let opt_transformed_self_ty = opt_self_info.map(|self_info| {
transform_self_ty(this, &rb, self_info)
});
let input_tys = decl.inputs.map(|a| ty_of_arg(this, &rb, a, None));
let output_ty = match decl.output.node {
ast::TyInfer => this.ty_infer(decl.output.span),
_ => ast_ty_to_ty(this, &rb, decl.output)
};
return (opt_transformed_self_ty,
ty::BareFnTy {
purity: purity,
abis: abi,
sig: ty::FnSig {binder_id: id,
inputs: input_tys,
output: output_ty,
variadic: decl.variadic}
});
fn transform_self_ty<AC:AstConv,RS:RegionScope>(
this: &AC,
rscope: &RS,
self_info: &SelfInfo) -> Option<ty::t>
{
let self_ty = opt_self_info.and_then(|self_info| {
match self_info.explicit_self.node {
ast::SelfStatic => None,
ast::SelfValue(_) => {
ast::SelfValue => {
Some(self_info.untransformed_self_ty)
}
ast::SelfRegion(ref lifetime, mutability) => {
let region =
opt_ast_region_to_region(this, rscope,
opt_ast_region_to_region(this, &rb,
self_info.explicit_self.span,
lifetime);
Some(ty::mk_rptr(this.tcx(), region,
@ -694,11 +650,37 @@ fn transform_self_ty<AC:AstConv,RS:RegionScope>(
ast::SelfBox => {
Some(ty::mk_box(this.tcx(), self_info.untransformed_self_ty))
}
ast::SelfUniq(_) => {
ast::SelfUniq => {
Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
}
}
}
});
// HACK(eddyb) replace the fake self type in the AST with the actual type.
let input_tys = if self_ty.is_some() {
decl.inputs.slice_from(1)
} else {
decl.inputs.as_slice()
};
let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
let output_ty = match decl.output.node {
ast::TyInfer => this.ty_infer(decl.output.span),
_ => ast_ty_to_ty(this, &rb, decl.output)
};
return ty::BareFnTy {
purity: purity,
abis: abi,
sig: ty::FnSig {
binder_id: id,
inputs: self_and_input_tys,
output: output_ty,
variadic: decl.variadic
}
};
}
pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(

View file

@ -80,6 +80,7 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
*/
use middle::subst::Subst;
use middle::resolve;
use middle::ty::*;
use middle::ty;
@ -422,19 +423,16 @@ fn push_inherent_candidates_from_object(&self,
|new_trait_ref, m, method_num, _bound_num| {
let vtable_index =
self.get_method_index(new_trait_ref, trait_ref, method_num);
let mut m = (*m).clone();
// We need to fix up the transformed self type.
let transformed_self_ty =
m.fty.sig.inputs[0] =
self.construct_transformed_self_ty_for_object(
did, &rcvr_substs, m);
let m = @Method {
transformed_self_ty: Some(transformed_self_ty),
.. (*m).clone()
};
did, &rcvr_substs, &m);
Candidate {
rcvr_match_condition: RcvrMatchesIfObject(did),
rcvr_substs: new_trait_ref.substs.clone(),
method_ty: m,
method_ty: @m,
origin: method_object(method_object {
trait_id: new_trait_ref.def_id,
object_trait_id: did,
@ -790,8 +788,7 @@ fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
ty_err => None,
ty_opaque_closure_ptr(_) | ty_unboxed_vec(_) |
ty_type | ty_infer(TyVar(_)) => {
ty_unboxed_vec(_) | ty_type | ty_infer(TyVar(_)) => {
self.bug(format!("Unexpected type: {}",
self.ty_to_str(self_ty)));
}
@ -932,32 +929,25 @@ fn merge_candidates(&self, candidates: &[Candidate]) -> ~[Candidate] {
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
-> method_map_entry {
// This method performs two sets of substitutions, one after the other:
// 1. Substitute values for any type/lifetime parameters from the impl and
// method declaration into the method type. This is the function type
// before it is called; it may still include late bound region variables.
// 2. Instantiate any late bound lifetime parameters in the method itself
// with fresh region variables.
let tcx = self.tcx();
let fty = ty::mk_bare_fn(tcx, candidate.method_ty.fty.clone());
debug!("confirm_candidate(expr={}, candidate={}, fty={})",
debug!("confirm_candidate(expr={}, candidate={})",
self.expr.repr(tcx),
self.cand_to_str(candidate),
self.ty_to_str(fty));
self.cand_to_str(candidate));
self.enforce_object_limitations(fty, candidate);
self.enforce_object_limitations(candidate);
self.enforce_drop_trait_limitations(candidate);
// static methods should never have gotten this far:
assert!(candidate.method_ty.explicit_self != SelfStatic);
let transformed_self_ty = match candidate.origin {
method_object(..) => {
// For annoying reasons, we've already handled the
// substitution for object calls.
candidate.method_ty.transformed_self_ty.unwrap()
}
_ => {
ty::subst(tcx, &candidate.rcvr_substs,
candidate.method_ty.transformed_self_ty.unwrap())
}
};
// Determine the values for the type parameters of the method.
// If they were not explicitly supplied, just construct fresh
// type variables.
@ -990,29 +980,41 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
self_ty: candidate.rcvr_substs.self_ty,
};
let ref bare_fn_ty = candidate.method_ty.fty;
// Compute the method type with type parameters substituted
debug!("fty={} all_substs={}",
self.ty_to_str(fty),
bare_fn_ty.repr(tcx),
ty::substs_to_str(tcx, &all_substs));
let fty = ty::subst(tcx, &all_substs, fty);
debug!("after subst, fty={}", self.ty_to_str(fty));
let fn_sig = &bare_fn_ty.sig;
let inputs = match candidate.origin {
method_object(..) => {
// For annoying reasons, we've already handled the
// substitution of self for object calls.
let args = fn_sig.inputs.slice_from(1).iter().map(|t| {
t.subst(tcx, &all_substs)
});
Some(fn_sig.inputs[0]).move_iter().chain(args).collect()
}
_ => fn_sig.inputs.subst(tcx, &all_substs)
};
let fn_sig = ty::FnSig {
binder_id: fn_sig.binder_id,
inputs: inputs,
output: fn_sig.output.subst(tcx, &all_substs),
variadic: fn_sig.variadic
};
debug!("after subst, fty={}", fn_sig.repr(tcx));
// Replace any bound regions that appear in the function
// signature with region variables
let bare_fn_ty = match ty::get(fty).sty {
ty::ty_bare_fn(ref f) => f,
ref s => {
tcx.sess.span_bug(
self.expr.span,
format!("Invoking method with non-bare-fn ty: {:?}", s));
}
};
let (_, opt_transformed_self_ty, fn_sig) =
replace_bound_regions_in_fn_sig(
tcx, Some(transformed_self_ty), &bare_fn_ty.sig,
|br| self.fcx.infcx().next_region_var(
infer::BoundRegionInFnCall(self.expr.span, br)));
let transformed_self_ty = opt_transformed_self_ty.unwrap();
let (_, fn_sig) = replace_bound_regions_in_fn_sig( tcx, &fn_sig, |br| {
self.fcx.infcx().next_region_var(
infer::BoundRegionInFnCall(self.expr.span, br))
});
let transformed_self_ty = fn_sig.inputs[0];
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
sig: fn_sig,
purity: bare_fn_ty.purity,
@ -1027,7 +1029,7 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
// should never fail.
match self.fcx.mk_subty(false, infer::Misc(self.self_expr.span),
rcvr_ty, transformed_self_ty) {
result::Ok(_) => (),
result::Ok(_) => {}
result::Err(_) => {
self.bug(format!("{} was a subtype of {} but now is not?",
self.ty_to_str(rcvr_ty),
@ -1038,9 +1040,7 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
self.fcx.write_ty(self.callee_id, fty);
self.fcx.write_substs(self.callee_id, all_substs);
method_map_entry {
self_ty: transformed_self_ty,
explicit_self: candidate.method_ty.explicit_self,
origin: candidate.origin,
origin: candidate.origin
}
}
@ -1064,7 +1064,7 @@ fn construct_transformed_self_ty_for_object(
* result to be `&'a Foo`. Assuming that `u_method` is being
* called, we want the result to be `~Foo`. Of course,
* this transformation has already been done as part of
* `method_ty.transformed_self_ty`, but there the type
* `method_ty.fty.sig.inputs[0]`, but there the type
* is expressed in terms of `Self` (i.e., `&'a Self`, `~Self`).
* Because objects are not standalone types, we can't just substitute
* `s/Self/Foo/`, so we must instead perform this kind of hokey
@ -1078,12 +1078,11 @@ fn construct_transformed_self_ty_for_object(
ast::SelfStatic => {
self.bug(~"static method for object type receiver");
}
ast::SelfValue(_) => {
ast::SelfValue => {
ty::mk_err() // error reported in `enforce_object_limitations()`
}
ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq(..) => {
let transformed_self_ty =
method_ty.transformed_self_ty.clone().unwrap();
ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq => {
let transformed_self_ty = method_ty.fty.sig.inputs[0];
match ty::get(transformed_self_ty).sty {
ty::ty_rptr(r, mt) => { // must be SelfRegion
ty::mk_trait(self.tcx(), trait_def_id,
@ -1110,10 +1109,7 @@ fn construct_transformed_self_ty_for_object(
}
}
fn enforce_object_limitations(&self,
method_fty: ty::t,
candidate: &Candidate)
{
fn enforce_object_limitations(&self, candidate: &Candidate) {
/*!
* There are some limitations to calling functions through an
* object, because (a) the self type is not known
@ -1137,21 +1133,38 @@ fn enforce_object_limitations(&self,
through an object");
}
ast::SelfValue(_) => { // reason (a) above
ast::SelfValue => { // reason (a) above
self.tcx().sess.span_err(
self.expr.span,
"cannot call a method with a by-value receiver \
through an object");
}
ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq(..) => {}
ast::SelfRegion(..) | ast::SelfBox | ast::SelfUniq => {}
}
if ty::type_has_self(method_fty) { // reason (a) above
self.tcx().sess.span_err(
self.expr.span,
"cannot call a method whose type contains a \
self-type through an object");
// reason (a) above
let check_for_self_ty = |ty| {
if ty::type_has_self(ty) {
self.tcx().sess.span_err(
self.expr.span,
"cannot call a method whose type contains a \
self-type through an object");
true
} else {
false
}
};
let ref sig = candidate.method_ty.fty.sig;
let mut found_self_ty = false;
for &input_ty in sig.inputs.iter() {
if check_for_self_ty(input_ty) {
found_self_ty = true;
break;
}
}
if !found_self_ty {
check_for_self_ty(sig.output);
}
if candidate.method_ty.generics.has_type_params() { // reason (b) above
@ -1198,7 +1211,7 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
false
}
SelfValue(_) => {
SelfValue => {
rcvr_matches_ty(self.fcx, rcvr_ty, candidate)
}
@ -1234,7 +1247,7 @@ fn is_relevant(&self, rcvr_ty: ty::t, candidate: &Candidate) -> bool {
}
}
SelfUniq(_) => {
SelfUniq => {
debug!("(is relevant?) explicit self is a unique pointer");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {

View file

@ -142,12 +142,6 @@
pub mod demand;
pub mod method;
pub struct SelfInfo {
self_ty: ty::t,
self_id: ast::NodeId,
span: Span
}
/// Fields that are part of a `FnCtxt` which are inherited by
/// closures defined within the function. For example:
///
@ -320,23 +314,21 @@ pub fn check_item_types(ccx: @CrateCtxt, crate: &ast::Crate) {
visit::walk_crate(&mut visit, crate, ());
}
pub fn check_bare_fn(ccx: @CrateCtxt,
decl: &ast::FnDecl,
body: &ast::Block,
id: ast::NodeId,
self_info: Option<SelfInfo>,
fty: ty::t,
param_env: ty::ParameterEnvironment) {
fn check_bare_fn(ccx: @CrateCtxt,
decl: &ast::FnDecl,
body: &ast::Block,
id: ast::NodeId,
fty: ty::t,
param_env: ty::ParameterEnvironment) {
match ty::get(fty).sty {
ty::ty_bare_fn(ref fn_ty) => {
let fcx =
check_fn(ccx, self_info, fn_ty.purity,
&fn_ty.sig, decl, id, body, Vanilla,
@Inherited::new(ccx.tcx, param_env));
check_fn(ccx, fn_ty.purity, &fn_ty.sig, decl, id, body,
Vanilla, @Inherited::new(ccx.tcx, param_env));
vtable::resolve_in_block(fcx, body);
regionck::regionck_fn(fcx, body);
writeback::resolve_type_vars_in_fn(fcx, decl, body, self_info);
writeback::resolve_type_vars_in_fn(fcx, decl, body);
}
_ => ccx.tcx.sess.impossible_case(body.span,
"check_bare_fn: function type expected")
@ -419,15 +411,14 @@ fn visit_item(&mut self, _: &ast::Item, _: ()) { }
}
pub fn check_fn(ccx: @CrateCtxt,
opt_self_info: Option<SelfInfo>,
purity: ast::Purity,
fn_sig: &ty::FnSig,
decl: &ast::FnDecl,
id: ast::NodeId,
body: &ast::Block,
fn_kind: FnKind,
inherited: @Inherited) -> @FnCtxt
fn check_fn(ccx: @CrateCtxt,
purity: ast::Purity,
fn_sig: &ty::FnSig,
decl: &ast::FnDecl,
id: ast::NodeId,
body: &ast::Block,
fn_kind: FnKind,
inherited: @Inherited) -> @FnCtxt
{
/*!
* Helper used by check_bare_fn and check_expr_fn. Does the
@ -442,99 +433,44 @@ pub fn check_fn(ccx: @CrateCtxt,
let tcx = ccx.tcx;
let err_count_on_creation = tcx.sess.err_count();
// First, we have to replace any bound regions in the fn and self
// types with free ones. The free region references will be bound
// the node_id of the body block.
let (opt_self_info, fn_sig) = {
let opt_self_ty = opt_self_info.map(|i| i.self_ty);
let (_, opt_self_ty, fn_sig) =
replace_bound_regions_in_fn_sig(
tcx, opt_self_ty, fn_sig,
|br| ty::ReFree(ty::FreeRegion {scope_id: body.id,
bound_region: br}));
let opt_self_info =
opt_self_info.map(
|si| SelfInfo {self_ty: opt_self_ty.unwrap(), .. si});
(opt_self_info, fn_sig)
};
// First, we have to replace any bound regions in the fn type with free ones.
// The free region references will be bound the node_id of the body block.
let (_, fn_sig) = replace_bound_regions_in_fn_sig(tcx, fn_sig, |br| {
ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
});
relate_free_regions(tcx, opt_self_info.map(|s| s.self_ty), &fn_sig);
relate_free_regions(tcx, &fn_sig);
let arg_tys = fn_sig.inputs.map(|a| *a);
let arg_tys = fn_sig.inputs.as_slice();
let ret_ty = fn_sig.output;
debug!("check_fn(arg_tys={:?}, ret_ty={:?}, opt_self_ty={:?})",
debug!("check_fn(arg_tys={:?}, ret_ty={:?})",
arg_tys.map(|&a| ppaux::ty_to_str(tcx, a)),
ppaux::ty_to_str(tcx, ret_ty),
opt_self_info.map(|si| ppaux::ty_to_str(tcx, si.self_ty)));
ppaux::ty_to_str(tcx, ret_ty));
// Create the function context. This is either derived from scratch or,
// in the case of function expressions, based on the outer context.
let fcx: @FnCtxt = {
@FnCtxt {
err_count_on_creation: err_count_on_creation,
ret_ty: ret_ty,
ps: RefCell::new(PurityState::function(purity, id)),
region_lb: Cell::new(body.id),
fn_kind: fn_kind,
inh: inherited,
ccx: ccx
}
let fcx = @FnCtxt {
err_count_on_creation: err_count_on_creation,
ret_ty: ret_ty,
ps: RefCell::new(PurityState::function(purity, id)),
region_lb: Cell::new(body.id),
fn_kind: fn_kind,
inh: inherited,
ccx: ccx
};
gather_locals(fcx, decl, body, arg_tys, opt_self_info);
check_block_with_expected(fcx, body, Some(ret_ty));
// We unify the tail expr's type with the
// function result type, if there is a tail expr.
match body.expr {
Some(tail_expr) => {
let tail_expr_ty = fcx.expr_ty(tail_expr);
// Special case: we print a special error if there appears
// to be do-block/for-loop confusion
demand::suptype_with_fn(fcx, tail_expr.span, false,
fcx.ret_ty, tail_expr_ty,
|sp, e, a, s| {
fcx.report_mismatched_return_types(sp, e, a, s) });
}
None => ()
}
for self_info in opt_self_info.iter() {
fcx.write_ty(self_info.self_id, self_info.self_ty);
}
for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
fcx.write_ty(input.id, *arg);
}
return fcx;
fn gather_locals(fcx: @FnCtxt,
decl: &ast::FnDecl,
body: &ast::Block,
arg_tys: &[ty::t],
opt_self_info: Option<SelfInfo>) {
let tcx = fcx.ccx.tcx;
{
let mut visit = GatherLocalsVisitor { fcx: fcx, tcx: tcx, };
// Add the self parameter
for self_info in opt_self_info.iter() {
visit.assign(self_info.self_id, Some(self_info.self_ty));
let locals = fcx.inh.locals.borrow();
debug!("self is assigned to {}",
fcx.infcx().ty_to_str(
locals.get().get_copy(&self_info.self_id)));
}
// Add formal parameters.
for (arg_ty, input) in arg_tys.iter().zip(decl.inputs.iter()) {
// Create type variables for each argument.
pat_util::pat_bindings(tcx.def_map,
input.pat,
|_bm, pat_id, _sp, _path| {
visit.assign(pat_id, None);
});
visit.assign(pat_id, None);
});
// Check the pattern.
let pcx = pat_ctxt {
@ -546,6 +482,29 @@ fn gather_locals(fcx: @FnCtxt,
visit.visit_block(body, ());
}
check_block_with_expected(fcx, body, Some(ret_ty));
// We unify the tail expr's type with the
// function result type, if there is a tail expr.
match body.expr {
Some(tail_expr) => {
// Special case: we print a special error if there appears
// to be do-block/for-loop confusion
demand::suptype_with_fn(fcx, tail_expr.span, false,
fcx.ret_ty, fcx.expr_ty(tail_expr),
|sp, e, a, s| {
fcx.report_mismatched_return_types(sp, e, a, s);
});
}
None => {}
}
for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
fcx.write_ty(input.id, *arg);
}
fcx
}
pub fn check_no_duplicate_fields(tcx: ty::ctxt,
@ -606,7 +565,7 @@ pub fn check_item(ccx: @CrateCtxt, it: &ast::Item) {
[],
body.id);
check_bare_fn(ccx, decl, body, it.id, None, fn_tpt.ty, param_env);
check_bare_fn(ccx, decl, body, it.id, fn_tpt.ty, param_env);
}
ast::ItemImpl(_, ref opt_trait_ref, _, ref ms) => {
debug!("ItemImpl {} with id {}", ccx.tcx.sess.str_of(it.ident), it.id);
@ -716,23 +675,11 @@ fn check_method_body(ccx: @CrateCtxt,
item_generics.region_param_defs,
method.body.id);
// Compute the self type and fty from point of view of inside fn
let opt_self_info = method_ty.transformed_self_ty.map(|ty| {
SelfInfo {self_ty: ty.subst(ccx.tcx, &param_env.free_substs),
self_id: method.self_id,
span: method.explicit_self.span}
});
// Compute the fty from point of view of inside fn
let fty = ty::node_id_to_type(ccx.tcx, method.id);
let fty = fty.subst(ccx.tcx, &param_env.free_substs);
check_bare_fn(
ccx,
method.decl,
method.body,
method.id,
opt_self_info,
fty,
param_env);
check_bare_fn(ccx, method.decl, method.body, method.id, fty, param_env);
}
fn check_impl_methods_against_trait(ccx: @CrateCtxt,
@ -815,13 +762,13 @@ fn check_impl_methods_against_trait(ccx: @CrateCtxt,
* - trait_m: the method in the trait
* - trait_substs: the substitutions used on the type of the trait
*/
pub fn compare_impl_method(tcx: ty::ctxt,
impl_generics: &ty::Generics,
impl_m: @ty::Method,
impl_m_span: Span,
impl_m_body_id: ast::NodeId,
trait_m: &ty::Method,
trait_substs: &ty::substs) {
fn compare_impl_method(tcx: ty::ctxt,
impl_generics: &ty::Generics,
impl_m: @ty::Method,
impl_m_span: Span,
impl_m_body_id: ast::NodeId,
trait_m: &ty::Method,
trait_substs: &ty::substs) {
debug!("compare_impl_method()");
let infcx = infer::new_infer_ctxt(tcx);
@ -953,52 +900,10 @@ pub fn compare_impl_method(tcx: ty::ctxt,
regions: ty::NonerasedRegions(dummy_impl_regions),
self_ty: None };
// We are going to create a synthetic fn type that includes
// both the method's self argument and its normal arguments.
// So a method like `fn(&self, a: uint)` would be converted
// into a function `fn(self: &T, a: uint)`.
let mut trait_fn_args = ~[];
let mut impl_fn_args = ~[];
// For both the trait and the impl, create an argument to
// represent the self argument (unless this is a static method).
// This argument will have the *transformed* self type.
for &t in trait_m.transformed_self_ty.iter() {
trait_fn_args.push(t);
}
for &t in impl_m.transformed_self_ty.iter() {
impl_fn_args.push(t);
}
// Add in the normal arguments.
trait_fn_args.push_all(trait_m.fty.sig.inputs);
impl_fn_args.push_all(impl_m.fty.sig.inputs);
// Create a bare fn type for trait/impl that includes self argument
let trait_fty =
ty::mk_bare_fn(tcx,
ty::BareFnTy {
purity: trait_m.fty.purity,
abis: trait_m.fty.abis,
sig: ty::FnSig {
binder_id: trait_m.fty.sig.binder_id,
inputs: trait_fn_args,
output: trait_m.fty.sig.output,
variadic: false
}
});
let impl_fty =
ty::mk_bare_fn(tcx,
ty::BareFnTy {
purity: impl_m.fty.purity,
abis: impl_m.fty.abis,
sig: ty::FnSig {
binder_id: impl_m.fty.sig.binder_id,
inputs: impl_fn_args,
output: impl_m.fty.sig.output,
variadic: false
}
});
// Create a bare fn type for trait/impl
// It'd be nice to refactor so as to provide the bare fn types instead.
let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
// Perform substitutions so that the trait/impl methods are expressed
// in terms of the same set of type/region parameters:
@ -1669,6 +1574,8 @@ fn check_method_argument_types(
sugar: ast::CallSugar,
deref_args: DerefArgs) -> ty::t
{
// HACK(eddyb) ignore provided self (it has special typeck rules).
let args = args.slice_from(1);
if ty::type_is_error(method_fn_ty) {
let err_inputs = err_args(args.len());
check_argument_types(fcx, sp, err_inputs, callee_expr,
@ -1677,8 +1584,10 @@ fn check_method_argument_types(
} else {
match ty::get(method_fn_ty).sty {
ty::ty_bare_fn(ref fty) => {
check_argument_types(fcx, sp, fty.sig.inputs, callee_expr,
args, sugar, deref_args, fty.sig.variadic);
// HACK(eddyb) ignore self in the definition (see above).
check_argument_types(fcx, sp, fty.sig.inputs.slice_from(1),
callee_expr, args, sugar, deref_args,
fty.sig.variadic);
fty.sig.output
}
_ => {
@ -1923,13 +1832,10 @@ fn check_call(fcx: @FnCtxt,
// Replace any bound regions that appear in the function
// signature with region variables
let (_, _, fn_sig) =
replace_bound_regions_in_fn_sig(fcx.tcx(),
None,
fn_sig,
|br| fcx.infcx()
.next_region_var(
infer::BoundRegionInFnCall(call_expr.span, br)));
let (_, fn_sig) = replace_bound_regions_in_fn_sig(fcx.tcx(), fn_sig, |br| {
fcx.infcx()
.next_region_var(infer::BoundRegionInFnCall(call_expr.span, br))
});
// Call the generic checker.
check_argument_types(fcx, call_expr.span, fn_sig.inputs, f,
@ -1942,11 +1848,11 @@ fn check_call(fcx: @FnCtxt,
fn check_method_call(fcx: @FnCtxt,
callee_id: ast::NodeId,
expr: &ast::Expr,
rcvr: &ast::Expr,
method_name: ast::Ident,
args: &[@ast::Expr],
tps: &[ast::P<ast::Ty>],
sugar: ast::CallSugar) {
let rcvr = args[0];
check_expr(fcx, rcvr);
// no need to check for bot/err -- callee does that
@ -2042,7 +1948,6 @@ fn check_then_else(fcx: @FnCtxt,
fn lookup_op_method(fcx: @FnCtxt,
callee_id: ast::NodeId,
op_ex: &ast::Expr,
self_ex: &ast::Expr,
self_t: ty::t,
opname: ast::Name,
args: &[@ast::Expr],
@ -2052,7 +1957,7 @@ fn lookup_op_method(fcx: @FnCtxt,
_expected_result: Option<ty::t>
)
-> ty::t {
match method::lookup(fcx, op_ex, self_ex,
match method::lookup(fcx, op_ex, args[0],
callee_id, opname, self_t, [],
deref_args, CheckTraitsOnly, autoderef_receiver) {
Some(ref origin) => {
@ -2084,7 +1989,7 @@ fn check_binop(fcx: @FnCtxt,
callee_id: ast::NodeId,
expr: &ast::Expr,
op: ast::BinOp,
lhs: &ast::Expr,
lhs: @ast::Expr,
rhs: @ast::Expr,
// Used only in the error case
expected_result: Option<ty::t>,
@ -2172,7 +2077,7 @@ fn check_binop(fcx: @FnCtxt,
fn check_user_binop(fcx: @FnCtxt,
callee_id: ast::NodeId,
ex: &ast::Expr,
lhs_expr: &ast::Expr,
lhs_expr: @ast::Expr,
lhs_resolved_t: ty::t,
op: ast::BinOp,
rhs: @ast::Expr,
@ -2187,10 +2092,10 @@ fn check_user_binop(fcx: @FnCtxt,
ast_util::binop_to_str(op), actual)},
lhs_resolved_t, None)
};
return lookup_op_method(fcx, callee_id, ex, lhs_expr, lhs_resolved_t,
token::intern(*name),
&[rhs], DoDerefArgs, DontAutoderefReceiver, if_op_unbound,
expected_result);
return lookup_op_method(fcx, callee_id, ex, lhs_resolved_t,
token::intern(*name), [lhs_expr, rhs],
DoDerefArgs,DontAutoderefReceiver,
if_op_unbound, expected_result);
}
None => ()
};
@ -2216,14 +2121,13 @@ fn check_user_unop(fcx: @FnCtxt,
op_str: &str,
mname: &str,
ex: &ast::Expr,
rhs_expr: &ast::Expr,
rhs_expr: @ast::Expr,
rhs_t: ty::t,
expected_t: Option<ty::t>)
-> ty::t {
lookup_op_method(
fcx, callee_id, ex, rhs_expr, rhs_t,
token::intern(mname), &[],
DoDerefArgs, DontAutoderefReceiver,
fcx, callee_id, ex, rhs_t, token::intern(mname),
[rhs_expr], DoDerefArgs, DontAutoderefReceiver,
|| {
fcx.type_error_message(ex.span, |actual| {
format!("cannot apply unary operator `{}` to type `{}`",
@ -2280,9 +2184,9 @@ fn check_expr_fn(fcx: @FnCtxt,
expected_bounds) = {
match expected_sty {
Some(ty::ty_closure(ref cenv)) => {
let (_, _, sig) =
let (_, sig) =
replace_bound_regions_in_fn_sig(
tcx, None, &cenv.sig,
tcx, &cenv.sig,
|_| fcx.inh.infcx.fresh_bound_region(expr.id));
(Some(sig), cenv.purity, cenv.sigil,
cenv.onceness, cenv.bounds)
@ -2352,7 +2256,7 @@ fn check_expr_fn(fcx: @FnCtxt,
(purity, expr.id),
sigil);
check_fn(fcx.ccx, None, inherited_purity, &fty_sig,
check_fn(fcx.ccx, inherited_purity, &fty_sig,
decl, id, body, fn_kind, fcx.inh);
}
@ -2916,12 +2820,6 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
let tpt = ty_param_bounds_and_ty_for_def(fcx, expr.span, defn);
instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
}
ast::ExprSelf => {
let definition = lookup_def(fcx, expr.span, id);
let ty_param_bounds_and_ty =
ty_param_bounds_and_ty_for_def(fcx, expr.span, definition);
fcx.write_ty(id, ty_param_bounds_and_ty.ty);
}
ast::ExprInlineAsm(ref ia) => {
for &(_, input) in ia.inputs.iter() {
check_expr(fcx, input);
@ -3088,18 +2986,16 @@ fn check_struct_enum_variant(fcx: @FnCtxt,
fcx.write_bot(id);
}
}
ast::ExprMethodCall(callee_id, rcvr, ident, ref tps, ref args, sugar) => {
check_method_call(fcx, callee_id, expr, rcvr, ident, *args, *tps, sugar);
let f_ty = fcx.expr_ty(rcvr);
ast::ExprMethodCall(callee_id, ident, ref tps, ref args, sugar) => {
check_method_call(fcx, callee_id, expr, ident, *args, *tps, sugar);
let arg_tys = args.map(|a| fcx.expr_ty(*a));
let (args_bot, args_err) = arg_tys.iter().fold((false, false),
|(rest_bot, rest_err), a| {
(rest_bot || ty::type_is_bot(*a),
rest_err || ty::type_is_error(*a))});
if ty::type_is_error(f_ty) || args_err {
if args_err {
fcx.write_error(id);
}
else if ty::type_is_bot(f_ty) || args_bot {
} else if args_bot {
fcx.write_bot(id);
}
}
@ -3327,10 +3223,9 @@ fn types_compatible(fcx: @FnCtxt, sp: Span,
let ret_ty = lookup_op_method(fcx,
callee_id,
expr,
base,
resolved,
index_ident.name,
&[idx],
[base, idx],
DoDerefArgs,
AutoderefReceiver,
error_message,
@ -3760,7 +3655,7 @@ pub fn ty_param_bounds_and_ty_for_def(fcx: @FnCtxt,
defn: ast::Def)
-> ty_param_bounds_and_ty {
match defn {
ast::DefArg(nid, _) | ast::DefLocal(nid, _) | ast::DefSelf(nid, _) |
ast::DefArg(nid, _) | ast::DefLocal(nid, _) |
ast::DefBinding(nid, _) => {
let typ = fcx.local_ty(sp, nid);
return no_params(typ);

View file

@ -41,7 +41,7 @@
use util::ppaux::{ty_to_str, region_to_str, Repr};
use syntax::ast::{ManagedSigil, OwnedSigil, BorrowedSigil};
use syntax::ast::{DefArg, DefBinding, DefLocal, DefSelf, DefUpvar};
use syntax::ast::{DefArg, DefBinding, DefLocal, DefUpvar};
use syntax::ast;
use syntax::codemap::Span;
use syntax::visit;
@ -64,7 +64,7 @@ fn region_of_def(fcx: @FnCtxt, def: ast::Def) -> ty::Region {
let tcx = fcx.tcx();
match def {
DefLocal(node_id, _) | DefArg(node_id, _) |
DefSelf(node_id, _) | DefBinding(node_id, _) => {
DefBinding(node_id, _) => {
tcx.region_maps.var_region(node_id)
}
DefUpvar(_, subdef, closure_id, body_id) => {
@ -316,8 +316,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
visit::walk_expr(rcx, expr, ());
}
ast::ExprMethodCall(callee_id, arg0, _, _, ref args, _) => {
constrain_call(rcx, callee_id, expr, Some(arg0), *args, false);
ast::ExprMethodCall(callee_id, _, _, ref args, _) => {
constrain_call(rcx, callee_id, expr, Some(args[0]),
args.slice_from(1), false);
visit::walk_expr(rcx, expr, ());
}
@ -1012,12 +1013,10 @@ fn guarantor(rcx: &mut Rcx, expr: &ast::Expr) -> Option<ty::Region> {
guarantor(rcx, e)
}
ast::ExprPath(..) | ast::ExprSelf => {
// Either a variable or constant and hence resides
// in constant memory or on the stack frame. Either way,
// not guaranteed by a region pointer.
None
}
// Either a variable or constant and hence resides
// in constant memory or on the stack frame. Either way,
// not guaranteed by a region pointer.
ast::ExprPath(..) => None,
// All of these expressions are rvalues and hence their
// value is not guaranteed by a region pointer.

View file

@ -21,29 +21,26 @@
pub fn replace_bound_regions_in_fn_sig(
tcx: ty::ctxt,
opt_self_ty: Option<ty::t>,
fn_sig: &ty::FnSig,
mapf: |ty::BoundRegion| -> ty::Region)
-> (HashMap<ty::BoundRegion,ty::Region>, Option<ty::t>, ty::FnSig) {
debug!("replace_bound_regions_in_fn_sig(self_ty={}, fn_sig={})",
opt_self_ty.repr(tcx),
fn_sig.repr(tcx));
-> (HashMap<ty::BoundRegion,ty::Region>, ty::FnSig) {
debug!("replace_bound_regions_in_fn_sig({})", fn_sig.repr(tcx));
let mut map = HashMap::new();
let (fn_sig, opt_self_ty) = {
let fn_sig = {
let mut f = ty_fold::RegionFolder::regions(tcx, |r| {
debug!("region r={}", r.to_str());
match r {
debug!("region r={}", r.to_str());
match r {
ty::ReLateBound(s, br) if s == fn_sig.binder_id => {
*map.find_or_insert_with(br, |_| mapf(br))
}
_ => r
}});
(ty_fold::super_fold_sig(&mut f, fn_sig),
ty_fold::fold_opt_ty(&mut f, opt_self_ty))
}
});
ty_fold::super_fold_sig(&mut f, fn_sig)
};
debug!("resulting map: {}", map.to_str());
(map, opt_self_ty, fn_sig)
(map, fn_sig)
}
pub fn relate_nested_regions(tcx: ty::ctxt,
@ -135,11 +132,7 @@ fn relate(&mut self, r_sub: ty::Region) {
}
}
pub fn relate_free_regions(
tcx: ty::ctxt,
self_ty: Option<ty::t>,
fn_sig: &ty::FnSig)
{
pub fn relate_free_regions(tcx: ty::ctxt, fn_sig: &ty::FnSig) {
/*!
* This function populates the region map's `free_region_map`.
* It walks over the transformed self type and argument types
@ -158,9 +151,6 @@ pub fn relate_free_regions(
for arg in fn_sig.inputs.iter() {
all_tys.push(*arg);
}
for &t in self_ty.iter() {
all_tys.push(t);
}
for &t in all_tys.iter() {
debug!("relate_free_regions(t={})", ppaux::ty_to_str(tcx, t));

View file

@ -712,7 +712,7 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
ast::ExprUnary(callee_id, _, _) |
ast::ExprAssignOp(callee_id, _, _, _) |
ast::ExprIndex(callee_id, _, _) |
ast::ExprMethodCall(callee_id, _, _, _, _, _) => {
ast::ExprMethodCall(callee_id, _, _, _, _) => {
match ty::method_call_type_param_defs(cx.tcx, fcx.inh.method_map, ex.id) {
Some(type_param_defs) => {
debug!("vtable resolution on parameter bounds for method call {}",

View file

@ -16,13 +16,12 @@
use middle::pat_util;
use middle::ty;
use middle::typeck::astconv::AstConv;
use middle::typeck::check::{FnCtxt, SelfInfo};
use middle::typeck::check::FnCtxt;
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
use middle::typeck::infer::resolve_type;
use middle::typeck::infer;
use middle::typeck::{vtable_res, vtable_origin};
use middle::typeck::{vtable_static, vtable_param};
use middle::typeck::method_map_entry;
use middle::typeck::write_substs_to_tcx;
use middle::typeck::write_ty_to_tcx;
use util::ppaux;
@ -62,7 +61,7 @@ fn resolve_type_vars_in_types(fcx: @FnCtxt, sp: Span, tys: &[ty::t])
})
}
fn resolve_method_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
fn resolve_method_map_entry(fcx: @FnCtxt, id: ast::NodeId) {
// Resolve any method map entry
let method_map_entry_opt = {
let method_map = fcx.inh.method_map.borrow();
@ -71,18 +70,9 @@ fn resolve_method_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
match method_map_entry_opt {
None => {}
Some(mme) => {
{
let r = resolve_type_vars_in_type(fcx, sp, mme.self_ty);
for t in r.iter() {
let method_map = fcx.ccx.method_map;
let new_entry = method_map_entry { self_ty: *t, ..mme };
debug!("writeback::resolve_method_map_entry(id={:?}, \
new_entry={:?})",
id, new_entry);
let mut method_map = method_map.borrow_mut();
method_map.get().insert(id, new_entry);
}
}
debug!("writeback::resolve_method_map_entry(id={:?}, entry={:?})", id, mme);
let mut method_map = fcx.ccx.method_map.borrow_mut();
method_map.get().insert(id, mme);
}
}
}
@ -148,19 +138,33 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
resolve_all | force_all) {
Err(e) => {
// This should not, I think, happen:
fcx.ccx.tcx.sess.span_err(
tcx.sess.span_err(
sp,
format!("cannot resolve bound for closure: \
{}",
infer::fixup_err_to_str(e)));
}
Ok(r1) => {
// FIXME(eddyb) #2190 Allow only statically resolved
// bare functions to coerce to a closure to avoid
// constructing (slower) indirect call wrappers.
{
let def_map = tcx.def_map.borrow();
match def_map.get().find(&id) {
Some(&ast::DefFn(..)) |
Some(&ast::DefStaticMethod(..)) |
Some(&ast::DefVariant(..)) |
Some(&ast::DefStruct(_)) => {}
_ => tcx.sess.span_err(sp,
"cannot coerce non-statically resolved bare fn")
}
}
let resolved_adj = @ty::AutoAddEnv(r1, s);
debug!("Adjustments for node {}: {:?}",
id,
resolved_adj);
let mut adjustments = fcx.tcx()
.adjustments
let mut adjustments = tcx.adjustments
.borrow_mut();
adjustments.get().insert(id, resolved_adj);
}
@ -175,7 +179,7 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
Ok(r1) => r1,
Err(e) => {
// This should not, I think, happen.
fcx.ccx.tcx.sess.span_err(
tcx.sess.span_err(
sp,
format!("cannot resolve scope of borrow: \
{}",
@ -195,13 +199,13 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
autoref: resolved_autoref,
});
debug!("Adjustments for node {}: {:?}", id, resolved_adj);
let mut adjustments = fcx.tcx().adjustments.borrow_mut();
let mut adjustments = tcx.adjustments.borrow_mut();
adjustments.get().insert(id, resolved_adj);
}
ty::AutoObject(..) => {
debug!("Adjustments for node {}: {:?}", id, adjustment);
let mut adjustments = fcx.tcx().adjustments.borrow_mut();
let mut adjustments = tcx.adjustments.borrow_mut();
adjustments.get().insert(id, adjustment);
}
}
@ -273,11 +277,11 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
resolve_type_vars_for_node(wbcx, e.span, e.id);
resolve_method_map_entry(wbcx.fcx, e.span, e.id);
resolve_method_map_entry(wbcx.fcx, e.id);
{
let r = e.get_callee_id();
for callee_id in r.iter() {
resolve_method_map_entry(wbcx.fcx, e.span, *callee_id);
resolve_method_map_entry(wbcx.fcx, *callee_id);
}
}
@ -303,7 +307,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id);
}
ast::ExprMethodCall(callee_id, _, _, _, _, _) => {
ast::ExprMethodCall(callee_id, _, _, _, _) => {
// We must always have written in a callee ID type for these.
resolve_type_vars_for_node(wbcx, e.span, callee_id);
}
@ -381,18 +385,11 @@ pub fn resolve_type_vars_in_expr(fcx: @FnCtxt, e: &ast::Expr) -> bool {
return wbcx.success;
}
pub fn resolve_type_vars_in_fn(fcx: @FnCtxt,
decl: &ast::FnDecl,
blk: &ast::Block,
self_info: Option<SelfInfo>) -> bool {
pub fn resolve_type_vars_in_fn(fcx: @FnCtxt, decl: &ast::FnDecl,
blk: &ast::Block) -> bool {
let mut wbcx = WbCtxt { fcx: fcx, success: true };
let wbcx = &mut wbcx;
wbcx.visit_block(blk, ());
for self_info in self_info.iter() {
resolve_type_vars_for_node(wbcx,
self_info.span,
self_info.self_id);
}
for arg in decl.inputs.iter() {
wbcx.visit_pat(arg.pat, ());
// Privacy needs the type for the whole pattern, not just each binding

View file

@ -24,8 +24,7 @@
use middle::ty::{ty_param, ty_param_bounds_and_ty, ty_ptr};
use middle::ty::{ty_rptr, ty_self, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_type, ty_uint, ty_uniq, ty_bare_fn, ty_closure};
use middle::ty::{ty_opaque_closure_ptr, ty_unboxed_vec};
use middle::ty::{type_is_ty_var};
use middle::ty::{ty_unboxed_vec, type_is_ty_var};
use middle::subst::Subst;
use middle::ty;
use middle::ty::{Impl, Method};
@ -84,7 +83,7 @@ pub fn get_base_type(inference_context: @InferCtxt,
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
ty_infer(..) | ty_param(..) | ty_self(..) | ty_type |
ty_opaque_closure_ptr(..) | ty_unboxed_vec(..) | ty_err | ty_box(_) |
ty_unboxed_vec(..) | ty_err | ty_box(_) |
ty_uniq(_) | ty_ptr(_) | ty_rptr(_, _) => {
debug!("(getting base type) no base type; found {:?}",
get(original_type).sty);
@ -820,9 +819,6 @@ fn subst_receiver_types_in_method_ty(tcx: ty::ctxt,
// method types *can* appear in the generic bounds
method.generics.subst(tcx, &combined_substs),
// method tps cannot appear in the self_ty, so use `substs` from trait ref
method.transformed_self_ty.subst(tcx, &trait_ref.substs),
// method types *can* appear in the fty
method.fty.subst(tcx, &combined_substs),

View file

@ -380,15 +380,13 @@ fn ty_method_of_trait_method(this: &CrateCtxt,
m_decl: &ast::FnDecl) -> ty::Method
{
let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
let (transformed_self_ty, fty) =
astconv::ty_of_method(this, *m_id, *m_purity,
trait_self_ty, *m_explicit_self, m_decl);
let fty = astconv::ty_of_method(this, *m_id, *m_purity, trait_self_ty,
*m_explicit_self, m_decl);
let num_trait_type_params = trait_generics.type_param_defs.len();
ty::Method::new(
*m_ident,
// FIXME(#5121) -- distinguish early vs late lifetime params
ty_generics(this, m_generics, num_trait_type_params),
transformed_self_ty,
fty,
m_explicit_self.node,
// assume public, because this is only invoked on trait methods
@ -512,10 +510,9 @@ fn ty_of_method(ccx: &CrateCtxt,
rcvr_generics: &ast::Generics,
rcvr_visibility: ast::Visibility) -> ty::Method
{
let (transformed_self_ty, fty) =
astconv::ty_of_method(ccx, m.id, m.purity,
untransformed_rcvr_ty,
m.explicit_self, m.decl);
let fty = astconv::ty_of_method(ccx, m.id, m.purity,
untransformed_rcvr_ty,
m.explicit_self, m.decl);
// if the method specifies a visibility, use that, otherwise
// inherit the visibility from the impl (so `foo` in `pub impl
@ -528,7 +525,6 @@ fn ty_of_method(ccx: &CrateCtxt,
m.ident,
// FIXME(#5121) -- distinguish early vs late lifetime params
ty_generics(ccx, &m.generics, num_rcvr_type_params),
transformed_self_ty,
fty,
m.explicit_self.node,
method_vis,

View file

@ -385,48 +385,37 @@ pub fn coerce_borrowed_fn(&self,
})))
}
pub fn coerce_from_bare_fn(&self,
a: ty::t,
fn_ty_a: &ty::BareFnTy,
b: ty::t)
-> CoerceResult {
self.unpack_actual_value(b, |sty_b| {
self.coerce_from_bare_fn_post_unpack(a, fn_ty_a, b, sty_b)
})
}
pub fn coerce_from_bare_fn_post_unpack(&self,
a: ty::t,
fn_ty_a: &ty::BareFnTy,
b: ty::t,
sty_b: &ty::sty)
-> CoerceResult {
fn coerce_from_bare_fn(&self, a: ty::t, fn_ty_a: &ty::BareFnTy, b: ty::t)
-> CoerceResult {
/*!
*
* Attempts to coerce from a bare Rust function (`extern
* "rust" fn`) into a closure.
* "Rust" fn`) into a closure or a `proc`.
*/
debug!("coerce_from_bare_fn(a={}, b={})",
a.inf_str(self.get_ref().infcx), b.inf_str(self.get_ref().infcx));
self.unpack_actual_value(b, |sty_b| {
if !fn_ty_a.abis.is_rust() || fn_ty_a.purity != ast::ImpureFn {
return self.subtype(a, b);
}
debug!("coerce_from_bare_fn(a={}, b={})",
a.inf_str(self.get_ref().infcx), b.inf_str(self.get_ref().infcx));
let fn_ty_b = match *sty_b {
ty::ty_closure(ref f) => (*f).clone(),
_ => return self.subtype(a, b),
};
if !fn_ty_a.abis.is_rust() || fn_ty_a.purity != ast::ImpureFn {
return self.subtype(a, b);
}
let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil);
let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
ty::ClosureTy {
sig: fn_ty_a.sig.clone(),
..fn_ty_b
});
if_ok!(self.subtype(a_closure, b));
Ok(Some(adj))
let fn_ty_b = match *sty_b {
ty::ty_closure(ref f) => (*f).clone(),
_ => return self.subtype(a, b)
};
let adj = @ty::AutoAddEnv(fn_ty_b.region, fn_ty_b.sigil);
let a_closure = ty::mk_closure(self.get_ref().infcx.tcx,
ty::ClosureTy {
sig: fn_ty_a.sig.clone(),
..fn_ty_b
});
if_ok!(self.subtype(a_closure, b));
Ok(Some(adj))
})
}
pub fn coerce_unsafe_ptr(&self,

View file

@ -25,7 +25,7 @@
use middle::ty;
use middle::ty_fold;
use middle::ty_fold::TypeFolder;
use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig};
use middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig;
use middle::typeck::infer::coercion::Coerce;
use middle::typeck::infer::combine::{Combine, CombineFields, eq_tys};
use middle::typeck::infer::region_inference::{RegionVarBindings};
@ -809,8 +809,8 @@ pub fn replace_bound_regions_with_fresh_regions(&self,
-> (ty::FnSig,
HashMap<ty::BoundRegion,
ty::Region>) {
let (map, _, fn_sig) =
replace_bound_regions_in_fn_sig(self.tcx, None, fsig, |br| {
let (map, fn_sig) =
replace_bound_regions_in_fn_sig(self.tcx, fsig, |br| {
let rvar = self.next_region_var(
BoundRegionInFnType(trace.origin.span(), br));
debug!("Bound region {} maps to {:?}",

View file

@ -171,8 +171,8 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
// Second, we instantiate each bound region in the supertype with a
// fresh concrete region.
let (skol_map, _, b_sig) = {
replace_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, None, b, |br| {
let (skol_map, b_sig) = {
replace_bound_regions_in_fn_sig(self.get_ref().infcx.tcx, b, |br| {
let skol = self.get_ref().infcx.region_vars.new_skolemized(br);
debug!("Bound region {} skolemized to {:?}",
bound_region_to_str(self.get_ref().infcx.tcx, "", false, br),

View file

@ -144,13 +144,6 @@ pub struct method_object {
#[deriving(Clone)]
pub struct method_map_entry {
// the type of the self parameter, which is not reflected in the fn type
// (FIXME #3446)
self_ty: ty::t,
// the type of explicit self on the method
explicit_self: ast::ExplicitSelf_,
// method details being invoked
origin: method_origin,
}
@ -264,10 +257,10 @@ pub fn write_tpt_to_tcx(tcx: ty::ctxt,
pub fn lookup_def_tcx(tcx: ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
let def_map = tcx.def_map.borrow();
match def_map.get().find(&id) {
Some(&x) => x,
_ => {
tcx.sess.span_fatal(sp, "internal error looking up a definition")
}
Some(&x) => x,
_ => {
tcx.sess.span_fatal(sp, "internal error looking up a definition")
}
}
}

View file

@ -472,22 +472,6 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
ast::ItemTrait(..) => {
let methods = ty::trait_methods(tcx, did);
for method in methods.iter() {
match method.transformed_self_ty {
Some(self_ty) => {
// The implicit self parameter is basically
// equivalent to a normal parameter declared
// like:
//
// self : self_ty
//
// where self_ty is `&Self` or `&mut Self`
// or whatever.
self.add_constraints_from_ty(
self_ty, self.contravariant);
}
None => {}
}
self.add_constraints_from_sig(
&method.fty.sig, self.covariant);
}
@ -691,8 +675,8 @@ fn add_constraints_from_ty(&mut self,
self.add_constraints_from_sig(sig, variance);
}
ty::ty_infer(..) | ty::ty_err | ty::ty_type |
ty::ty_opaque_closure_ptr(..) | ty::ty_unboxed_vec(..) => {
ty::ty_infer(..) | ty::ty_err |
ty::ty_type | ty::ty_unboxed_vec(..) => {
self.tcx().sess.bug(
format!("Unexpected type encountered in \
variance inference: {}",

View file

@ -18,10 +18,8 @@
ReEmpty};
use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_opaque_closure_ptr, ty_param};
use middle::ty::{ty_ptr, ty_rptr, ty_self, ty_tup, ty_type, ty_uniq};
use middle::ty::{ty_trait, ty_int};
use middle::ty::{ty_uint, ty_unboxed_vec, ty_infer};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_self, ty_tup, ty_type};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_unboxed_vec, ty_infer};
use middle::ty;
use middle::typeck;
use syntax::abi::AbiSet;
@ -501,10 +499,7 @@ fn push_sig_to_str(cx: ctxt,
ty_vec(ref mt, vs) => {
vstore_ty_to_str(cx, mt, vs)
}
ty_str(vs) => format!("{}{}", vstore_to_str(cx, vs), "str"),
ty_opaque_closure_ptr(ast::BorrowedSigil) => ~"&closure",
ty_opaque_closure_ptr(ast::ManagedSigil) => ~"@closure",
ty_opaque_closure_ptr(ast::OwnedSigil) => ~"~closure",
ty_str(vs) => format!("{}{}", vstore_to_str(cx, vs), "str")
}
}
@ -800,11 +795,10 @@ fn repr(&self, _: ctxt) -> ~str {
impl Repr for ty::Method {
fn repr(&self, tcx: ctxt) -> ~str {
format!("method(ident: {}, generics: {}, transformed_self_ty: {}, \
fty: {}, explicit_self: {}, vis: {}, def_id: {})",
format!("method(ident: {}, generics: {}, fty: {}, \
explicit_self: {}, vis: {}, def_id: {})",
self.ident.repr(tcx),
self.generics.repr(tcx),
self.transformed_self_ty.repr(tcx),
self.fty.repr(tcx),
self.explicit_self.repr(tcx),
self.vis.repr(tcx),
@ -847,12 +841,7 @@ fn repr(&self, tcx: ctxt) -> ~str {
impl Repr for typeck::method_map_entry {
fn repr(&self, tcx: ctxt) -> ~str {
format!("method_map_entry \\{self_arg: {}, \
explicit_self: {}, \
origin: {}\\}",
self.self_ty.repr(tcx),
self.explicit_self.repr(tcx),
self.origin.repr(tcx))
format!("method_map_entry \\{origin: {}\\}", self.origin.repr(tcx))
}
}

View file

@ -330,6 +330,16 @@ pub struct Method {
impl Clean<Item> for ast::Method {
fn clean(&self) -> Item {
let inputs = match self.explicit_self.node {
ast::SelfStatic => self.decl.inputs.as_slice(),
_ => self.decl.inputs.slice_from(1)
};
let decl = FnDecl {
inputs: inputs.iter().map(|x| x.clean()).collect(),
output: (self.decl.output.clean()),
cf: self.decl.cf.clean(),
attrs: ~[]
};
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
@ -340,7 +350,7 @@ fn clean(&self) -> Item {
generics: self.generics.clean(),
self_: self.explicit_self.clean(),
purity: self.purity.clone(),
decl: self.decl.clean(),
decl: decl,
}),
}
}
@ -356,6 +366,16 @@ pub struct TyMethod {
impl Clean<Item> for ast::TypeMethod {
fn clean(&self) -> Item {
let inputs = match self.explicit_self.node {
ast::SelfStatic => self.decl.inputs.as_slice(),
_ => self.decl.inputs.slice_from(1)
};
let decl = FnDecl {
inputs: inputs.iter().map(|x| x.clean()).collect(),
output: (self.decl.output.clean()),
cf: self.decl.cf.clean(),
attrs: ~[]
};
Item {
name: Some(self.ident.clean()),
attrs: self.attrs.clean(),
@ -364,7 +384,7 @@ fn clean(&self) -> Item {
visibility: None,
inner: TyMethodItem(TyMethod {
purity: self.purity.clone(),
decl: self.decl.clean(),
decl: decl,
self_: self.explicit_self.clean(),
generics: self.generics.clean(),
}),
@ -385,8 +405,8 @@ impl Clean<SelfTy> for ast::ExplicitSelf {
fn clean(&self) -> SelfTy {
match self.node {
ast::SelfStatic => SelfStatic,
ast::SelfValue(_) => SelfValue,
ast::SelfUniq(_) => SelfOwned,
ast::SelfValue => SelfValue,
ast::SelfUniq => SelfOwned,
ast::SelfRegion(lt, mt) => SelfBorrowed(lt.clean(), mt.clean()),
ast::SelfBox => SelfManaged,
}
@ -1178,7 +1198,7 @@ fn resolve_type(path: Path, tpbs: Option<~[TyParamBound]>,
let (def_id, kind) = match *d {
ast::DefFn(i, _) => (i, TypeFunction),
ast::DefSelf(i, _) | ast::DefSelfTy(i) => return Self(i),
ast::DefSelfTy(i) => return Self(i),
ast::DefTy(i) => (i, TypeEnum),
ast::DefTrait(i) => {
debug!("saw DefTrait in def_to_id");

View file

@ -682,7 +682,7 @@ fn recurse<T>(&mut self, s: ~str, f: |&mut Context| -> T) -> T {
///
/// This currently isn't parallelized, but it'd be pretty easy to add
/// parallelization to this function.
fn crate(mut self, mut crate: clean::Crate, cache: Cache) {
fn crate(self, mut crate: clean::Crate, cache: Cache) {
let mut item = match crate.module.take() {
Some(i) => i,
None => return

View file

@ -338,7 +338,7 @@ fn socket_name(&mut self) -> Result<ip::SocketAddr, IoError> {
}
impl rtio::RtioTcpListener for TcpListener {
fn listen(mut ~self) -> Result<~rtio::RtioTcpAcceptor, IoError> {
fn listen(~self) -> Result<~rtio::RtioTcpAcceptor, IoError> {
// create the acceptor object from ourselves
let mut acceptor = ~TcpAcceptor { listener: self };

View file

@ -174,7 +174,7 @@ pub fn bind(io: &mut UvIoFactory, name: &CString)
}
impl RtioUnixListener for PipeListener {
fn listen(mut ~self) -> Result<~RtioUnixAcceptor, IoError> {
fn listen(~self) -> Result<~RtioUnixAcceptor, IoError> {
// create the acceptor object from ourselves
let mut acceptor = ~PipeAcceptor { listener: self };

View file

@ -230,7 +230,7 @@ pub fn get_ref<'a>(&'a self) -> &'a W { self.inner.get_ref() }
/// Unwraps this buffer, returning the underlying writer.
///
/// The internal buffer is flushed before returning the writer.
pub fn unwrap(mut self) -> W { self.inner.unwrap() }
pub fn unwrap(self) -> W { self.inner.unwrap() }
}
impl<W: Writer> Writer for LineBufferedWriter<W> {

View file

@ -451,13 +451,8 @@ fn visit_type(&mut self) -> bool {
true
}
fn visit_opaque_box(&mut self) -> bool {
self.align_to::<@u8>();
if ! self.inner.visit_opaque_box() { return false; }
self.bump_past::<@u8>();
true
}
// NOTE remove after next snapshot
#[cfg(stage0)]
fn visit_closure_ptr(&mut self, ck: uint) -> bool {
self.align_to::<proc()>();
if ! self.inner.visit_closure_ptr(ck) {

View file

@ -580,14 +580,8 @@ fn visit_param(&mut self, _i: uint) -> bool { true }
fn visit_self(&mut self) -> bool { true }
fn visit_type(&mut self) -> bool { true }
fn visit_opaque_box(&mut self) -> bool {
self.writer.write(['@' as u8]);
self.get::<&raw::Box<()>>(|this, b| {
let p = ptr::to_unsafe_ptr(&b.data) as *u8;
this.visit_ptr_inner(p, b.type_desc);
})
}
// NOTE remove after next snapshot
#[cfg(stage0)]
fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
}

View file

@ -164,7 +164,9 @@ fn visit_leave_fn(&mut self, purity: uint, proto: uint,
fn visit_param(&mut self, i: uint) -> bool;
fn visit_self(&mut self) -> bool;
fn visit_type(&mut self) -> bool;
fn visit_opaque_box(&mut self) -> bool;
// NOTE remove after next snapshot
#[cfg(stage0)]
fn visit_closure_ptr(&mut self, ck: uint) -> bool;
}

View file

@ -10,10 +10,11 @@
// The Rust abstract syntax tree.
use codemap::{Span, Spanned};
use codemap::{Span, Spanned, DUMMY_SP};
use abi::AbiSet;
use ast_util;
use opt_vec::OptVec;
use parse::token::{interner_get, str_to_ident};
use parse::token::{interner_get, str_to_ident, special_idents};
use std::cell::RefCell;
use std::hashmap::HashMap;
@ -236,7 +237,6 @@ pub enum MethodProvenance {
pub enum Def {
DefFn(DefId, Purity),
DefStaticMethod(/* method */ DefId, MethodProvenance, Purity),
DefSelf(NodeId, bool /* is_mutbl */),
DefSelfTy(/* trait id */ NodeId),
DefMod(DefId),
DefForeignMod(DefId),
@ -357,7 +357,7 @@ pub enum BindingMode {
pub enum Pat_ {
PatWild,
PatWildMulti,
// A pat_ident may either be a new bound variable,
// A PatIdent may either be a new bound variable,
// or a nullary enum (in which case the second field
// is None).
// In the nullary enum case, the parser can't determine
@ -366,7 +366,7 @@ pub enum Pat_ {
// set (of "pat_idents that refer to nullary enums")
PatIdent(BindingMode, Path, Option<@Pat>),
PatEnum(Path, Option<~[@Pat]>), /* "none" means a * pattern where
* we don't bind the fields to names */
* we don't bind the fields to names */
PatStruct(Path, ~[FieldPat], bool),
PatTup(~[@Pat]),
PatUniq(@Pat),
@ -374,7 +374,7 @@ pub enum Pat_ {
PatLit(@Expr),
PatRange(@Expr, @Expr),
// [a, b, ..i, y, z] is represented as
// pat_vec(~[a, b], Some(i), ~[y, z])
// PatVec(~[a, b], Some(i), ~[y, z])
PatVec(~[@Pat], Option<@Pat>, ~[@Pat])
}
@ -526,7 +526,7 @@ pub struct Expr {
impl Expr {
pub fn get_callee_id(&self) -> Option<NodeId> {
match self.node {
ExprMethodCall(callee_id, _, _, _, _, _) |
ExprMethodCall(callee_id, _, _, _, _) |
ExprIndex(callee_id, _, _) |
ExprBinary(callee_id, _, _, _) |
ExprAssignOp(callee_id, _, _, _) |
@ -550,7 +550,7 @@ pub enum Expr_ {
ExprBox(@Expr, @Expr),
ExprVec(~[@Expr], Mutability),
ExprCall(@Expr, ~[@Expr], CallSugar),
ExprMethodCall(NodeId, @Expr, Ident, ~[P<Ty>], ~[@Expr], CallSugar),
ExprMethodCall(NodeId, Ident, ~[P<Ty>], ~[@Expr], CallSugar),
ExprTup(~[@Expr]),
ExprBinary(NodeId, BinOp, @Expr, @Expr),
ExprUnary(NodeId, UnOp, @Expr),
@ -579,8 +579,6 @@ pub enum Expr_ {
/// of a function call.
ExprPath(Path),
/// The special identifier `self`.
ExprSelf,
ExprAddrOf(Mutability, @Expr),
ExprBreak(Option<Name>),
ExprAgain(Option<Name>),
@ -783,7 +781,7 @@ pub enum IntTy {
impl ToStr for IntTy {
fn to_str(&self) -> ~str {
::ast_util::int_ty_to_str(*self)
ast_util::int_ty_to_str(*self)
}
}
@ -798,7 +796,7 @@ pub enum UintTy {
impl ToStr for UintTy {
fn to_str(&self) -> ~str {
::ast_util::uint_ty_to_str(*self)
ast_util::uint_ty_to_str(*self)
}
}
@ -810,7 +808,7 @@ pub enum FloatTy {
impl ToStr for FloatTy {
fn to_str(&self) -> ~str {
::ast_util::float_ty_to_str(*self)
ast_util::float_ty_to_str(*self)
}
}
@ -886,7 +884,7 @@ pub enum Ty_ {
TyTup(~[P<Ty>]),
TyPath(Path, Option<OptVec<TyParamBound>>, NodeId), // for #7264; see above
TyTypeof(@Expr),
// ty_infer means the type should be inferred instead of it having been
// TyInfer 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
// nested in one.
TyInfer,
@ -917,6 +915,26 @@ pub struct Arg {
id: NodeId,
}
impl Arg {
pub fn new_self(span: Span, mutability: Mutability) -> Arg {
let path = ast_util::ident_to_path(span, special_idents::self_);
Arg {
// HACK(eddyb) fake type for the self argument.
ty: P(Ty {
id: DUMMY_NODE_ID,
node: TyInfer,
span: DUMMY_SP,
}),
pat: @Pat {
id: DUMMY_NODE_ID,
node: PatIdent(BindByValue(mutability), path, None),
span: span
},
id: DUMMY_NODE_ID
}
}
}
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub struct FnDecl {
inputs: ~[Arg],
@ -952,10 +970,10 @@ pub enum RetStyle {
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
pub enum ExplicitSelf_ {
SelfStatic, // no self
SelfValue(Mutability), // `self`, `mut self`
SelfValue, // `self`
SelfRegion(Option<Lifetime>, Mutability), // `&'lt self`, `&'lt mut self`
SelfBox, // `@self`
SelfUniq(Mutability) // `~self`, `mut ~self`
SelfUniq // `~self`
}
pub type ExplicitSelf = Spanned<ExplicitSelf_>;
@ -971,7 +989,6 @@ pub struct Method {
body: P<Block>,
id: NodeId,
span: Span,
self_id: NodeId,
vis: Visibility,
}

View file

@ -17,7 +17,6 @@
use fold::Folder;
use fold;
use parse::token::{get_ident_interner, IdentInterner};
use parse::token::special_idents;
use print::pprust;
use util::small_vector::SmallVector;
@ -163,10 +162,7 @@ pub enum Node {
NodeExpr(@Expr),
NodeStmt(@Stmt),
NodeArg(@Pat),
// HACK(eddyb) should always be a pattern, but `self` is not, and thus it
// is identified only by an ident and no span is available. In all other
// cases, node_span will return the proper span (required by borrowck).
NodeLocal(Ident, Option<@Pat>),
NodeLocal(@Pat),
NodeBlock(P<Block>),
/// NodeStructCtor represents a tuple struct.
@ -246,10 +242,6 @@ fn insert(&self, id: ast::NodeId, node: Node) {
let mut map = self.map.map.borrow_mut();
map.get().insert(id as uint, node);
}
fn map_self(&self, m: @Method) {
self.insert(m.self_id, NodeLocal(special_idents::self_, None));
}
}
impl<F: FoldOps> Folder for Ctx<F> {
@ -285,7 +277,6 @@ fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
let impl_did = ast_util::local_def(i.id);
for &m in ms.iter() {
self.insert(m.id, NodeMethod(m, impl_did, p));
self.map_self(m);
}
}
@ -332,7 +323,6 @@ fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
}
Provided(m) => {
self.insert(m.id, NodeTraitMethod(@Provided(m), d_id, p));
self.map_self(m);
}
}
}
@ -348,9 +338,9 @@ fn fold_item(&mut self, i: @Item) -> SmallVector<@Item> {
fn fold_pat(&mut self, pat: @Pat) -> @Pat {
let pat = fold::noop_fold_pat(pat, self);
match pat.node {
PatIdent(_, ref path, _) => {
PatIdent(..) => {
// Note: this is at least *potentially* a pattern...
self.insert(pat.id, NodeLocal(ast_util::path_to_ident(path), Some(pat)));
self.insert(pat.id, NodeLocal(pat));
}
_ => {}
}
@ -467,7 +457,6 @@ pub fn map_decoded_item<F: 'static + FoldOps>(diag: @SpanHandler,
NodeMethod(m, impl_did, @path)
};
cx.insert(m.id, entry);
cx.map_self(m);
}
}
@ -525,8 +514,8 @@ pub fn node_id_to_str(map: Map, id: NodeId, itr: @IdentInterner) -> ~str {
Some(NodeArg(pat)) => {
format!("arg {} (id={})", pprust::pat_to_str(pat, itr), id)
}
Some(NodeLocal(ident, _)) => {
format!("local (id={}, name={})", id, itr.get(ident.name))
Some(NodeLocal(pat)) => {
format!("local {} (id={})", pprust::pat_to_str(pat, itr), id)
}
Some(NodeBlock(block)) => {
format!("block {} (id={})", pprust::block_to_str(block, itr), id)
@ -559,11 +548,7 @@ pub fn node_span(items: Map, id: ast::NodeId) -> Span {
Some(NodeVariant(variant, _, _)) => variant.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeArg(pat)) => pat.span,
Some(NodeLocal(_, pat)) => match pat {
Some(pat) => pat.span,
None => fail!("node_span: cannot get span from NodeLocal (likely `self`)")
},
Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Some(NodeStructCtor(_, item, _)) => item.span,
Some(NodeCalleeScope(expr)) => expr.span,

View file

@ -60,19 +60,19 @@ pub fn variant_def_ids(d: Def) -> Option<(DefId, DefId)> {
pub fn def_id_of_def(d: Def) -> DefId {
match d {
DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
id
}
DefArg(id, _) | DefLocal(id, _) | DefSelf(id, _) | DefSelfTy(id)
| DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
| DefTyParamBinder(id) | DefLabel(id) => {
local_def(id)
}
DefFn(id, _) | DefStaticMethod(id, _, _) | DefMod(id) |
DefForeignMod(id) | DefStatic(id, _) |
DefVariant(_, id, _) | DefTy(id) | DefTyParam(id, _) |
DefUse(id) | DefStruct(id) | DefTrait(id) | DefMethod(id, _) => {
id
}
DefArg(id, _) | DefLocal(id, _) | DefSelfTy(id)
| DefUpvar(id, _, _, _) | DefBinding(id, _) | DefRegion(id)
| DefTyParamBinder(id) | DefLabel(id) => {
local_def(id)
}
DefPrimTy(_) => fail!()
DefPrimTy(_) => fail!()
}
}
@ -292,16 +292,6 @@ pub fn struct_field_visibility(field: ast::StructField) -> Visibility {
}
}
/* True if d is either a def_self, or a chain of def_upvars
referring to a def_self */
pub fn is_self(d: ast::Def) -> bool {
match d {
DefSelf(..) => true,
DefUpvar(_, d, _, _) => is_self(*d),
_ => false
}
}
/// Maps a binary operator to its precedence
pub fn operator_prec(op: ast::BinOp) -> uint {
match op {
@ -504,11 +494,8 @@ fn visit_fn(&mut self,
self.operation.visit_id(node_id);
match *function_kind {
visit::FkItemFn(_, generics, _, _) => {
self.visit_generics_helper(generics)
}
visit::FkMethod(_, generics, method) => {
self.operation.visit_id(method.self_id);
visit::FkItemFn(_, generics, _, _) |
visit::FkMethod(_, generics, _) => {
self.visit_generics_helper(generics)
}
visit::FkFnBlock => {}

View file

@ -18,6 +18,7 @@
use fold::Folder;
use opt_vec;
use opt_vec::OptVec;
use parse::token::special_idents;
pub struct Field {
ident: ast::Ident,
@ -478,7 +479,7 @@ fn expr_ident(&self, span: Span, id: ast::Ident) -> @ast::Expr {
self.expr_path(self.path_ident(span, id))
}
fn expr_self(&self, span: Span) -> @ast::Expr {
self.expr(span, ast::ExprSelf)
self.expr_ident(span, special_idents::self_)
}
fn expr_binary(&self, sp: Span, op: ast::BinOp,
@ -523,9 +524,9 @@ fn expr_call_global(&self, sp: Span, fn_path: ~[ast::Ident],
fn expr_method_call(&self, span: Span,
expr: @ast::Expr,
ident: ast::Ident,
args: ~[@ast::Expr]) -> @ast::Expr {
self.expr(span,
ast::ExprMethodCall(ast::DUMMY_NODE_ID, expr, ident, ~[], args, ast::NoSugar))
mut args: ~[@ast::Expr]) -> @ast::Expr {
args.unshift(expr);
self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args, ast::NoSugar))
}
fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
self.expr(b.span, ast::ExprBlock(b))

View file

@ -551,9 +551,14 @@ fn create_method(&self, trait_: &TraitDef,
// create the generics that aren't for Self
let fn_generics = self.generics.to_generics(trait_.cx, trait_.span, type_ident, generics);
let self_arg = match explicit_self.node {
ast::SelfStatic => None,
_ => Some(ast::Arg::new_self(trait_.span, ast::MutImmutable))
};
let args = arg_types.move_iter().map(|(name, ty)| {
trait_.cx.arg(trait_.span, name, ty)
}).collect();
});
let args = self_arg.move_iter().chain(args).collect();
let ret_type = self.get_ret_ty(trait_, generics, type_ident);
@ -578,7 +583,6 @@ fn create_method(&self, trait_: &TraitDef,
body: body_block,
id: ast::DUMMY_NODE_ID,
span: trait_.span,
self_id: ast::DUMMY_NODE_ID,
vis: ast::Inherited,
}
}

View file

@ -244,13 +244,13 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
let self_path = cx.expr_self(span);
match *self_ptr {
None => {
(self_path, respan(span, ast::SelfValue(ast::MutImmutable)))
(self_path, respan(span, ast::SelfValue))
}
Some(ref ptr) => {
let self_ty = respan(
span,
match *ptr {
Send => ast::SelfUniq(ast::MutImmutable),
Send => ast::SelfUniq,
Managed => ast::SelfBox,
Borrowed(ref lt, mutbl) => {
let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s)));

View file

@ -306,9 +306,7 @@ fn fold_explicit_self(&mut self, es: &ExplicitSelf) -> ExplicitSelf {
fn fold_explicit_self_(&mut self, es: &ExplicitSelf_) -> ExplicitSelf_ {
match *es {
SelfStatic | SelfValue(_) | SelfUniq(_) | SelfBox => {
*es
}
SelfStatic | SelfValue | SelfUniq | SelfBox => *es,
SelfRegion(ref lifetime, m) => {
SelfRegion(fold_opt_lifetime(lifetime, self), m)
}
@ -666,7 +664,6 @@ pub fn noop_fold_method<T: Folder>(m: &Method, folder: &mut T) -> @Method {
body: folder.fold_block(m.body),
id: folder.new_id(m.id),
span: folder.new_span(m.span),
self_id: folder.new_id(m.self_id),
vis: m.vis
}
}
@ -737,10 +734,9 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
args.map(|&x| folder.fold_expr(x)),
blk)
}
ExprMethodCall(callee_id, f, i, ref tps, ref args, blk) => {
ExprMethodCall(callee_id, i, ref tps, ref args, blk) => {
ExprMethodCall(
folder.new_id(callee_id),
folder.fold_expr(f),
folder.fold_ident(i),
tps.map(|&x| folder.fold_ty(x)),
args.map(|&x| folder.fold_expr(x)),
@ -811,7 +807,6 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
folder.fold_expr(er))
}
ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
ExprSelf => ExprSelf,
ExprLogLevel => ExprLogLevel,
ExprBreak(opt_ident) => ExprBreak(opt_ident),
ExprAgain(opt_ident) => ExprAgain(opt_ident),

View file

@ -31,8 +31,8 @@ pub fn expr_requires_semi_to_be_stmt(e: @ast::Expr) -> bool {
| ast::ExprForLoop(..)
| ast::ExprCall(_, _, ast::DoSugar)
| ast::ExprCall(_, _, ast::ForSugar)
| ast::ExprMethodCall(_, _, _, _, _, ast::DoSugar)
| ast::ExprMethodCall(_, _, _, _, _, ast::ForSugar) => false,
| ast::ExprMethodCall(_, _, _, _, ast::DoSugar)
| ast::ExprMethodCall(_, _, _, _, ast::ForSugar) => false,
_ => true
}
}

View file

@ -27,8 +27,8 @@
use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc, ExprRepeat};
use ast::{ExprRet, ExprSelf, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
use ast::{ExprVec, ExprVstore, ExprVstoreSlice, ExprVstoreBox};
use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, ExternFn, Field, FnDecl};
use ast::{ExprVstoreUniq, Onceness, Once, Many};
@ -1093,7 +1093,6 @@ pub fn parse_trait_methods(&mut self) -> ~[TraitMethod] {
body: body,
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
self_id: ast::DUMMY_NODE_ID,
vis: vis,
})
}
@ -1687,13 +1686,9 @@ pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr], sugar: CallSugar) -> ast::Ex
ExprCall(f, args, sugar)
}
pub fn mk_method_call(&mut self,
rcvr: @Expr,
ident: Ident,
tps: ~[P<Ty>],
args: ~[@Expr],
fn mk_method_call(&mut self, ident: Ident, tps: ~[P<Ty>], args: ~[@Expr],
sugar: CallSugar) -> ast::Expr_ {
ExprMethodCall(ast::DUMMY_NODE_ID, rcvr, ident, tps, args, sugar)
ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args, sugar)
}
pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
@ -1794,7 +1789,8 @@ pub fn parse_bottom_expr(&mut self) -> @Expr {
return self.mk_expr(lo, body.span.hi, ExprProc(decl, fakeblock));
} else if self.eat_keyword(keywords::Self) {
ex = ExprSelf;
let path = ast_util::ident_to_path(mk_sp(lo, hi), special_idents::self_);
ex = ExprPath(path);
hi = self.span.hi;
} else if self.eat_keyword(keywords::If) {
return self.parse_if_expr();
@ -1993,7 +1989,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
// expr.f() method call
match self.token {
token::LPAREN => {
let es = self.parse_unspanned_seq(
let mut es = self.parse_unspanned_seq(
&token::LPAREN,
&token::RPAREN,
seq_sep_trailing_disallowed(token::COMMA),
@ -2001,7 +1997,8 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: @Expr) -> @Expr {
);
hi = self.span.hi;
let nd = self.mk_method_call(e, i, tys, es, NoSugar);
es.unshift(e);
let nd = self.mk_method_call(i, tys, es, NoSugar);
e = self.mk_expr(lo, hi, nd);
}
_ => {
@ -2569,16 +2566,15 @@ pub fn parse_sugary_call_expr(&mut self,
let block = self.parse_lambda_block_expr();
let last_arg = self.mk_expr(block.span.lo, block.span.hi,
ctor(block));
let args = vec::append((*args).clone(), [last_arg]);
let args = vec::append_one((*args).clone(), last_arg);
self.mk_expr(lo, block.span.hi, ExprCall(f, args, sugar))
}
ExprMethodCall(_, f, i, ref tps, ref args, NoSugar) => {
ExprMethodCall(_, i, ref tps, ref args, NoSugar) => {
let block = self.parse_lambda_block_expr();
let last_arg = self.mk_expr(block.span.lo, block.span.hi,
ctor(block));
let args = vec::append((*args).clone(), [last_arg]);
let method_call = self.mk_method_call(f,
i,
let args = vec::append_one((*args).clone(), last_arg);
let method_call = self.mk_method_call(i,
(*tps).clone(),
args,
sugar);
@ -2588,10 +2584,9 @@ pub fn parse_sugary_call_expr(&mut self,
let block = self.parse_lambda_block_expr();
let last_arg = self.mk_expr(block.span.lo, block.span.hi,
ctor(block));
let method_call = self.mk_method_call(f,
i,
let method_call = self.mk_method_call(i,
(*tps).clone(),
~[last_arg],
~[f, last_arg],
sugar);
self.mk_expr(lo, block.span.hi, method_call)
}
@ -3712,6 +3707,7 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
// A bit of complexity and lookahead is needed here in order to be
// backwards compatible.
let lo = self.span.lo;
let mut mutbl_self = MutImmutable;
let explicit_self = match self.token {
token::BINOP(token::AND) => {
maybe_parse_borrowed_explicit_self(self)
@ -3720,57 +3716,60 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
maybe_parse_explicit_self(SelfBox, self)
}
token::TILDE => {
maybe_parse_explicit_self(SelfUniq(MutImmutable), self)
maybe_parse_explicit_self(SelfUniq, self)
}
token::IDENT(..) if self.is_self_ident() => {
self.bump();
SelfValue(MutImmutable)
SelfValue
}
token::BINOP(token::STAR) => {
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
// emitting cryptic "unexpected token" errors.
self.bump();
let mutability = if Parser::token_is_mutability(&self.token) {
let _mutability = if Parser::token_is_mutability(&self.token) {
self.parse_mutability()
} else { MutImmutable };
if self.is_self_ident() {
self.span_err(self.span, "cannot pass self by unsafe pointer");
self.bump();
}
SelfValue(mutability)
SelfValue
}
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) => {
let mutability = self.parse_mutability();
mutbl_self = self.parse_mutability();
self.expect_self_ident();
SelfValue(mutability)
SelfValue
}
_ if Parser::token_is_mutability(&self.token) &&
self.look_ahead(1, |t| *t == token::TILDE) &&
self.look_ahead(2, |t| token::is_keyword(keywords::Self, t)) => {
let mutability = self.parse_mutability();
mutbl_self = self.parse_mutability();
self.bump();
self.expect_self_ident();
SelfUniq(mutability)
SelfUniq
}
_ => SelfStatic
};
let explicit_self_sp = mk_sp(lo, self.span.hi);
// If we parsed a self type, expect a comma before the argument list.
let fn_inputs;
if explicit_self != SelfStatic {
let fn_inputs = if explicit_self != SelfStatic {
match self.token {
token::COMMA => {
self.bump();
let sep = seq_sep_trailing_disallowed(token::COMMA);
fn_inputs = self.parse_seq_to_before_end(
let mut fn_inputs = self.parse_seq_to_before_end(
&token::RPAREN,
sep,
parse_arg_fn
);
fn_inputs.unshift(Arg::new_self(explicit_self_sp, mutbl_self));
fn_inputs
}
token::RPAREN => {
fn_inputs = ~[];
~[Arg::new_self(explicit_self_sp, mutbl_self)]
}
_ => {
let token_str = self.this_token_to_str();
@ -3780,10 +3779,8 @@ fn maybe_parse_borrowed_explicit_self(this: &mut Parser)
}
} else {
let sep = seq_sep_trailing_disallowed(token::COMMA);
fn_inputs = self.parse_seq_to_before_end(&token::RPAREN,
sep,
parse_arg_fn);
}
self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
};
self.expect(&token::RPAREN);
@ -3918,7 +3915,6 @@ fn parse_method(&mut self, already_parsed_attrs: Option<~[Attribute]>) -> @Metho
body: body,
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
self_id: ast::DUMMY_NODE_ID,
vis: visa,
}
}

View file

@ -1213,10 +1213,10 @@ fn print_field(s: &mut State, field: &ast::Field) {
print_expr(s, func);
print_call_post(s, sugar, &blk, &mut base_args);
}
ast::ExprMethodCall(_, func, ident, ref tys, ref args, sugar) => {
let mut base_args = (*args).clone();
ast::ExprMethodCall(_, ident, ref tys, ref args, sugar) => {
let mut base_args = args.slice_from(1).to_owned();
let blk = print_call_pre(s, sugar, &mut base_args);
print_expr(s, func);
print_expr(s, args[0]);
word(&mut s.s, ".");
print_ident(s, ident);
if tys.len() > 0u {
@ -1445,7 +1445,6 @@ fn print_field(s: &mut State, field: &ast::Field) {
word(&mut s.s, "]");
}
ast::ExprPath(ref path) => print_path(s, path, true),
ast::ExprSelf => word(&mut s.s, "self"),
ast::ExprBreak(opt_ident) => {
word(&mut s.s, "break");
space(&mut s.s);
@ -1749,19 +1748,20 @@ fn print_field(s: &mut State, f: &ast::FieldPat) {
}
pub fn explicit_self_to_str(explicit_self: &ast::ExplicitSelf_, intr: @IdentInterner) -> ~str {
to_str(explicit_self, |a, &b| { print_explicit_self(a, b); () }, intr)
to_str(explicit_self, |a, &b| { print_explicit_self(a, b, ast::MutImmutable); () }, intr)
}
// Returns whether it printed anything
pub fn print_explicit_self(s: &mut State, explicit_self: ast::ExplicitSelf_) -> bool {
fn print_explicit_self(s: &mut State,
explicit_self: ast::ExplicitSelf_,
mutbl: ast::Mutability) -> bool {
print_mutability(s, mutbl);
match explicit_self {
ast::SelfStatic => { return false; }
ast::SelfValue(m) => {
print_mutability(s, m);
ast::SelfValue => {
word(&mut s.s, "self");
}
ast::SelfUniq(m) => {
print_mutability(s, m);
ast::SelfUniq => {
word(&mut s.s, "~self");
}
ast::SelfRegion(ref lt, m) => {
@ -1799,11 +1799,25 @@ pub fn print_fn_args(s: &mut State, decl: &ast::FnDecl,
// self type and the args all in the same box.
rbox(s, 0u, Inconsistent);
let mut first = true;
for explicit_self in opt_explicit_self.iter() {
first = !print_explicit_self(s, *explicit_self);
for &explicit_self in opt_explicit_self.iter() {
let m = match explicit_self {
ast::SelfStatic => ast::MutImmutable,
_ => match decl.inputs[0].pat.node {
ast::PatIdent(ast::BindByValue(m), _, _) => m,
_ => ast::MutImmutable
}
};
first = !print_explicit_self(s, explicit_self, m);
}
for arg in decl.inputs.iter() {
// HACK(eddyb) ignore the separately printed self argument.
let args = if first {
decl.inputs.as_slice()
} else {
decl.inputs.slice_from(1)
};
for arg in args.iter() {
if first { first = false; } else { word_space(s, ","); }
print_arg(s, arg);
}
@ -2090,18 +2104,7 @@ pub fn print_ty_fn(s: &mut State,
popen(s);
}
// It is unfortunate to duplicate the commasep logic, but we want the
// self type and the args all in the same box.
rbox(s, 0u, Inconsistent);
let mut first = true;
for explicit_self in opt_explicit_self.iter() {
first = !print_explicit_self(s, *explicit_self);
}
for arg in decl.inputs.iter() {
if first { first = false; } else { word_space(s, ","); }
print_arg(s, arg);
}
end(s);
print_fn_args(s, decl, opt_explicit_self);
if opt_sigil == Some(ast::BorrowedSigil) {
word(&mut s.s, "|");

View file

@ -186,7 +186,7 @@ fn walk_explicit_self<E: Clone, V: Visitor<E>>(visitor: &mut V,
explicit_self: &ExplicitSelf,
env: E) {
match explicit_self.node {
SelfStatic | SelfValue(_) | SelfBox | SelfUniq(_) => {}
SelfStatic | SelfValue | SelfBox | SelfUniq => {}
SelfRegion(ref lifetime, _) => {
visitor.visit_opt_lifetime_ref(explicit_self.span, lifetime, env)
}
@ -654,12 +654,11 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
}
visitor.visit_expr(callee_expression, env.clone())
}
ExprMethodCall(_, callee, _, ref types, ref arguments, _) => {
ExprMethodCall(_, _, ref types, ref arguments, _) => {
walk_exprs(visitor, *arguments, env.clone());
for &typ in types.iter() {
visitor.visit_ty(typ, env.clone())
}
visitor.visit_expr(callee, env.clone())
}
ExprBinary(_, _, left_expression, right_expression) => {
visitor.visit_expr(left_expression, env.clone());
@ -734,7 +733,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
ExprPath(ref path) => {
visitor.visit_path(path, expression.id, env.clone())
}
ExprSelf | ExprBreak(_) | ExprAgain(_) => {}
ExprBreak(_) | ExprAgain(_) => {}
ExprRet(optional_expression) => {
walk_expr_opt(visitor, optional_expression, env.clone())
}

View file

@ -0,0 +1,19 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn foo() {}
fn main() {
let f = foo;
let f_closure: || = f;
//~^ ERROR: cannot coerce non-statically resolved bare fn
let f_proc: proc() = f;
//~^ ERROR: cannot coerce non-statically resolved bare fn
}

View file

@ -1,4 +1,4 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -11,11 +11,10 @@
struct A;
impl A {
fn m(&self) {
fn x() {
self.m()
//~^ ERROR can't capture dynamic environment in a fn item
//~^^ ERROR `self` is not allowed in this context
}
fn x() {
self.m() //~ ERROR can't capture dynamic environment in a fn item
//~^ ERROR unresolved name `self`
}
}
}
fn main() {}

View file

@ -0,0 +1,22 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(dead_assignment)];
#[allow(unused_variable)];
#[allow(dead_code)];
#[deny(unused_mut)];
struct Foo;
impl Foo {
fn foo(mut self) {} //~ ERROR: variable does not need to be mutable
fn bar(mut ~self) {} //~ ERROR: variable does not need to be mutable
}
fn main() {}

View file

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -13,7 +13,7 @@ trait foo {
}
impl foo for int {
fn bar(&self) -> int {
//~^ ERROR method `bar` has 0 parameters but the declaration in trait `foo::bar` has 1
//~^ ERROR method `bar` has 1 parameter but the declaration in trait `foo::bar` has 2
*self
}
}

View file

@ -0,0 +1,47 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn id<T>(x: T) -> T {
x
}
#[deriving(Eq)]
struct Foo<T>(T);
#[deriving(Eq)]
enum Bar<T> {
Bar(T)
}
pub fn main() {
let f: |int| -> int = id;
assert_eq!(f(5), 5);
let f: proc(int) -> int = id;
assert_eq!(f(5), 5);
let f: |int| -> Foo<int> = Foo;
assert_eq!(f(5), Foo(5));
let f: proc(int) -> Foo<int> = Foo;
assert_eq!(f(5), Foo(5));
let f: |int| -> Bar<int> = Bar;
assert_eq!(f(5), Bar(5));
let f: proc(int) -> Bar<int> = Bar;
assert_eq!(f(5), Bar(5));
let f: |int| -> Option<int> = Some;
assert_eq!(f(5), Some(5));
let f: proc(int) -> Option<int> = Some;
assert_eq!(f(5), Some(5));
}

View file

@ -13,7 +13,7 @@
fn test_fn() {
type t = 'static || -> int;
fn ten() -> int { return 10; }
let rs: t = { ten };
let rs: t = ten;
assert!((rs() == 10));
}

View file

@ -436,20 +436,6 @@ fn visit_type(&mut self) -> bool {
if ! self.inner().visit_type() { return false; }
true
}
fn visit_opaque_box(&mut self) -> bool {
self.align_to::<@u8>();
if ! self.inner().visit_opaque_box() { return false; }
self.bump_past::<@u8>();
true
}
fn visit_closure_ptr(&mut self, ck: uint) -> bool {
self.align_to::<(uint,uint)>();
if ! self.inner().visit_closure_ptr(ck) { return false; }
self.bump_past::<(uint,uint)>();
true
}
}
struct my_visitor(@RefCell<Stuff>);
@ -611,8 +597,6 @@ fn visit_trait(&mut self, _name: &str) -> bool { true }
fn visit_param(&mut self, _i: uint) -> bool { true }
fn visit_self(&mut self) -> bool { true }
fn visit_type(&mut self) -> bool { true }
fn visit_opaque_box(&mut self) -> bool { true }
fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
}
fn get_tydesc_for<T>(_t: T) -> *TyDesc {

View file

@ -137,8 +137,6 @@ fn visit_trait(&mut self, _name: &str) -> bool { true }
fn visit_param(&mut self, _i: uint) -> bool { true }
fn visit_self(&mut self) -> bool { true }
fn visit_type(&mut self) -> bool { true }
fn visit_opaque_box(&mut self) -> bool { true }
fn visit_closure_ptr(&mut self, _ck: uint) -> bool { true }
}
fn visit_ty<T>(v: &mut MyVisitor) {