normalize env constness for nested obligations

This commit is contained in:
Deadbeef 2021-12-25 00:33:23 +08:00
parent 59337cddd4
commit 77297e5f1c
No known key found for this signature in database
GPG Key ID: 6D017A96D8E6C2F9
2 changed files with 47 additions and 0 deletions

View File

@ -8,6 +8,7 @@
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir::lang_items::LangItem;
use rustc_hir::Constness;
use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
@ -51,6 +52,38 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligation: &TraitObligation<'tcx>,
candidate: SelectionCandidate<'tcx>,
) -> Result<Selection<'tcx>, SelectionError<'tcx>> {
let mut obligation = obligation;
let new_obligation;
// HACK(const_trait_impl): the surrounding environment is remapped to a non-const context
// because nested obligations might be actually `~const` then (incorrectly) requiring
// const impls. for example:
// ```
// pub trait Super {}
// pub trait Sub: Super {}
//
// impl<A> const Super for &A where A: ~const Super {}
// impl<A> const Sub for &A where A: ~const Sub {}
// ```
//
// The procedure to check the code above without the remapping code is as follows:
// ```
// CheckWf(impl const Sub for &A where A: ~const Sub) // <- const env
// CheckPredicate(&A: Super)
// CheckPredicate(A: ~const Super) // <- still const env, failure
// ```
if obligation.param_env.constness() == Constness::Const
&& obligation.predicate.skip_binder().constness == ty::BoundConstness::NotConst
{
new_obligation = TraitObligation {
cause: obligation.cause.clone(),
param_env: obligation.param_env.without_const(),
..*obligation
};
obligation = &new_obligation;
}
match candidate {
BuiltinCandidate { has_nested } => {
let data = self.confirm_builtin_candidate(obligation, has_nested);

View File

@ -0,0 +1,14 @@
// Regression test for #92230.
//
// check-pass
#![feature(const_fn_trait_bound)]
#![feature(const_trait_impl)]
pub trait Super {}
pub trait Sub: Super {}
impl<A> const Super for &A where A: ~const Super {}
impl<A> const Sub for &A where A: ~const Sub {}
fn main() {}