// obligations within. This is expected to be done 'late enough'
// that all type inference variables have been bound and so forth.
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
+
+ // true if trait selection in this context should emit `default impl` candiates
+ pub emit_defaul_impl_candidates: Cell<bool>,
}
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
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)
}))
}
}
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
}
obligation.predicate.def_id(),
obligation.predicate.0.trait_ref.self_ty(),
|impl_def_id| {
- self.probe(|this, snapshot| { /* [1] */
- match this.match_impl(impl_def_id, obligation, snapshot) {
- Ok(skol_map) => {
- candidates.vec.push(ImplCandidate(impl_def_id));
-
- // NB: we can safely drop the skol map
- // since we are in a probe [1]
- mem::drop(skol_map);
+ if self.infcx().emit_defaul_impl_candidates.get() ||
+ !self.tcx().impl_is_default(impl_def_id) {
+ self.probe(|this, snapshot| { /* [1] */
+ match this.match_impl(impl_def_id, obligation, snapshot) {
+ Ok(skol_map) => {
+ candidates.vec.push(ImplCandidate(impl_def_id));
+
+ // NB: we can safely drop the skol map
+ // since we are in a probe [1]
+ mem::drop(skol_map);
+ }
+ Err(_) => { }
}
- Err(_) => { }
- }
- });
+ });
+ }
}
);
self_ty: Ty<'tcx>,
mut f: F)
{
- let mut emit_impl = |impl_def_id: DefId| {
- if !self.impl_is_default(impl_def_id) {
- f(impl_def_id);
- }
- };
-
let impls = self.trait_impls_of(def_id);
for &impl_def_id in impls.blanket_impls.iter() {
- emit_impl(impl_def_id);
+ f(impl_def_id);
}
// simplify_type(.., false) basically replaces type parameters and
if let Some(simp) = fast_reject::simplify_type(self, self_ty, true) {
if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls {
- emit_impl(impl_def_id);
+ f(impl_def_id);
}
}
} else {
for v in impls.non_blanket_impls.values() {
for &impl_def_id in v {
- emit_impl(impl_def_id);
+ f(impl_def_id);
}
}
}
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,
}
}
+ 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
}
fcx.body_id,
&trait_ref,
ast_trait_ref.path.span);
-
- // not registering predicates associcated with a `default impl`
- let impl_is_default = fcx.tcx.impl_is_default(item_def_id);
for obligation in obligations {
- let register = match obligation.predicate {
- ty::Predicate::Trait(..) => !impl_is_default,
- _ => true
- };
-
- if register {
- fcx.register_predicate(obligation);
- }
+ fcx.register_predicate(obligation);
}
}
None => {
--- /dev/null
+// Copyright 2015 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.
+
+#![feature(specialization)]
+
+trait Foo<'a, T: Eq + 'a> { }
+
+default impl<U> Foo<'static, U> for () {}
+//~^ ERROR the trait bound `U: std::cmp::Eq` is not satisfied
+
+fn main(){}
\ No newline at end of file