Skip to content

Commit 220bb22

Browse files
committed
add Self: Trait<..> inside the param_env of a default impl
1 parent 2f22a92 commit 220bb22

File tree

8 files changed

+51
-62
lines changed

8 files changed

+51
-62
lines changed

src/libcore/iter/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -579,15 +579,15 @@ impl<'a, I, T: 'a> FusedIterator for Cloned<I>
579579
{}
580580

581581
#[doc(hidden)]
582-
default unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
582+
unsafe impl<'a, I, T: 'a> TrustedRandomAccess for Cloned<I>
583583
where I: TrustedRandomAccess<Item=&'a T>, T: Clone
584584
{
585-
unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
585+
default unsafe fn get_unchecked(&mut self, i: usize) -> Self::Item {
586586
self.it.get_unchecked(i).clone()
587587
}
588588

589589
#[inline]
590-
fn may_have_side_effect() -> bool { true }
590+
default fn may_have_side_effect() -> bool { true }
591591
}
592592

593593
#[doc(hidden)]

src/librustc/traits/select.rs

+11-33
Original file line numberDiff line numberDiff line change
@@ -1710,44 +1710,22 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17101710
{
17111711
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
17121712

1713-
// Check if default impls should be emitted.
1714-
// default impls are emitted if the param_env is refered to a default impl.
1715-
// The param_env should contain a Self: Trait<..> predicate in those cases
1716-
let self_trait_is_present:Vec<&ty::Predicate<'tcx>> =
1717-
obligation.param_env
1718-
.caller_bounds
1719-
.iter()
1720-
.filter(|predicate| {
1721-
match **predicate {
1722-
ty::Predicate::Trait(ref trait_predicate) => {
1723-
trait_predicate.def_id() ==
1724-
obligation.predicate.def_id() &&
1725-
obligation.predicate.0.trait_ref.self_ty() ==
1726-
trait_predicate.skip_binder().self_ty()
1727-
}
1728-
_ => false
1729-
}
1730-
}).collect::<Vec<&ty::Predicate<'tcx>>>();
1731-
17321713
self.tcx().for_each_relevant_impl(
17331714
obligation.predicate.def_id(),
17341715
obligation.predicate.0.trait_ref.self_ty(),
17351716
|impl_def_id| {
1736-
if self_trait_is_present.len() > 0 ||
1737-
!self.tcx().impl_is_default(impl_def_id) {
1738-
self.probe(|this, snapshot| { /* [1] */
1739-
match this.match_impl(impl_def_id, obligation, snapshot) {
1740-
Ok(skol_map) => {
1741-
candidates.vec.push(ImplCandidate(impl_def_id));
1742-
1743-
// NB: we can safely drop the skol map
1744-
// since we are in a probe [1]
1745-
mem::drop(skol_map);
1746-
}
1747-
Err(_) => { }
1717+
self.probe(|this, snapshot| { /* [1] */
1718+
match this.match_impl(impl_def_id, obligation, snapshot) {
1719+
Ok(skol_map) => {
1720+
candidates.vec.push(ImplCandidate(impl_def_id));
1721+
1722+
// NB: we can safely drop the skol map
1723+
// since we are in a probe [1]
1724+
mem::drop(skol_map);
17481725
}
1749-
});
1750-
}
1726+
Err(_) => { }
1727+
}
1728+
});
17511729
}
17521730
);
17531731

src/librustc/ty/mod.rs

+1-24
Original file line numberDiff line numberDiff line change
@@ -2606,31 +2606,8 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
26062606
def_id: DefId)
26072607
-> ParamEnv<'tcx> {
26082608
// Compute the bounds on Self and the type parameters.
2609-
let mut predicates = tcx.predicates_of(def_id);
2610-
match tcx.hir.as_local_node_id(def_id)
2611-
.and_then(|node_id| tcx.hir.find(node_id))
2612-
.and_then(|item| {
2613-
match item {
2614-
hir::map::NodeItem(..) => {
2615-
if tcx.impl_is_default(def_id) {
2616-
tcx.impl_trait_ref(def_id)
2617-
} else {
2618-
None
2619-
}
2620-
}
2621-
_ => None
2622-
}
2623-
}) {
2624-
Some(trait_ref) =>
2625-
predicates.predicates
2626-
.push(
2627-
trait_ref.to_poly_trait_ref()
2628-
.to_predicate()
2629-
),
2630-
None => {}
2631-
}
26322609

2633-
let bounds = predicates.instantiate_identity(tcx);
2610+
let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx);
26342611
let predicates = bounds.predicates;
26352612

