about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs25
2 files changed, 23 insertions, 6 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index c7bf1f2a943..4312cc94682 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -144,7 +144,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // Instead, we select the right impl now but report "`Bar` does
         // not implement `Clone`".
         if candidates.len() == 1 {
-            return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
+            return self.filter_impls(candidates.pop().unwrap(), stack.obligation);
         }
 
         // Winnow, but record the exact outcome of evaluation, which
@@ -217,7 +217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
 
         // Just one candidate left.
-        self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
+        self.filter_impls(candidates.pop().unwrap().candidate, stack.obligation)
     }
 
     pub(super) fn assemble_candidates<'o>(
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 1aa4bc0a412..f334452a791 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -1015,13 +1015,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         (result, dep_node)
     }
 
-    // Treat negative impls as unimplemented, and reservation impls as ambiguity.
-    fn filter_negative_and_reservation_impls(
+    fn filter_impls(
         &mut self,
         candidate: SelectionCandidate<'tcx>,
+        obligation: &TraitObligation<'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
+        let tcx = self.tcx();
+        // Respect const trait obligations
+        if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
+            match candidate {
+                // const impl
+                ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {}
+                // const param
+                ParamCandidate(ty::ConstnessAnd { constness: hir::Constness::Const, .. }) => {}
+                // auto trait impl
+                AutoImplCandidate(..) => {}
+                // FIXME check if this is right, but this would allow Sized impls
+                BuiltinCandidate { .. } => {}
+                _ => { // reject all other types of candidates
+                    return Err(Unimplemented)
+                }
+            }
+        }
+        // Treat negative impls as unimplemented, and reservation impls as ambiguity.
         if let ImplCandidate(def_id) = candidate {
-            let tcx = self.tcx();
             match tcx.impl_polarity(def_id) {
                 ty::ImplPolarity::Negative if !self.allow_negative_impls => {
                     return Err(Unimplemented);
@@ -1035,7 +1052,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         let value = attr.and_then(|a| a.value_str());
                         if let Some(value) = value {
                             debug!(
-                                "filter_negative_and_reservation_impls: \
+                                "filter_impls: \
                                  reservation impl ambiguity on {:?}",
                                 def_id
                             );