diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2012-10-12 17:00:08 -0700 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2012-10-12 17:46:43 -0700 |
| commit | cb55e246ba517a14eaabb82cba3294ab4ad23c0a (patch) | |
| tree | e2c9dd4e2183de97b01c81c08b71d0b46a471e1a /src/rustc | |
| parent | 57b4d10ff652d3beddae64782c882a07822bac3c (diff) | |
Use the Nth impl when translating a static method call, instead
of the 0th. 0th is only correct when there are no bound tps on the trait. Fixes #3741.
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/metadata/decoder.rs | 64 | ||||
| -rw-r--r-- | src/rustc/metadata/encoder.rs | 1 | ||||
| -rw-r--r-- | src/rustc/middle/astencode.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/resolve.rs | 1 | ||||
| -rw-r--r-- | src/rustc/middle/trans/callee.rs | 5 | ||||
| -rw-r--r-- | src/rustc/middle/trans/expr.rs | 7 | ||||
| -rw-r--r-- | src/rustc/middle/trans/meth.rs | 43 | ||||
| -rw-r--r-- | src/rustc/middle/typeck/check.rs | 4 |
8 files changed, 90 insertions, 39 deletions
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs index 4c647d41880..38838120a10 100644 --- a/src/rustc/metadata/decoder.rs +++ b/src/rustc/metadata/decoder.rs @@ -178,6 +178,12 @@ fn item_parent_item(d: ebml::Doc) -> Option<ast::def_id> { None } +fn item_reqd_and_translated_parent_item(cnum: ast::crate_num, + d: ebml::Doc) -> ast::def_id { + let trait_did = item_parent_item(d).expect(~"item without parent"); + {crate: cnum, node: trait_did.node} +} + fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id { let tagdoc = ebml::get_doc(d, tag_def_id); return translate_def_id(cdata, ebml::with_doc_data(tagdoc, @@ -297,35 +303,39 @@ fn item_name(intr: @ident_interner, item: ebml::Doc) -> ast::ident { } fn item_to_def_like(item: ebml::Doc, did: ast::def_id, cnum: ast::crate_num) - -> def_like { + -> def_like +{ let fam = item_family(item); match fam { - Const => dl_def(ast::def_const(did)), - Class => dl_def(ast::def_class(did, true)), - Struct => dl_def(ast::def_class(did, false)), - UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), - Fn => dl_def(ast::def_fn(did, ast::impure_fn)), - PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), - ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), - UnsafeStaticMethod => dl_def(ast::def_static_method(did, - ast::unsafe_fn)), - StaticMethod => dl_def(ast::def_static_method(did, ast::impure_fn)), - PureStaticMethod => dl_def(ast::def_static_method(did, ast::pure_fn)), - Type | ForeignType => dl_def(ast::def_ty(did)), - Mod => dl_def(ast::def_mod(did)), - ForeignMod => dl_def(ast::def_foreign_mod(did)), - Variant => { - match item_parent_item(item) { - Some(t) => { - let tid = {crate: cnum, node: t.node}; - dl_def(ast::def_variant(tid, did)) - } - None => fail ~"item_to_def_like: enum item has no parent" - } - } - Trait | Enum => dl_def(ast::def_ty(did)), - Impl => dl_impl(did), - PublicField | PrivateField | InheritedField => dl_field, + Const => dl_def(ast::def_const(did)), + Class => dl_def(ast::def_class(did, true)), + Struct => dl_def(ast::def_class(did, false)), + UnsafeFn => dl_def(ast::def_fn(did, ast::unsafe_fn)), + Fn => dl_def(ast::def_fn(did, ast::impure_fn)), + PureFn => dl_def(ast::def_fn(did, ast::pure_fn)), + ForeignFn => dl_def(ast::def_fn(did, ast::extern_fn)), + UnsafeStaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::unsafe_fn)) + } + StaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::impure_fn)) + } + PureStaticMethod => { + let trait_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_static_method(did, trait_did, ast::pure_fn)) + } + Type | ForeignType => dl_def(ast::def_ty(did)), + Mod => dl_def(ast::def_mod(did)), + ForeignMod => dl_def(ast::def_foreign_mod(did)), + Variant => { + let enum_did = item_reqd_and_translated_parent_item(cnum, item); + dl_def(ast::def_variant(enum_did, did)) + } + Trait | Enum => dl_def(ast::def_ty(did)), + Impl => dl_impl(did), + PublicField | PrivateField | InheritedField => dl_field, } } diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index f188d8ee5d8..63a7ce1ac74 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -794,6 +794,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::Serializer, ebml_w.start_tag(tag_items_data_item); encode_def_id(ebml_w, local_def(ty_m.id)); + encode_parent_item(ebml_w, local_def(item.id)); encode_name(ecx, ebml_w, ty_m.ident); encode_family(ebml_w, purity_static_method_family(ty_m.purity)); diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs index 103f1eecf87..15b20c41b67 100644 --- a/src/rustc/middle/astencode.rs +++ b/src/rustc/middle/astencode.rs @@ -345,8 +345,8 @@ impl ast::def: tr { fn tr(xcx: extended_decode_ctxt) -> ast::def { match self { ast::def_fn(did, p) => { ast::def_fn(did.tr(xcx), p) } - ast::def_static_method(did, p) => { - ast::def_static_method(did.tr(xcx), p) + ast::def_static_method(did, did2, p) => { + ast::def_static_method(did.tr(xcx), did2.tr(xcx), p) } ast::def_self(nid) => { ast::def_self(xcx.tr_id(nid)) } ast::def_mod(did) => { ast::def_mod(did.tr(xcx)) } diff --git a/src/rustc/middle/resolve.rs b/src/rustc/middle/resolve.rs index 18880fe917b..314dea1b576 100644 --- a/src/rustc/middle/resolve.rs +++ b/src/rustc/middle/resolve.rs @@ -1126,6 +1126,7 @@ impl Resolver { self.add_child(ident, new_parent, ~[ValueNS], ty_m.span); let def = def_static_method(local_def(ty_m.id), + local_def(item.id), ty_m.purity); (*method_name_bindings).define_value (Public, def, ty_m.span); diff --git a/src/rustc/middle/trans/callee.rs b/src/rustc/middle/trans/callee.rs index c851c5bc725..aa998fb7b92 100644 --- a/src/rustc/middle/trans/callee.rs +++ b/src/rustc/middle/trans/callee.rs @@ -78,8 +78,9 @@ fn trans(bcx: block, expr: @ast::expr) -> Callee { ast::def_fn(did, _) => { fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id)) } - ast::def_static_method(did, _) => { - fn_callee(bcx, meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, trait_did, _) => { + fn_callee(bcx, meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id)) } ast::def_variant(tid, vid) => { diff --git a/src/rustc/middle/trans/expr.rs b/src/rustc/middle/trans/expr.rs index 4e50f7a848e..c841d9bd913 100644 --- a/src/rustc/middle/trans/expr.rs +++ b/src/rustc/middle/trans/expr.rs @@ -641,10 +641,11 @@ fn trans_def_dps_unadjusted(bcx: block, ref_expr: @ast::expr, let fn_data = callee::trans_fn_ref(bcx, did, ref_expr.id); return fn_data_to_datum(bcx, did, fn_data, lldest); } - ast::def_static_method(did, _) => { - let fn_data = meth::trans_static_method_callee(bcx, did, + ast::def_static_method(impl_did, trait_did, _) => { + let fn_data = meth::trans_static_method_callee(bcx, impl_did, + trait_did, ref_expr.id); - return fn_data_to_datum(bcx, did, fn_data, lldest); + return fn_data_to_datum(bcx, impl_did, fn_data, lldest); } ast::def_variant(tid, vid) => { if ty::enum_variant_with_id(ccx.tcx, tid, vid).args.len() > 0u { diff --git a/src/rustc/middle/trans/meth.rs b/src/rustc/middle/trans/meth.rs index d8a2fda4d14..96cf7fabd1f 100644 --- a/src/rustc/middle/trans/meth.rs +++ b/src/rustc/middle/trans/meth.rs @@ -162,11 +162,50 @@ fn trans_method_callee(bcx: block, callee_id: ast::node_id, fn trans_static_method_callee(bcx: block, method_id: ast::def_id, + trait_id: ast::def_id, callee_id: ast::node_id) -> FnData { let _icx = bcx.insn_ctxt("impl::trans_static_method_callee"); let ccx = bcx.ccx(); + debug!("trans_static_method_callee(method_id=%?, trait_id=%s, \ + callee_id=%?)", + method_id, + ty::item_path_str(bcx.tcx(), trait_id), + callee_id); + let _indenter = indenter(); + + // When we translate a static fn defined in a trait like: + // + // trait<T1...Tn> Trait { + // static fn foo<M1...Mn>(...) {...} + // } + // + // this winds up being translated as something like: + // + // fn foo<T1...Tn,self: Trait<T1...Tn>,M1...Mn>(...) {...} + // + // So when we see a call to this function foo, we have to figure + // out which impl the `Trait<T1...Tn>` bound on the type `self` was + // bound to. Due to the fact that we use a flattened list of + // impls, one per bound, this means we have to total up the bounds + // found on the type parametesr T1...Tn to find the index of the + // one we are interested in. + let bound_index = { + let trait_polyty = ty::lookup_item_type(bcx.tcx(), trait_id); + let mut index = 0; + for trait_polyty.bounds.each |param_bounds| { + for param_bounds.each |param_bound| { + match *param_bound { + ty::bound_trait(_) => { index += 1; } + ty::bound_copy | ty::bound_owned | + ty::bound_send | ty::bound_const => {} + } + } + } + index + }; + let mname = if method_id.crate == ast::local_crate { match bcx.tcx().items.get(method_id.node) { ast_map::node_trait_method(trait_method, _, _) => { @@ -187,9 +226,7 @@ fn trans_static_method_callee(bcx: block, let vtbls = resolve_vtables_in_fn_ctxt( bcx.fcx, ccx.maps.vtable_map.get(callee_id)); - // FIXME(#3446) -- I am pretty sure index 0 is not the right one, - // if the static method is implemented on a generic type. (NDM) - match vtbls[0] { + match vtbls[bound_index] { typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => { let mth_id = method_with_name(bcx.ccx(), impl_did, mname); diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index c1ab29758f2..bf0ca36dddf 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -2403,13 +2403,13 @@ fn ty_param_bounds_and_ty_for_def(fcx: @fn_ctxt, sp: span, defn: ast::def) -> } ast::def_fn(id, ast::unsafe_fn) | - ast::def_static_method(id, ast::unsafe_fn) => { + ast::def_static_method(id, _, ast::unsafe_fn) => { // Unsafe functions can only be touched in an unsafe context fcx.require_unsafe(sp, ~"access to unsafe function"); return ty::lookup_item_type(fcx.ccx.tcx, id); } - ast::def_fn(id, _) | ast::def_static_method(id, _) | + ast::def_fn(id, _) | ast::def_static_method(id, _, _) | ast::def_const(id) | ast::def_variant(_, id) | ast::def_class(id, _) => { return ty::lookup_item_type(fcx.ccx.tcx, id); |
