auto merge of #19011 : ricky26/rust/trait_supertraits, r=nikomatsakis

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.
This commit is contained in:
bors 2014-11-25 22:36:59 +00:00
commit eedfc07796
2 changed files with 50 additions and 1 deletions

View file

@ -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)
@ -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)
}
}

View file

@ -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>();
}