Skip to content

Commit 2f22a92

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

File tree

9 files changed

+49
-35
lines changed

9 files changed

+49
-35
lines changed

src/librustc/infer/mod.rs

-4
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
181181
// obligations within. This is expected to be done 'late enough'
182182
// that all type inference variables have been bound and so forth.
183183
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
184-
185-
// true if trait selection in this context should emit `default impl` candiates
186-
pub emit_defaul_impl_candidates: Cell<bool>,
187184
}
188185

189186
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
@@ -455,7 +452,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
455452
err_count_on_creation: tcx.sess.err_count(),
456453
in_snapshot: Cell::new(false),
457454
region_obligations: RefCell::new(vec![]),
458-
emit_defaul_impl_candidates: Cell::new(false)
459455
}))
460456
}
461457
}

src/librustc/traits/select.rs

+20-7
Original file line numberDiff line numberDiff line change
@@ -1296,12 +1296,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
12961296
return false;
12971297
}
12981298

1299-
// Using local cache if the infcx can emit `default impls`
1300-
if self.infcx.emit_defaul_impl_candidates.get() {
1301-
return false;
1302-
}
1303-
1304-
13051299
// Otherwise, we can use the global cache.
13061300
true
13071301
}
@@ -1716,11 +1710,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17161710
{
17171711
debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
17181712

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+
17191732
self.tcx().for_each_relevant_impl(
17201733
obligation.predicate.def_id(),
17211734
obligation.predicate.0.trait_ref.self_ty(),
17221735
|impl_def_id| {
1723-
if self.infcx().emit_defaul_impl_candidates.get() ||
1736+
if self_trait_is_present.len() > 0 ||
17241737
!self.tcx().impl_is_default(impl_def_id) {
17251738
self.probe(|this, snapshot| { /* [1] */
17261739
match this.match_impl(impl_def_id, obligation, snapshot) {

src/librustc/ty/instance.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
use hir::def_id::DefId;
1212
use ty::{self, Ty, TypeFoldable, Substs, TyCtxt};
13-
use ty::subst::{Kind, Subst};
13+
use ty::subst::Kind;
1414
use traits;
1515
use syntax::abi::Abi;
1616
use util::ppaux;

src/librustc/ty/mod.rs

+24-1
Original file line numberDiff line numberDiff line change
@@ -2606,8 +2606,31 @@ 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+
}
26092632

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

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

src/librustc_typeck/check/mod.rs

-18
Original file line numberDiff line numberDiff line change
@@ -1745,8 +1745,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
17451745
param_env: ty::ParamEnv<'tcx>,
17461746
body_id: ast::NodeId)
17471747
-> FnCtxt<'a, 'gcx, 'tcx> {
1748-
FnCtxt::set_emit_default_impl_candidates(inh, body_id);
1749-
17501748
FnCtxt {
17511749
body_id,
17521750
param_env,
@@ -1765,22 +1763,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
17651763
}
17661764
}
17671765

1768-
fn set_emit_default_impl_candidates(inh: &'a Inherited<'a, 'gcx, 'tcx>,
1769-
body_id: ast::NodeId) {
1770-
inh.infcx.emit_defaul_impl_candidates.set(
1771-
match inh.tcx.hir.find(body_id) {
1772-
Some(Node::NodeItem(..)) => {
1773-
if inh.tcx.impl_is_default(inh.tcx.hir.local_def_id(body_id)) {
1774-
true
1775-
} else {
1776-
false
1777-
}
1778-
},
1779-
_ => false
1780-
}
1781-
);
1782-
}
1783-
17841766
pub fn sess(&self) -> &Session {
17851767
&self.tcx.sess
17861768
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@ impl Foo for MyStruct {}
2828

2929
fn main() {
3030
println!("{}", MyStruct.foo_one());
31-
}
31+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ default impl<T> Foo for T {
2727
fn main() {
2828
println!("{}", MyStruct.foo_one());
2929
//~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope
30-
}
30+
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ trait Foo<'a, T: Eq + 'a> { }
1515
default impl<U> Foo<'static, U> for () {}
1616
//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
1717

18-
fn main(){}
18+
fn main(){}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,4 @@ impl Foo for MyStruct {
3131

3232
fn main() {
3333
assert!(MyStruct.foo_two() == "generic");
34-
}
34+
}

0 commit comments

Comments
 (0)