Skip to content

Commit 77297e5

Browse files
committed
normalize env constness for nested obligations
1 parent 59337cd commit 77297e5

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

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

+33
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
99
use rustc_data_structures::stack::ensure_sufficient_stack;
1010
use rustc_hir::lang_items::LangItem;
11+
use rustc_hir::Constness;
1112
use rustc_index::bit_set::GrowableBitSet;
1213
use rustc_infer::infer::InferOk;
1314
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@@ -51,6 +52,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
5152
obligation: &TraitObligation<'tcx>,
5253
candidate: SelectionCandidate<'tcx>,
5354
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
55+
let mut obligation = obligation;
56+
let new_obligation;
57+
58+
// HACK(const_trait_impl): the surrounding environment is remapped to a non-const context
59+
// because nested obligations might be actually `~const` then (incorrectly) requiring
60+
// const impls. for example:
61+
// ```
62+
// pub trait Super {}
63+
// pub trait Sub: Super {}
64+
//
65+
// impl<A> const Super for &A where A: ~const Super {}
66+
// impl<A> const Sub for &A where A: ~const Sub {}
67+
// ```
68+
//
69+
// The procedure to check the code above without the remapping code is as follows:
70+
// ```
71+
// CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env
72+
// CheckPredicate(&A: Super)
73+
// CheckPredicate(A: ~const Super) // <- still const env, failure
74+
// ```
75+
if obligation.param_env.constness() == Constness::Const
76+
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst
77+
{
78+
new_obligation = TraitObligation {
79+
cause: obligation.cause.clone(),
80+
param_env: obligation.param_env.without_const(),
81+
..*obligation
82+
};
83+
84+
obligation = &new_obligation;
85+
}
86+
5487
match candidate {
5588
BuiltinCandidate { has_nested } => {
5689
let data = self.confirm_builtin_candidate(obligation, has_nested);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Regression test for #92230.
2+
//
3+
// check-pass
4+
5+
#![feature(const_fn_trait_bound)]
6+
#![feature(const_trait_impl)]
7+
8+
pub trait Super {}
9+
pub trait Sub: Super {}
10+
11+
impl<A> const Super for &A where A: ~const Super {}
12+
impl<A> const Sub for &A where A: ~const Sub {}
13+
14+
fn main() {}

0 commit comments

Comments
 (0)