Skip to content

Commit cae1898

Browse files
committed
Filter non-const impls when we expect a const one
1 parent 8350528 commit cae1898

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
144144
// Instead, we select the right impl now but report "`Bar` does
145145
// not implement `Clone`".
146146
if candidates.len() == 1 {
147-
return self.filter_negative_and_reservation_impls(candidates.pop().unwrap());
147+
return self.filter_impls(candidates.pop().unwrap(), stack.obligation);
148148
}
149149

150150
// Winnow, but record the exact outcome of evaluation, which
@@ -217,7 +217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
217217
}
218218

219219
// Just one candidate left.
220-
self.filter_negative_and_reservation_impls(candidates.pop().unwrap().candidate)
220+
self.filter_impls(candidates.pop().unwrap().candidate, stack.obligation)
221221
}
222222

223223
pub(super) fn assemble_candidates<'o>(

compiler/rustc_trait_selection/src/traits/select/mod.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,13 +1015,30 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10151015
(result, dep_node)
10161016
}
10171017

1018-
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
1019-
fn filter_negative_and_reservation_impls(
1018+
fn filter_impls(
10201019
&mut self,
10211020
candidate: SelectionCandidate<'tcx>,
1021+
obligation: &TraitObligation<'tcx>,
10221022
) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
1023+
let tcx = self.tcx();
1024+
// Respect const trait obligations
1025+
if let hir::Constness::Const = obligation.predicate.skip_binder().constness {
1026+
match candidate {
1027+
// const impl
1028+
ImplCandidate(def_id) if tcx.impl_constness(def_id) == hir::Constness::Const => {}
1029+
// const param
1030+
ParamCandidate(ty::ConstnessAnd { constness: hir::Constness::Const, .. }) => {}
1031+
// auto trait impl
1032+
AutoImplCandidate(..) => {}
1033+
// FIXME check if this is right, but this would allow Sized impls
1034+
BuiltinCandidate { .. } => {}
1035+
_ => { // reject all other types of candidates
1036+
return Err(Unimplemented)
1037+
}
1038+
}
1039+
}
1040+
// Treat negative impls as unimplemented, and reservation impls as ambiguity.
10231041
if let ImplCandidate(def_id) = candidate {
1024-
let tcx = self.tcx();
10251042
match tcx.impl_polarity(def_id) {
10261043
ty::ImplPolarity::Negative if !self.allow_negative_impls => {
10271044
return Err(Unimplemented);
@@ -1035,7 +1052,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
10351052
let value = attr.and_then(|a| a.value_str());
10361053
if let Some(value) = value {
10371054
debug!(
1038-
"filter_negative_and_reservation_impls: \
1055+
"filter_impls: \
10391056
reservation impl ambiguity on {:?}",
10401057
def_id
10411058
);

0 commit comments

Comments
 (0)