diff options
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_trait_selection/src/traits/select/mod.rs | 25 |
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 ); |
