Skip to content

Fix a bug with cross-crate trait impls #20385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 2, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,9 +1272,9 @@ pub fn each_impl<F>(cdata: Cmd, mut callback: F) where
}

pub fn each_implementation_for_type<F>(cdata: Cmd,
id: ast::NodeId,
mut callback: F) where
F: FnMut(ast::DefId),
id: ast::NodeId,
mut callback: F)
where F: FnMut(ast::DefId),
{
let item_doc = lookup_item(id, cdata.data());
reader::tagged_docs(item_doc,
Expand Down
9 changes: 4 additions & 5 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1222,8 +1222,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
encode_attributes(rbml_w, item.attrs[]);
encode_unsafety(rbml_w, unsafety);
match ty.node {
ast::TyPath(ref path, _) if path.segments
.len() == 1 => {
ast::TyPath(ref path, _) if path.segments.len() == 1 => {
let ident = path.segments.last().unwrap().identifier;
encode_impl_type_basename(rbml_w, ident);
}
Expand Down Expand Up @@ -1351,6 +1350,9 @@ fn encode_info_for_item(ecx: &EncodeContext,
// Encode the implementations of this trait.
encode_extension_implementations(ecx, rbml_w, def_id);

// Encode inherent implementations for this trait.
encode_inherent_implementations(ecx, rbml_w, def_id);

rbml_w.end_tag();

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

rbml_w.end_tag();
}

// Encode inherent implementations for this trait.
encode_inherent_implementations(ecx, rbml_w, def_id);
}
ast::ItemMac(..) => {
// macros are encoded separately
Expand Down
20 changes: 11 additions & 9 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl ImplOrTraitItemContainer {
}
}

#[deriving(Clone)]
#[deriving(Clone, Show)]
pub enum ImplOrTraitItem<'tcx> {
MethodTraitItem(Rc<Method<'tcx>>),
TypeTraitItem(Rc<AssociatedType>),
Expand Down Expand Up @@ -173,7 +173,7 @@ impl<'tcx> ImplOrTraitItem<'tcx> {
}
}

#[deriving(Clone, Copy)]
#[deriving(Clone, Copy, Show)]
pub enum ImplOrTraitItemId {
MethodTraitItemId(ast::DefId),
TypeTraitItemId(ast::DefId),
Expand Down Expand Up @@ -232,7 +232,7 @@ impl<'tcx> Method<'tcx> {
}
}

#[deriving(Clone, Copy)]
#[deriving(Clone, Copy, Show)]
pub struct AssociatedType {
pub name: ast::Name,
pub vis: ast::Visibility,
Expand Down Expand Up @@ -4931,10 +4931,11 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
}
}

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

debug!("populate_implementations_for_type_if_necessary: searching for {}", type_id);

let mut inherent_impls = Vec::new();
csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
|impl_def_id| {
let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
impl_def_id);
let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);

// Record the trait->implementation mappings, if applicable.
let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_typeck/check/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
return; // already visited
}

debug!("assemble_inherent_impl_probe {}", impl_def_id);

let method = match impl_method(self.tcx(), impl_def_id, self.method_name) {
Some(m) => m,
None => { return; } // No method with correct name on this impl
Expand Down Expand Up @@ -432,7 +434,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
}

fn assemble_extension_candidates_for_trait(&mut self,
trait_def_id: ast::DefId) {
trait_def_id: ast::DefId) {
debug!("assemble_extension_candidates_for_trait: trait_def_id={}",
trait_def_id.repr(self.tcx()));

Expand Down Expand Up @@ -983,6 +985,7 @@ fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-> Option<(uint, Rc<ty::Method<'tcx>>)>
{
let trait_items = ty::trait_items(tcx, trait_def_id);
debug!("trait_method; items: {}", trait_items);
trait_items
.iter()
.filter(|item|
Expand Down
17 changes: 17 additions & 0 deletions src/test/auxiliary/traitimpl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test inherant trait impls work cross-crait.

pub trait Bar<'a> for ?Sized : 'a {}

impl<'a> Bar<'a> {
pub fn bar(&self) {}
}
11 changes: 11 additions & 0 deletions src/test/run-pass/trait-impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

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

// aux-build:traitimpl.rs
extern crate traitimpl;
use traitimpl::Bar;

static mut COUNT: uint = 1;

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

impl T for int {}

struct Foo;
impl<'a> Bar<'a> for Foo {}

fn main() {
let x: &T = &42i;

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

unsafe { assert!(COUNT == 12); }

// Cross-crait case
let x: &Bar = &Foo;
x.bar();
}