Skip to content

Commit d06b705

Browse files
committed
Fix a bug with cross-crate trait impls
Closes rust-lang#19056
1 parent 10d99a9 commit d06b705

File tree

6 files changed

+50
-18
lines changed

6 files changed

+50
-18
lines changed

src/librustc/metadata/decoder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1272,9 +1272,9 @@ pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
12721272
}
12731273

12741274
pub fn each_implementation_for_type<F>(cdata: Cmd,
1275-
id: ast::NodeId,
1276-
mut callback: F) where
1277-
F: FnMut(ast::DefId),
1275+
id: ast::NodeId,
1276+
mut callback: F)
1277+
where F: FnMut(ast::DefId),
12781278
{
12791279
let item_doc = lookup_item(id, cdata.data());
12801280
reader::tagged_docs(item_doc,

src/librustc/metadata/encoder.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,8 +1222,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
12221222
encode_attributes(rbml_w, item.attrs[]);
12231223
encode_unsafety(rbml_w, unsafety);
12241224
match ty.node {
1225-
ast::TyPath(ref path, _) if path.segments
1226-
.len() == 1 => {
1225+
ast::TyPath(ref path, _) if path.segments.len() == 1 => {
12271226
let ident = path.segments.last().unwrap().identifier;
12281227
encode_impl_type_basename(rbml_w, ident);
12291228
}
@@ -1351,6 +1350,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
13511350
// Encode the implementations of this trait.
13521351
encode_extension_implementations(ecx, rbml_w, def_id);
13531352

1353+
// Encode inherent implementations for this trait.
1354+
encode_inherent_implementations(ecx, rbml_w, def_id);
1355+
13541356
rbml_w.end_tag();
13551357

13561358
// Now output the trait item info for each trait item.
@@ -1452,9 +1454,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
14521454

14531455
rbml_w.end_tag();
14541456
}
1455-
1456-
// Encode inherent implementations for this trait.
1457-
encode_inherent_implementations(ecx, rbml_w, def_id);
14581457
}
14591458
ast::ItemMac(..) => {
14601459
// macros are encoded separately

src/librustc/middle/ty.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ impl ImplOrTraitItemContainer {
128128
}
129129
}
130130

131-
#[deriving(Clone)]
131+
#[deriving(Clone, Show)]
132132
pub enum ImplOrTraitItem<'tcx> {
133133
MethodTraitItem(Rc<Method<'tcx>>),
134134
TypeTraitItem(Rc<AssociatedType>),
@@ -173,7 +173,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
173173
}
174174
}
175175

176-
#[deriving(Clone, Copy)]
176+
#[deriving(Clone, Copy, Show)]
177177
pub enum ImplOrTraitItemId {
178178
MethodTraitItemId(ast::DefId),
179179
TypeTraitItemId(ast::DefId),
@@ -232,7 +232,7 @@ impl<'tcx> Method<'tcx> {
232232
}
233233
}
234234

235-
#[deriving(Clone, Copy)]
235+
#[deriving(Clone, Copy, Show)]
236236
pub struct AssociatedType {
237237
pub name: ast::Name,
238238
pub vis: ast::Visibility,
@@ -4931,10 +4931,11 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
49314931
}
49324932
}
49334933

4934-
/// Helper for looking things up in the various maps that are populated during typeck::collect
4935-
/// (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share the pattern that if the
4936-
/// id is local, it should have been loaded into the map by the `typeck::collect` phase. If the
4937-
/// def-id is external, then we have to go consult the crate loading code (and cache the result for
4934+
/// Helper for looking things up in the various maps that are populated during
4935+
/// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of
4936+
/// these share the pattern that if the id is local, it should have been loaded
4937+
/// into the map by the `typeck::collect` phase. If the def-id is external,
4938+
/// then we have to go consult the crate loading code (and cache the result for
49384939
/// the future).
49394940
fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
49404941
def_id: ast::DefId,
@@ -5973,11 +5974,12 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
59735974
return
59745975
}
59755976

5977+
debug!("populate_implementations_for_type_if_necessary: searching for {}", type_id);
5978+
59765979
let mut inherent_impls = Vec::new();
59775980
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
59785981
|impl_def_id| {
5979-
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
5980-
impl_def_id);
5982+
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
59815983

59825984
// Record the trait->implementation mappings, if applicable.
59835985
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);

src/librustc_typeck/check/method/probe.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
267267
return; // already visited
268268
}
269269

270+
debug!("assemble_inherent_impl_probe {}", impl_def_id);
271+
270272
let method = match impl_method(self.tcx(), impl_def_id, self.method_name) {
271273
Some(m) => m,
272274
None => { return; } // No method with correct name on this impl
@@ -432,7 +434,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
432434
}
433435

434436
fn assemble_extension_candidates_for_trait(&mut self,
435-
trait_def_id: ast::DefId) {
437+
trait_def_id: ast::DefId) {
436438
debug!("assemble_extension_candidates_for_trait: trait_def_id={}",
437439
trait_def_id.repr(self.tcx()));
438440

@@ -983,6 +985,7 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
983985
-> Option<(uint, Rc<ty::Method<'tcx>>)>
984986
{
985987
let trait_items = ty::trait_items(tcx, trait_def_id);
988+
debug!("trait_method; items: {}", trait_items);
986989
trait_items
987990
.iter()
988991
.filter(|item|

src/test/auxiliary/traitimpl.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test inherant trait impls work cross-crait.
12+
13+
pub trait Bar<'a> for ?Sized : 'a {}
14+
15+
impl<'a> Bar<'a> {
16+
pub fn bar(&self) {}
17+
}

src/test/run-pass/trait-impl.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

1111
// Test calling methods on an impl for a bare trait.
1212

13+
// aux-build:traitimpl.rs
14+
extern crate traitimpl;
15+
use traitimpl::Bar;
16+
1317
static mut COUNT: uint = 1;
1418

1519
trait T {}
@@ -25,6 +29,9 @@ impl<'a> T+'a {
2529

2630
impl T for int {}
2731

32+
struct Foo;
33+
impl<'a> Bar<'a> for Foo {}
34+
2835
fn main() {
2936
let x: &T = &42i;
3037

@@ -33,4 +40,8 @@ fn main() {
3340
T::bar();
3441

3542
unsafe { assert!(COUNT == 12); }
43+
44+
// Cross-crait case
45+
let x: &Bar = &Foo;
46+
x.bar();
3647
}

0 commit comments

Comments
 (0)