From b80b0688d5ccc276e1dd3b6dfeeaea5e6f2782de Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 5 Oct 2012 18:51:36 -0700 Subject: [PATCH] rustc: Add a new method_self method call origin. Part of default methods. --- src/rustc/middle/astencode.rs | 3 ++ src/rustc/middle/privacy.rs | 7 +++-- src/rustc/middle/trans/base.rs | 15 ++++++++-- src/rustc/middle/trans/meth.rs | 3 ++ src/rustc/middle/trans/type_use.rs | 2 +- src/rustc/middle/ty.rs | 3 +- src/rustc/middle/typeck.rs | 5 +++- src/rustc/middle/typeck/check/method.rs | 38 +++++++++++++++++++++---- 8 files changed, 61 insertions(+), 15 deletions(-) diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index f2ee3df66106..a364c1d75d43 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -493,6 +493,9 @@ impl method_origin: tr { typeck::method_trait(did, m, vstore) => { typeck::method_trait(did.tr(xcx), m, vstore) } + typeck::method_self(did, m) => { + typeck::method_self(did.tr(xcx), m) + } } } } diff --git a/src/rustc/middle/privacy.rs b/src/rustc/middle/privacy.rs index f15ace40d309..98260a0d0819 100644 --- a/src/rustc/middle/privacy.rs +++ b/src/rustc/middle/privacy.rs @@ -8,8 +8,8 @@ use syntax::ast::{item_trait, local_crate, node_id, pat_struct, private}; use syntax::ast::{provided, required}; use syntax::ast_map::{node_item, node_method}; use ty::ty_class; -use typeck::{method_map, method_origin, method_param, method_static}; -use typeck::{method_trait}; +use typeck::{method_map, method_origin, method_param, method_self}; +use typeck::{method_static, method_trait}; use core::util::ignore; use dvec::DVec; @@ -81,7 +81,8 @@ fn check_crate(tcx: ty::ctxt, method_map: &method_map, crate: @ast::crate) { } } method_param({trait_id: trait_id, method_num: method_num, _}) | - method_trait(trait_id, method_num, _) => { + method_trait(trait_id, method_num, _) | + method_self(trait_id, method_num) => { if trait_id.crate == local_crate { match tcx.items.find(trait_id.node) { Some(node_item(item, _)) => { diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 24774add4dc3..afa008fdbb77 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1847,7 +1847,7 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { } } } - ast::item_impl(tps, trait_refs, _, ms) => { + ast::item_impl(tps, trait_refs, self_ast_ty, ms) => { meth::trans_impl(ccx, *path, item.ident, ms, tps, None); // Translate any methods that have provided implementations. @@ -1860,13 +1860,22 @@ fn trans_item(ccx: @crate_ctxt, item: ast::item) { loop; } + // Get the self type. + let self_ty; + match ccx.tcx.ast_ty_to_ty_cache.get(self_ast_ty) { + ty::atttce_resolved(self_type) => self_ty = self_type, + ty::atttce_unresolved => { + ccx.tcx.sess.impossible_case(item.span, + ~"didn't cache self ast ty"); + } + } + match ccx.tcx.items.get(trait_id.node) { ast_map::node_item(trait_item, _) => { match trait_item.node { ast::item_trait(tps, _, trait_methods) => { - // XXX: ty_self is wrong here. Get the real type. trans_trait(ccx, tps, trait_methods, path, - item.ident, ty::mk_self(ccx.tcx)); + item.ident, self_ty); } _ => { ccx.tcx.sess.impossible_case(item.span, diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index 65605f0e4668..b4a64abeed7e 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -154,6 +154,9 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, typeck::method_trait(_, off, vstore) => { trans_trait_callee(bcx, callee_id, off, self, vstore) } + typeck::method_self(_, off) => { + bcx.tcx().sess.span_bug(self.span, ~"self method call"); + } } } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 8bd5bd7afc78..8eabf26e2178 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -247,7 +247,7 @@ fn mark_for_expr(cx: ctx, e: @expr) { typeck::method_param({param_num: param, _}) => { cx.uses[param] |= use_tydesc; } - typeck::method_trait(*) => (), + typeck::method_trait(*) | typeck::method_self(*) => (), } } } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 78949ec5f794..f2f7b32b6706 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -2826,7 +2826,8 @@ fn method_call_bounds(tcx: ctxt, method_map: typeck::method_map, } typeck::method_param({trait_id:trt_id, method_num:n_mth, _}) | - typeck::method_trait(trt_id, n_mth, _) => { + typeck::method_trait(trt_id, n_mth, _) | + typeck::method_self(trt_id, n_mth) => { // ...trait methods bounds, in contrast, include only the // method bounds, so we must preprend the tps from the // trait itself. This ought to be harmonized. diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index 6c461126853f..514fc2cfbb32 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -73,7 +73,7 @@ export deserialize_method_map_entry; export vtable_map; export vtable_res; export vtable_origin; -export method_static, method_param, method_trait; +export method_static, method_param, method_trait, method_self; export vtable_static, vtable_param, vtable_trait; export provided_methods_map; @@ -87,6 +87,9 @@ enum method_origin { // method invoked on a trait instance method_trait(ast::def_id, uint, ty::vstore), + + // method invoked on "self" inside a default method + method_self(ast::def_id, uint), } // details for a method invoked with a receiver whose type is a type parameter diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs index d55f9facc626..f3b2c8f1b7ed 100644 --- a/src/rustc/middle/typeck/check/method.rs +++ b/src/rustc/middle/typeck/check/method.rs @@ -232,9 +232,8 @@ impl LookupContext { let self_did = self.fcx.self_impl_def_id.expect( ~"unexpected `none` for self_impl_def_id"); let substs = {self_r: None, self_ty: None, tps: ~[]}; - self.push_inherent_candidates_from_trait( - self_ty, self_did, &substs, - ty::vstore_slice(ty::re_static)); // XXX: Wrong! + self.push_inherent_candidates_from_self( + self_ty, self_did, &substs); } ty_enum(did, _) | ty_class(did, _) => { self.push_inherent_impl_candidates_for_type(did); @@ -397,6 +396,33 @@ impl LookupContext { }); } + fn push_inherent_candidates_from_self(&self, + self_ty: ty::t, + did: def_id, + substs: &ty::substs) { + let tcx = self.tcx(); + let methods = ty::trait_methods(tcx, did); // XXX: Inherited methods. + let index; + match vec::position(*methods, |m| m.ident == self.m_name) { + Some(i) => index = i, + None => return + } + let method = &methods[index]; + + let rcvr_substs = { self_ty: Some(self_ty), ..*substs }; + let (rcvr_ty, rcvr_substs) = + self.create_rcvr_ty_and_substs_for_method( + method.self_ty, self_ty, move rcvr_substs); + + self.inherent_candidates.push(Candidate { + rcvr_ty: rcvr_ty, + rcvr_substs: move rcvr_substs, + num_method_tps: method.tps.len(), + self_mode: get_mode_from_self_type(method.self_ty), + origin: method_self(did, index) + }); + } + fn push_inherent_impl_candidates_for_type(did: def_id) { let opt_impl_infos = @@ -737,7 +763,7 @@ impl LookupContext { * vtable and hence cannot be monomorphized. */ match candidate.origin { - method_static(*) | method_param(*) => { + method_static(*) | method_param(*) | method_self(*) => { return; // not a call to a trait instance } method_trait(*) => {} @@ -772,7 +798,7 @@ impl LookupContext { method_param(ref mp) => { type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num) } - method_trait(did, idx, _) => { + method_trait(did, idx, _) | method_self(did, idx) => { type_of_trait_method(self.tcx(), did, idx) } }; @@ -793,7 +819,7 @@ impl LookupContext { method_param(mp) => { self.report_param_candidate(idx, mp.trait_id) } - method_trait(trait_did, _, _) => { + method_trait(trait_did, _, _) | method_self(trait_did, _) => { self.report_param_candidate(idx, trait_did) } }