Skip to content

Commit eedfc07

Browse files
committed
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.
2 parents 689ef2d + 729bf44 commit eedfc07

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/librustc/middle/traits/select.rs

+18-1
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13271327
}
13281328
}
13291329

1330-
ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
1330+
ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => {
13311331
match bound {
13321332
ty::BoundSized => {
13331333
Err(Unimplemented)
@@ -1336,6 +1336,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
13361336
if bounds.builtin_bounds.contains(&bound) {
13371337
Ok(If(Vec::new()))
13381338
} else {
1339+
// Recursively check all supertraits to find out if any further
1340+
// bounds are required and thus we must fulfill.
1341+
// We have to create a temp trait ref here since TyTraits don't
1342+
// have actual self type info (which is required for the
1343+
// supertraits iterator).
1344+
let tmp_tr = Rc::new(ty::TraitRef {
1345+
def_id: principal.def_id,
1346+
substs: principal.substs.with_self_ty(ty::mk_err())
1347+
});
1348+
for tr in util::supertraits(self.tcx(), tmp_tr) {
1349+
let td = ty::lookup_trait_def(self.tcx(), tr.def_id);
1350+
1351+
if td.bounds.builtin_bounds.contains(&bound) {
1352+
return Ok(If(Vec::new()))
1353+
}
1354+
}
1355+
13391356
Err(Unimplemented)
13401357
}
13411358
}

src/test/run-pass/issue-15155.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2012 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+
trait TraitWithSend: Send {}
12+
trait IndirectTraitWithSend: TraitWithSend {}
13+
14+
// Check struct instantiation (Box<TraitWithSend> will only have Send if TraitWithSend has Send)
15+
#[allow(dead_code)]
16+
struct Blah { x: Box<TraitWithSend> }
17+
impl TraitWithSend for Blah {}
18+
19+
// Struct instantiation 2-levels deep
20+
#[allow(dead_code)]
21+
struct IndirectBlah { x: Box<IndirectTraitWithSend> }
22+
impl TraitWithSend for IndirectBlah {}
23+
impl IndirectTraitWithSend for IndirectBlah {}
24+
25+
fn test_trait<Sized? T: Send>() { println!("got here!") }
26+
27+
fn main() {
28+
test_trait::<TraitWithSend>();
29+
test_trait::<IndirectTraitWithSend>();
30+
}
31+
32+

0 commit comments

Comments
 (0)