Skip to content

Commit

Permalink
auto merge of rust-lang#19011 : ricky26/rust/trait_supertraits, r=nik…
Browse files Browse the repository at this point in the history
…omatsakis

It looks like currently kinds required by traits are not propagated when they are wrapped in a TyTrait. Additionally, in SelectionContext::builtin_bound, no attempt is made to check whether the target trait or its supertraits require the kind specified.

This PR alters SelectionContext::builtin_bound to examine all supertraits in the target trait's bounds recursively for required kinds.

Alternatively, the kinds could be added to the TyTrait upon creation (by just setting its builtin_bounds to the union of the bounds requested in this instance and the bounds required by the trait), this option may have less overhead during compilation but information is lost about which kinds were explicitly requested for this instance (vs those specified by traits/supertraits) would be lost.
  • Loading branch information
bors committed Nov 25, 2014
2 parents 689ef2d + 729bf44 commit eedfc07
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
19 changes: 18 additions & 1 deletion src/librustc/middle/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}

ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
match bound {
ty::BoundSized => {
Err(Unimplemented)
Expand All @@ -1336,6 +1336,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if bounds.builtin_bounds.contains(&bound) {
Ok(If(Vec::new()))
} else {
// Recursively check all supertraits to find out if any further
// bounds are required and thus we must fulfill.
// We have to create a temp trait ref here since TyTraits don't
// have actual self type info (which is required for the
// supertraits iterator).
let tmp_tr = Rc::new(ty::TraitRef {
def_id: principal.def_id,
substs: principal.substs.with_self_ty(ty::mk_err())
});
for tr in util::supertraits(self.tcx(), tmp_tr) {
let td = ty::lookup_trait_def(self.tcx(), tr.def_id);

if td.bounds.builtin_bounds.contains(&bound) {
return Ok(If(Vec::new()))
}
}

Err(Unimplemented)
}
}
Expand Down
32 changes: 32 additions & 0 deletions src/test/run-pass/issue-15155.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Copyright 2012 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.

trait TraitWithSend: Send {}
trait IndirectTraitWithSend: TraitWithSend {}

// Check struct instantiation (Box<TraitWithSend> will only have Send if TraitWithSend has Send)
#[allow(dead_code)]
struct Blah { x: Box<TraitWithSend> }
impl TraitWithSend for Blah {}

// Struct instantiation 2-levels deep
#[allow(dead_code)]
struct IndirectBlah { x: Box<IndirectTraitWithSend> }
impl TraitWithSend for IndirectBlah {}
impl IndirectTraitWithSend for IndirectBlah {}

fn test_trait<Sized? T: Send>() { println!("got here!") }

fn main() {
test_trait::<TraitWithSend>();
test_trait::<IndirectTraitWithSend>();
}


0 comments on commit eedfc07

Please sign in to comment.