about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/mod.rs4
-rw-r--r--src/librustc/traits/select.rs31
-rw-r--r--src/librustc/ty/trait_def.rs12
-rw-r--r--src/librustc_typeck/check/mod.rs18
-rw-r--r--src/librustc_typeck/check/wfcheck.rs12
-rw-r--r--src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs18
6 files changed, 64 insertions, 31 deletions
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 07c5b319970..a2d5af67516 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -181,6 +181,9 @@ 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<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
@@ -452,6 +455,7 @@ 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 4ed25646d43..b58a154275c 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1296,6 +1296,12 @@ 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
     }
@@ -1714,18 +1720,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             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(_) => { }
-                    }
-                });
+                    });
+                }
             }
         );
 
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 33972df97fb..0fbf9f1bd58 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -92,16 +92,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                                                    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
@@ -132,13 +126,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         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);
                 }
             }
         }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 4fe2f5b574e..a622f0b6732 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1745,6 +1745,8 @@ 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,
@@ -1763,6 +1765,22 @@ 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/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 78113bdcc0e..3668fc46ddc 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -343,18 +343,8 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> {
                                                   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 => {
diff --git a/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs
new file mode 100644
index 00000000000..5f6844d0c82
--- /dev/null
+++ b/src/test/compile-fail/specialization/defaultimpl/specialization-wfcheck.rs
@@ -0,0 +1,18 @@
+// 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