mirror of
https://github.com/rust-lang/rust
synced 2024-09-05 00:24:52 +00:00
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:
commit
d6d7812da8
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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), ':');
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
_ => { }
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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(..)) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(..) |
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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]) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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, _) => {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
};
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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>(
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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, ¶m_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, ¶m_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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 {}",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {:?}",
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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: {}",
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => {}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, "|");
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
19
src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs
Normal file
19
src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs
Normal 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
|
||||
}
|
|
@ -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() {}
|
||||
|
|
22
src/test/compile-fail/lint-unused-mut-self.rs
Normal file
22
src/test/compile-fail/lint-unused-mut-self.rs
Normal 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() {}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
47
src/test/run-pass/coerce-to-closure-and-proc.rs
Normal file
47
src/test/run-pass/coerce-to-closure-and-proc.rs
Normal 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));
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in a new issue