26362613
// Finally, we have to normalize the bounds in the environment, in

src/librustc_typeck/collect.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -1364,6 +1364,7 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13641364
let node = tcx.hir.get(node_id);
13651365

13661366
let mut is_trait = None;
1367+
let mut is_default_impl_trait = None;
13671368

13681369
let icx = ItemCtxt::new(tcx, def_id);
13691370
let no_generics = hir::Generics::empty();
@@ -1373,8 +1374,13 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
13731374

13741375
NodeItem(item) => {
13751376
match item.node {
1377+
ItemImpl(_, _, defaultness, ref generics, ..) => {
1378+
if defaultness.is_default() {
1379+
is_default_impl_trait = tcx.impl_trait_ref(def_id);
1380+
}
1381+
generics
1382+
}
13761383
ItemFn(.., ref generics, _) |
1377-
ItemImpl(_, _, _, ref generics, ..) |
13781384
ItemTy(_, ref generics) |
13791385
ItemEnum(_, ref generics) |
13801386
ItemStruct(_, ref generics) |
@@ -1446,6 +1452,18 @@ fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
14461452
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
14471453
}
14481454

1455+
// In default impls, we can assume that the self type implements
1456+
// the trait. So in:
1457+
//
1458+
// default impl Foo for Bar { .. }
1459+
//
1460+
// we add a default where clause `Foo: Bar`. We do a similar thing for traits
1461+
// (see below). Recall that a default impl is not itself an impl, but rather a
1462+
// set of defaults that can be incorporated into another impl.
1463+
if let Some(trait_ref) = is_default_impl_trait {
1464+
predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
1465+
}
1466+
14491467
// Collect the region predicates that were declared inline as
14501468
// well. In the case of parameters declared on a fn or method, we
14511469
// have to be careful to only iterate over early-bound regions.

src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Tests that default impls do not have to supply all items but regular impls do.
12+
1113
#![feature(specialization)]
1214

1315
trait Foo {

src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Tests that:
12+
// - default impls do not have to supply all items and
13+
// - a default impl does not count as an impl (in this case, an incomplete default impl).
14+
1115
#![feature(specialization)]
1216

1317
trait Foo {

src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Tests that a default impl still has to have a WF trait ref.
12+
1113
#![feature(specialization)]
1214

1315
trait Foo<'a, T: Eq + 'a> { }

src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,33 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
// Tests that we can combine a default impl that supplies one method with a
12+
// full impl that supplies the other, and they can invoke one another.
13+
1114
#![feature(specialization)]
1215

1316
trait Foo {
1417
fn foo_one(&self) -> &'static str;
1518
fn foo_two(&self) -> &'static str;
19+
fn foo_three(&self) -> &'static str;
1620
}
1721

1822
struct MyStruct;
1923

2024
default impl<T> Foo for T {
2125
fn foo_one(&self) -> &'static str {
22-
"generic"
26+
self.foo_three()
2327
}
2428
}
2529

2630
impl Foo for MyStruct {
2731
fn foo_two(&self) -> &'static str {
2832
self.foo_one()
2933
}
34+
35+
fn foo_three(&self) -> &'static str {
36+
"generic"
37+
}
3038
}
3139

3240
fn main() {

0 commit comments

Comments
 (0)