From 15ba0c310a2bfe2ab69670d0d87529a29d527973 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Mon, 27 Jan 2014 14:18:36 +0200 Subject: [PATCH] Demote self to an (almost) regular argument and remove the env param. Fixes #10667 and closes #10259. --- src/libextra/test.rs | 2 +- src/librustc/metadata/common.rs | 25 +- src/librustc/metadata/decoder.rs | 16 +- src/librustc/metadata/encoder.rs | 31 +- src/librustc/metadata/tydecode.rs | 4 - src/librustc/metadata/tyencode.rs | 4 - src/librustc/middle/astencode.rs | 22 +- src/librustc/middle/borrowck/check_loans.rs | 22 +- .../borrowck/gather_loans/gather_moves.rs | 3 +- .../middle/borrowck/gather_loans/lifetime.rs | 5 +- .../borrowck/gather_loans/restrictions.rs | 3 +- src/librustc/middle/borrowck/mod.rs | 19 +- src/librustc/middle/cfg/construct.rs | 5 +- src/librustc/middle/dataflow.rs | 21 +- src/librustc/middle/effect.rs | 2 +- src/librustc/middle/freevars.rs | 2 +- src/librustc/middle/kind.rs | 3 +- src/librustc/middle/liveness.rs | 33 +- src/librustc/middle/mem_categorization.rs | 19 +- src/librustc/middle/moves.rs | 21 +- src/librustc/middle/privacy.rs | 4 +- src/librustc/middle/region.rs | 6 - src/librustc/middle/resolve.rs | 147 ++------ src/librustc/middle/trans/_match.rs | 4 +- src/librustc/middle/trans/base.rs | 247 +++++--------- src/librustc/middle/trans/builder.rs | 5 + src/librustc/middle/trans/callee.rs | 198 +++++------ src/librustc/middle/trans/cleanup.rs | 2 +- src/librustc/middle/trans/closure.rs | 230 +++++++------ src/librustc/middle/trans/common.rs | 20 +- src/librustc/middle/trans/consts.rs | 70 ++-- src/librustc/middle/trans/context.rs | 4 + src/librustc/middle/trans/controlflow.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 93 +----- src/librustc/middle/trans/expr.rs | 143 +++----- src/librustc/middle/trans/foreign.rs | 21 +- src/librustc/middle/trans/glue.rs | 316 +++++++++--------- src/librustc/middle/trans/inline.rs | 21 +- src/librustc/middle/trans/intrinsic.rs | 11 +- src/librustc/middle/trans/meth.rs | 168 +++------- src/librustc/middle/trans/monomorphize.rs | 47 +-- src/librustc/middle/trans/reflect.rs | 21 +- src/librustc/middle/trans/type_.rs | 40 +-- src/librustc/middle/trans/type_of.rs | 52 ++- src/librustc/middle/ty.rs | 151 ++++----- src/librustc/middle/ty_fold.rs | 1 - src/librustc/middle/typeck/astconv.rs | 106 +++--- src/librustc/middle/typeck/check/method.rs | 143 ++++---- src/librustc/middle/typeck/check/mod.rs | 313 ++++++----------- src/librustc/middle/typeck/check/regionck.rs | 19 +- .../middle/typeck/check/regionmanip.rs | 30 +- src/librustc/middle/typeck/check/vtable.rs | 2 +- src/librustc/middle/typeck/check/writeback.rs | 63 ++-- src/librustc/middle/typeck/coherence.rs | 8 +- src/librustc/middle/typeck/collect.rs | 14 +- src/librustc/middle/typeck/infer/coercion.rs | 57 ++-- src/librustc/middle/typeck/infer/mod.rs | 6 +- src/librustc/middle/typeck/infer/sub.rs | 4 +- src/librustc/middle/typeck/mod.rs | 15 +- src/librustc/middle/typeck/variance.rs | 20 +- src/librustc/util/ppaux.rs | 23 +- src/librustdoc/clean.rs | 30 +- src/librustdoc/html/render.rs | 2 +- src/librustuv/net.rs | 2 +- src/librustuv/pipe.rs | 2 +- src/libstd/io/buffered.rs | 2 +- src/libstd/reflect.rs | 9 +- src/libstd/repr.rs | 10 +- src/libstd/unstable/intrinsics.rs | 4 +- src/libsyntax/ast.rs | 51 ++- src/libsyntax/ast_map.rs | 27 +- src/libsyntax/ast_util.rs | 41 +-- src/libsyntax/ext/build.rs | 9 +- src/libsyntax/ext/deriving/generic.rs | 8 +- src/libsyntax/ext/deriving/ty.rs | 4 +- src/libsyntax/fold.rs | 9 +- src/libsyntax/parse/classify.rs | 4 +- src/libsyntax/parse/parser.rs | 70 ++-- src/libsyntax/print/pprust.rs | 53 +-- src/libsyntax/visit.rs | 7 +- .../coerce-bare-fn-to-closure-and-proc.rs | 19 ++ src/test/compile-fail/issue-6642.rs | 11 +- src/test/compile-fail/lint-unused-mut-self.rs | 22 ++ .../trait-impl-different-num-params.rs | 4 +- .../run-pass/coerce-to-closure-and-proc.rs | 47 +++ src/test/run-pass/expr-block-fn.rs | 2 +- src/test/run-pass/reflect-visit-data.rs | 16 - src/test/run-pass/reflect-visit-type.rs | 2 - 88 files changed, 1437 insertions(+), 2139 deletions(-) create mode 100644 src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs create mode 100644 src/test/compile-fail/lint-unused-mut-self.rs create mode 100644 src/test/run-pass/coerce-to-closure-and-proc.rs diff --git a/src/libextra/test.rs b/src/libextra/test.rs index a54f3110cd6..c621461fc36 100644 --- a/src/libextra/test.rs +++ b/src/libextra/test.rs @@ -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; } diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 09531e80ae5..e8cfa97c0e1 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -176,24 +176,23 @@ pub fn from_uint(value : uint) -> Option { 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; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index a7e5082bcbb..11fab9cced7 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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 -{ - 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, diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index c7d238dac18..8a2c56cbcd3 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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) { - 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); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 4f19d461c85..a40ba4a44a5 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -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), ':'); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 965aab31f14..23e96110c06 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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); diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index b990c5073d1..a601b624c19 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -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) }) }) } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 0fd92079489..59310d722e4 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -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); } } - _ => { } + _ => {} } } diff --git a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs index 9ba8e00dc8e..78350a993b4 100644 --- a/src/librustc/middle/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc/middle/borrowck/gather_loans/gather_moves.rs @@ -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 } diff --git a/src/librustc/middle/borrowck/gather_loans/lifetime.rs b/src/librustc/middle/borrowck/gather_loans/lifetime.rs index 9a4869fb6d1..4c2f0986d9c 100644 --- a/src/librustc/middle/borrowck/gather_loans/lifetime.rs +++ b/src/librustc/middle/borrowck/gather_loans/lifetime.rs @@ -76,7 +76,6 @@ fn check(&self, cmt: mc::cmt, discr_scope: Option) -> 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(..)) => { diff --git a/src/librustc/middle/borrowck/gather_loans/restrictions.rs b/src/librustc/middle/borrowck/gather_loans/restrictions.rs index 50b437e95d5..22e64064c9c 100644 --- a/src/librustc/middle/borrowck/gather_loans/restrictions.rs +++ b/src/librustc/middle/borrowck/gather_loans/restrictions.rs @@ -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, diff --git a/src/librustc/middle/borrowck/mod.rs b/src/librustc/middle/borrowck/mod.rs index 002f263209a..90c9a61b18b 100644 --- a/src/librustc/middle/borrowck/mod.rs +++ b/src/librustc/middle/borrowck/mod.rs @@ -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( diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index dc0b700da52..923e5eba109 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -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(..) | diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index 9115125324c..a0ef6e503a1 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -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 diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index e291d2595a0..36dd46388c6 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -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)); diff --git a/src/librustc/middle/freevars.rs b/src/librustc/middle/freevars.rs index 4ee8eb4108d..635fbf7eea8 100644 --- a/src/librustc/middle/freevars.rs +++ b/src/librustc/middle/freevars.rs @@ -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) { diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index fde3e4809c3..81a00e27fa0 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -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, diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 180b97ce270..dfe9af9f3f0 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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); + } }) } } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 70d4f63a164..b6271b68046 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -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 { 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) } diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs index e0146694881..054e2936439 100644 --- a/src/librustc/middle/moves.rs +++ b/src/librustc/middle/moves.rs @@ -227,10 +227,9 @@ pub fn compute_moves(tcx: ty::ctxt, pub fn moved_variable_node_id_from_def(def: Def) -> Option { 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]) { diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 052a6ad898f..2562c34b54b 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -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(); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index c202684c7ab..4ebbd097f29 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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) diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index b6a4a55186c..dab9c7c71d9 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -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>, - self_binding: RefCell>, 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 { 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 { // 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>, - type_parameters: TypeParameters, - block: P, - self_binding: SelfBinding) { + rib_kind: RibKind, + optional_declaration: Option>, + type_parameters: TypeParameters, + block: P) { // 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 { - // 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); diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index c8d2cf36938..d5022b2a4df 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -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, _) => { diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 9744c395b7c..c71469f0c3d 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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, - 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, 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) @@ -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) -> 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; type LvalueDatum = datum::Datum; -// 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, - arg_tys: &[ty::t]) - -> (Option, ~[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, 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, 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, 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) + 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 } diff --git a/src/librustc/middle/trans/builder.rs b/src/librustc/middle/trans/builder.rs index c4beb935ffe..71b25b79feb 100644 --- a/src/librustc/middle/trans/builder.rs +++ b/src/librustc/middle/trans/builder.rs @@ -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()); diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 229a1b3662d..e10c7af7f31 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -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), - 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) // 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, - autoref_arg: AutorefArg) + dest: Option) -> 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 diff --git a/src/librustc/middle/trans/cleanup.rs b/src/librustc/middle/trans/cleanup.rs index 020b840e5b2..6e92ea9f11e 100644 --- a/src/librustc/middle/trans/cleanup.rs +++ b/src/librustc/middle/trans/cleanup.rs @@ -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); diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 21091c4f88e..4d171bc86b1 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -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()) } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index e466e4da38d..45f5d84eb8a 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -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, + // The environment argument in a closure. + llenv: Option, // 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>, llreturn: Cell>, - // 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>, - // The a value alloca'd for calls to upcalls.rust_personality. Used when // outputting the resume instruction. personality: Cell>, @@ -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 } } diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index a28cb1a030c..da4be012dc0 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -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") }; diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 527308be0ff..01040824681 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -91,6 +91,9 @@ pub struct CrateContext { impl_method_cache: RefCell>, + // Cache of closure wrappers for bare fn's. + closure_bare_wrapper_cache: RefCell>, + module_data: RefCell>, lltypes: RefCell>, llsizingtypes: RefCell>, @@ -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()), diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index ec47dbacb39..8c8c6829e49 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -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); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 4c5ed91e5f7..c4fdc895670 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -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); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 36fc927b64c..8de2c1d4cb2 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -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` 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, diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 2526d8e3fea..fd0d8a890e3 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -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. diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index ae03d48dbf0..5004bcca91e 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -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); diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index 98e3593a9f1..3a0b97813df 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -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) } diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index fe2b3578a05..eb71f6b8f19 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -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, diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 338b487de46..0301bbf5979 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -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| -> 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 => { diff --git a/src/librustc/middle/trans/monomorphize.rs b/src/librustc/middle/trans/monomorphize.rs index 5e3e3236394..678d23c0e19 100644 --- a/src/librustc/middle/trans/monomorphize.rs +++ b/src/librustc/middle/trans/monomorphize.rs @@ -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, diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index c13bb139da7..46086828329 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -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") } } diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 833a7848ad3..bbaf94afabe 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -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() }; diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 4db89fbecce..a4228fbd17b 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -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, - 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, 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, 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); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 5b038d3c944..a31b8413550 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -73,7 +73,6 @@ pub enum MethodContainer { pub struct Method { ident: ast::Ident, generics: ty::Generics, - transformed_self_ty: Option, 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, fty: BareFnTy, explicit_self: ast::ExplicitSelf_, vis: ast::Visibility, @@ -95,17 +93,9 @@ pub fn new(ident: ast::Ident, container: MethodContainer, provided_source: Option) -> 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(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); } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 28ba566c0a4..e322792c996 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -189,7 +189,6 @@ pub fn super_fold_sty(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() diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index 2e25ac941a6..f1e1f379b0c 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -589,13 +589,8 @@ fn check_path_args(tcx: ty::ctxt, return typ; } -pub fn ty_of_arg( - this: &AC, - rscope: &RS, - a: &ast::Arg, - expected_ty: Option) - -> ty::t { +pub fn ty_of_arg(this: &AC, rscope: &RS, a: &ast::Arg, + expected_ty: Option) -> 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( purity: ast::Purity, untransformed_self_ty: ty::t, explicit_self: ast::ExplicitSelf, - decl: &ast::FnDecl) -> (Option, 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( - 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(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( - this: &AC, - id: ast::NodeId, - purity: ast::Purity, - abi: AbiSet, - opt_self_info: Option<&SelfInfo>, - decl: &ast::FnDecl) -> (Option>, ty::BareFnTy) -{ +fn ty_of_method_or_bare_fn(this: &AC, id: ast::NodeId, + purity: ast::Purity, abi: AbiSet, + opt_self_info: Option, + 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( - this: &AC, - rscope: &RS, - self_info: &SelfInfo) -> Option - { + 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( 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( diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 002dd0c002a..398b4cca015 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -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) => { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 5f221994787..a0b50f65f20 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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, - 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, - 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) { - 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], 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 { - 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, @@ -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 { 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); diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index b21f2c74630..1653429e457 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -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 { 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. diff --git a/src/librustc/middle/typeck/check/regionmanip.rs b/src/librustc/middle/typeck/check/regionmanip.rs index daf5bdd9ea3..0b04db88234 100644 --- a/src/librustc/middle/typeck/check/regionmanip.rs +++ b/src/librustc/middle/typeck/check/regionmanip.rs @@ -21,29 +21,26 @@ pub fn replace_bound_regions_in_fn_sig( tcx: ty::ctxt, - opt_self_ty: Option, fn_sig: &ty::FnSig, mapf: |ty::BoundRegion| -> ty::Region) - -> (HashMap, Option, ty::FnSig) { - debug!("replace_bound_regions_in_fn_sig(self_ty={}, fn_sig={})", - opt_self_ty.repr(tcx), - fn_sig.repr(tcx)); + -> (HashMap, 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, - 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)); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 43af40363cd..0a231be5d45 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -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 {}", diff --git a/src/librustc/middle/typeck/check/writeback.rs b/src/librustc/middle/typeck/check/writeback.rs index 2237c2f43e1..48b1acd3f9b 100644 --- a/src/librustc/middle/typeck/check/writeback.rs +++ b/src/librustc/middle/typeck/check/writeback.rs @@ -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) -> 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 diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index d533f9b0b13..0dcb3c7329b 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -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), diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 474335caa7b..04d708f0638 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -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, diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index d3931d277dd..6a4de959c2b 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -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, diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 68fb4b1e579..812b7ffd97d 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -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) { - 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 {:?}", diff --git a/src/librustc/middle/typeck/infer/sub.rs b/src/librustc/middle/typeck/infer/sub.rs index 6e370a85096..19abbecaa8a 100644 --- a/src/librustc/middle/typeck/infer/sub.rs +++ b/src/librustc/middle/typeck/infer/sub.rs @@ -171,8 +171,8 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres { // 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), diff --git a/src/librustc/middle/typeck/mod.rs b/src/librustc/middle/typeck/mod.rs index da3a2eebfeb..8837a978f43 100644 --- a/src/librustc/middle/typeck/mod.rs +++ b/src/librustc/middle/typeck/mod.rs @@ -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") + } } } diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 7740645030d..c2608967313 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -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: {}", diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index dc35ab7e885..7199c945627 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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)) } } diff --git a/src/librustdoc/clean.rs b/src/librustdoc/clean.rs index e48c0800506..e86122fb7d1 100644 --- a/src/librustdoc/clean.rs +++ b/src/librustdoc/clean.rs @@ -330,6 +330,16 @@ pub struct Method { impl Clean 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 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 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"); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b0a56cb402b..90ed4a4c744 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -682,7 +682,7 @@ fn recurse(&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 diff --git a/src/librustuv/net.rs b/src/librustuv/net.rs index 74489b70192..012ab9ed122 100644 --- a/src/librustuv/net.rs +++ b/src/librustuv/net.rs @@ -338,7 +338,7 @@ fn socket_name(&mut self) -> Result { } 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 }; diff --git a/src/librustuv/pipe.rs b/src/librustuv/pipe.rs index 0fed29631a6..36a7a631943 100644 --- a/src/librustuv/pipe.rs +++ b/src/librustuv/pipe.rs @@ -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 }; diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 745273a1d74..64e42c5480f 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -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 Writer for LineBufferedWriter { diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs index c0af649f26c..87655f5911f 100644 --- a/src/libstd/reflect.rs +++ b/src/libstd/reflect.rs @@ -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::(); if ! self.inner.visit_closure_ptr(ck) { diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs index e3b34147c01..1ecc31ec2f4 100644 --- a/src/libstd/repr.rs +++ b/src/libstd/repr.rs @@ -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 } } diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index 198df3090ee..1988993707f 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -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; } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 03b7f1891a1..10b1aad8138 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -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 { 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], ~[@Expr], CallSugar), + ExprMethodCall(NodeId, Ident, ~[P], ~[@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), ExprAgain(Option), @@ -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]), TyPath(Path, Option>, 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, Mutability), // `&'lt self`, `&'lt mut self` SelfBox, // `@self` - SelfUniq(Mutability) // `~self`, `mut ~self` + SelfUniq // `~self` } pub type ExplicitSelf = Spanned; @@ -971,7 +989,6 @@ pub struct Method { body: P, id: NodeId, span: Span, - self_id: NodeId, vis: Visibility, } diff --git a/src/libsyntax/ast_map.rs b/src/libsyntax/ast_map.rs index 49bea6a33a9..bb66d620d29 100644 --- a/src/libsyntax/ast_map.rs +++ b/src/libsyntax/ast_map.rs @@ -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), /// 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 Folder for Ctx { @@ -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(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, diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index d3504f8d204..405de5c5542 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -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 => {} diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index 3b2cc4ca6ed..3b43c96a184 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -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::Expr { self.expr(b.span, ast::ExprBlock(b)) diff --git a/src/libsyntax/ext/deriving/generic.rs b/src/libsyntax/ext/deriving/generic.rs index 1f778779fbd..e1fb80049e0 100644 --- a/src/libsyntax/ext/deriving/generic.rs +++ b/src/libsyntax/ext/deriving/generic.rs @@ -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, } } diff --git a/src/libsyntax/ext/deriving/ty.rs b/src/libsyntax/ext/deriving/ty.rs index c2b32b45ce4..b22dcfe0da2 100644 --- a/src/libsyntax/ext/deriving/ty.rs +++ b/src/libsyntax/ext/deriving/ty.rs @@ -244,13 +244,13 @@ pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option) 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))); diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 7a86dd6e4ce..c739fb911ba 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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(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(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(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), diff --git a/src/libsyntax/parse/classify.rs b/src/libsyntax/parse/classify.rs index 1204cbc2eea..61c80919b6e 100644 --- a/src/libsyntax/parse/classify.rs +++ b/src/libsyntax/parse/classify.rs @@ -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 } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index e110ebae093..17590ccf523 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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], - args: ~[@Expr], + fn mk_method_call(&mut self, ident: Ident, tps: ~[P], 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, } } diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 36a87658c11..d3c194b6af6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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, "|"); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 484f8dce1f7..5e7ad3af526 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -186,7 +186,7 @@ fn walk_explicit_self>(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>(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>(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()) } diff --git a/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs b/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs new file mode 100644 index 00000000000..c165802d61f --- /dev/null +++ b/src/test/compile-fail/coerce-bare-fn-to-closure-and-proc.rs @@ -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 or the MIT license +// , 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 +} diff --git a/src/test/compile-fail/issue-6642.rs b/src/test/compile-fail/issue-6642.rs index bffca995b8e..2c1809d4d48 100644 --- a/src/test/compile-fail/issue-6642.rs +++ b/src/test/compile-fail/issue-6642.rs @@ -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() {} diff --git a/src/test/compile-fail/lint-unused-mut-self.rs b/src/test/compile-fail/lint-unused-mut-self.rs new file mode 100644 index 00000000000..ada534ffc72 --- /dev/null +++ b/src/test/compile-fail/lint-unused-mut-self.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/trait-impl-different-num-params.rs b/src/test/compile-fail/trait-impl-different-num-params.rs index f293644840a..ea2062dd272 100644 --- a/src/test/compile-fail/trait-impl-different-num-params.rs +++ b/src/test/compile-fail/trait-impl-different-num-params.rs @@ -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 } } diff --git a/src/test/run-pass/coerce-to-closure-and-proc.rs b/src/test/run-pass/coerce-to-closure-and-proc.rs new file mode 100644 index 00000000000..6f643ca0f41 --- /dev/null +++ b/src/test/run-pass/coerce-to-closure-and-proc.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn id(x: T) -> T { + x +} + +#[deriving(Eq)] +struct Foo(T); + +#[deriving(Eq)] +enum Bar { + 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 = Foo; + assert_eq!(f(5), Foo(5)); + + let f: proc(int) -> Foo = Foo; + assert_eq!(f(5), Foo(5)); + + let f: |int| -> Bar = Bar; + assert_eq!(f(5), Bar(5)); + + let f: proc(int) -> Bar = Bar; + assert_eq!(f(5), Bar(5)); + + let f: |int| -> Option = Some; + assert_eq!(f(5), Some(5)); + + let f: proc(int) -> Option = Some; + assert_eq!(f(5), Some(5)); +} diff --git a/src/test/run-pass/expr-block-fn.rs b/src/test/run-pass/expr-block-fn.rs index e1850925223..9ca41c56dc9 100644 --- a/src/test/run-pass/expr-block-fn.rs +++ b/src/test/run-pass/expr-block-fn.rs @@ -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)); } diff --git a/src/test/run-pass/reflect-visit-data.rs b/src/test/run-pass/reflect-visit-data.rs index e244eace65b..6dec5fdaa1c 100644 --- a/src/test/run-pass/reflect-visit-data.rs +++ b/src/test/run-pass/reflect-visit-data.rs @@ -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); @@ -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) -> *TyDesc { diff --git a/src/test/run-pass/reflect-visit-type.rs b/src/test/run-pass/reflect-visit-type.rs index f5871facd1d..91e69028103 100644 --- a/src/test/run-pass/reflect-visit-type.rs +++ b/src/test/run-pass/reflect-visit-type.rs @@ -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(v: &mut MyVisitor) {