From 2f22a929c6d231d9a9d872ac40b5c9e36daabe38 Mon Sep 17 00:00:00 2001 From: Gianni Ciccarelli Date: Wed, 7 Feb 2018 06:58:01 +0000 Subject: [PATCH] add Self: Trait<..> inside the param_env of a default impl --- src/librustc/infer/mod.rs | 4 --- src/librustc/traits/select.rs | 27 ++++++++++++++----- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 25 ++++++++++++++++- src/librustc_typeck/check/mod.rs | 18 ------------- ...ecialization-trait-item-not-implemented.rs | 2 +- .../specialization-trait-not-implemented.rs | 2 +- .../defaultimpl/specialization-wfcheck.rs | 2 +- ...ecialization-trait-item-not-implemented.rs | 2 +- 9 files changed, 49 insertions(+), 35 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index a2d5af6751602..07c5b319970f8 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -181,9 +181,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { // obligations within. This is expected to be done 'late enough' // that all type inference variables have been bound and so forth. region_obligations: RefCell)>>, - - // true if trait selection in this context should emit `default impl` candiates - pub emit_defaul_impl_candidates: Cell, } /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized @@ -455,7 +452,6 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> { err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), region_obligations: RefCell::new(vec![]), - emit_defaul_impl_candidates: Cell::new(false) })) } } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index b58a154275ca9..aa43bf8ca2eff 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1296,12 +1296,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { return false; } - // Using local cache if the infcx can emit `default impls` - if self.infcx.emit_defaul_impl_candidates.get() { - return false; - } - - // Otherwise, we can use the global cache. true } @@ -1716,11 +1710,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { debug!("assemble_candidates_from_impls(obligation={:?})", obligation); + // Check if default impls should be emitted. + // default impls are emitted if the param_env is refered to a default impl. + // The param_env should contain a Self: Trait<..> predicate in those cases + let self_trait_is_present:Vec<&ty::Predicate<'tcx>> = + obligation.param_env + .caller_bounds + .iter() + .filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref trait_predicate) => { + trait_predicate.def_id() == + obligation.predicate.def_id() && + obligation.predicate.0.trait_ref.self_ty() == + trait_predicate.skip_binder().self_ty() + } + _ => false + } + }).collect::>>(); + self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), obligation.predicate.0.trait_ref.self_ty(), |impl_def_id| { - if self.infcx().emit_defaul_impl_candidates.get() || + if self_trait_is_present.len() > 0 || !self.tcx().impl_is_default(impl_def_id) { self.probe(|this, snapshot| { /* [1] */ match this.match_impl(impl_def_id, obligation, snapshot) { diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 6c727c94f58c5..63bf52a9bdf78 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -10,7 +10,7 @@ use hir::def_id::DefId; use ty::{self, Ty, TypeFoldable, Substs, TyCtxt}; -use ty::subst::{Kind, Subst}; +use ty::subst::Kind; use traits; use syntax::abi::Abi; use util::ppaux; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f52f2ea0f9fc8..52d33c750f864 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2606,8 +2606,31 @@ fn param_env<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ParamEnv<'tcx> { // Compute the bounds on Self and the type parameters. + let mut predicates = tcx.predicates_of(def_id); + match tcx.hir.as_local_node_id(def_id) + .and_then(|node_id| tcx.hir.find(node_id)) + .and_then(|item| { + match item { + hir::map::NodeItem(..) => { + if tcx.impl_is_default(def_id) { + tcx.impl_trait_ref(def_id) + } else { + None + } + } + _ => None + } + }) { + Some(trait_ref) => + predicates.predicates + .push( + trait_ref.to_poly_trait_ref() + .to_predicate() + ), + None => {} + } - let bounds = tcx.predicates_of(def_id).instantiate_identity(tcx); + let bounds = predicates.instantiate_identity(tcx); let predicates = bounds.predicates; // Finally, we have to normalize the bounds in the environment, in diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a622f0b673220..4fe2f5b574e67 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1745,8 +1745,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { param_env: ty::ParamEnv<'tcx>, body_id: ast::NodeId) -> FnCtxt<'a, 'gcx, 'tcx> { - FnCtxt::set_emit_default_impl_candidates(inh, body_id); - FnCtxt { body_id, param_env, @@ -1765,22 +1763,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - fn set_emit_default_impl_candidates(inh: &'a Inherited<'a, 'gcx, 'tcx>, - body_id: ast::NodeId) { - inh.infcx.emit_defaul_impl_candidates.set( - match inh.tcx.hir.find(body_id) { - Some(Node::NodeItem(..)) => { - if inh.tcx.impl_is_default(inh.tcx.hir.local_def_id(body_id)) { - true - } else { - false - } - }, - _ => false - } - ); - } - pub fn sess(&self) -> &Session { &self.tcx.sess } diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs index 323ff7b2db9d3..072507851d795 100644 --- a/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -28,4 +28,4 @@ impl Foo for MyStruct {} fn main() { println!("{}", MyStruct.foo_one()); -} \ No newline at end of file +} diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs index 36945e98b0884..d020a6775772d 100644 --- a/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-trait-not-implemented.rs @@ -27,4 +27,4 @@ default impl Foo for T { fn main() { println!("{}", MyStruct.foo_one()); //~^ ERROR no method named `foo_one` found for type `MyStruct` in the current scope -} \ No newline at end of file +} diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs index 5f6844d0c8289..3422973799282 100644 --- a/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs +++ b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs @@ -15,4 +15,4 @@ trait Foo<'a, T: Eq + 'a> { } default impl Foo<'static, U> for () {} //~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied -fn main(){} \ No newline at end of file +fn main(){} diff --git a/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs index f8eb57bad770b..e11a30214974e 100644 --- a/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs +++ b/src/test/run-pass/specialization/defaultimpl/specialization-trait-item-not-implemented.rs @@ -31,4 +31,4 @@ impl Foo for MyStruct { fn main() { assert!(MyStruct.foo_two() == "generic"); -} \ No newline at end of file +}