Skip to content

Commit

Permalink
Auto merge of rust-lang#135969 - compiler-errors:normalize-erasing-re…
Browse files Browse the repository at this point in the history
…gions, r=<try>

Rewrite `normalize_erasing_regions` to not use `QueryNormalizer`

r? `@ghost`
  • Loading branch information
bors committed Jan 24, 2025
2 parents 22a220a + 6d70fcc commit 8c6c13e
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 68 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/ty/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ impl<'tcx> TyCtxt<'tcx> {
value,
typing_env,
);
debug_assert!(
!value.has_escaping_bound_vars(),
"{value:?} cannot be normalized with escaping bound vars"
);

// Erase first before we do the real query -- this keeps the
// cache from being too polluted.
Expand Down
120 changes: 78 additions & 42 deletions compiler/rustc_traits/src/normalize_erasing_regions.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::ScrubbedTraitError;
use rustc_middle::bug;
use rustc_middle::query::Providers;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, PseudoCanonicalInput, TyCtxt, TypeFoldable, TypeVisitableExt};
use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt;
use rustc_trait_selection::traits::{Normalized, ObligationCause};
use rustc_middle::ty::{
self, PseudoCanonicalInput, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, TypingMode,
};
use rustc_span::DUMMY_SP;
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::error_reporting::traits::OverflowCause;
use rustc_trait_selection::traits::{self, ObligationCause, ObligationCtxt};
use tracing::debug;

pub(crate) fn provide(p: &mut Providers) {
Expand All @@ -17,54 +24,83 @@ pub(crate) fn provide(p: &mut Providers) {
};
}

// FIXME(-Znext-solver): This can be simplified further to just a `deeply_normalize` call.
fn try_normalize_after_erasing_regions<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + PartialEq + Copy>(
tcx: TyCtxt<'tcx>,
goal: PseudoCanonicalInput<'tcx, T>,
) -> Result<T, NoSolution> {
let PseudoCanonicalInput { typing_env, value } = goal;
let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
let cause = ObligationCause::dummy();
match infcx.at(&cause, param_env).query_normalize(value) {
Ok(Normalized { value: normalized_value, obligations: normalized_obligations }) => {
// We don't care about the `obligations`; they are
// always only region relations, and we are about to
// erase those anyway:
// This has been seen to fail in RL, so making it a non-debug assertion to better catch
// those cases.
assert_eq!(
normalized_obligations.iter().find(|p| not_outlives_predicate(p.predicate)),
None,
);
let ocx = ObligationCtxt::new(&infcx);
let mut normalized =
ocx.deeply_normalize(&ObligationCause::dummy(), param_env, value).map_err(|errors| {
match infcx.typing_mode() {
TypingMode::PostAnalysis => {
for error in errors {
match error {
ScrubbedTraitError::Cycle(pred) => {
infcx.err_ctxt().report_overflow_error(
OverflowCause::TraitSolver(pred.first().unwrap().predicate),
DUMMY_SP,
false,
|_| {},
);
}
_ => {}
}
}
}
_ => {}
}

let resolved_value = infcx.resolve_vars_if_possible(normalized_value);
// It's unclear when `resolve_vars` would have an effect in a
// fresh `InferCtxt`. If this assert does trigger, it will give
// us a test case.
debug_assert_eq!(normalized_value, resolved_value);
let erased = infcx.tcx.erase_regions(resolved_value);
debug_assert!(!erased.has_infer(), "{erased:?}");
Ok(erased)
}
Err(NoSolution) => Err(NoSolution),
// Otherwise, bail with `NoSolution`
NoSolution
})?;

if tcx.features().generic_const_exprs() {
normalized =
normalized.fold_with(&mut FoldConsts { ocx: &ocx, param_env, universes: vec![] });
}

let resolved = infcx.resolve_vars_if_possible(normalized);
let erased = tcx.erase_regions(resolved);

if erased.has_non_region_infer() {
bug!("encountered infer when normalizing {value:?} to {erased:?}");
}

Ok(erased)
}

fn not_outlives_predicate(p: ty::Predicate<'_>) -> bool {
match p.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..)) => false,
ty::PredicateKind::Clause(ty::ClauseKind::Trait(..))
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(..))
| ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::NormalizesTo(..)
| ty::PredicateKind::AliasRelate(..)
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
| ty::PredicateKind::DynCompatible(..)
| ty::PredicateKind::Subtype(..)
| ty::PredicateKind::Coerce(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous => true,
struct FoldConsts<'a, 'tcx> {
ocx: &'a ObligationCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>,
universes: Vec<Option<ty::UniverseIndex>>,
}

impl<'tcx> TypeFolder<TyCtxt<'tcx>> for FoldConsts<'_, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.ocx.infcx.tcx
}

fn fold_binder<T>(&mut self, binder: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.universes.push(None);
let binder = binder.super_fold_with(self);
self.universes.pop();
binder
}

fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
let ct = traits::with_replaced_escaping_bound_vars(
self.ocx.infcx,
&mut self.universes,
ct,
|constant| traits::evaluate_const(self.ocx.infcx, constant, self.param_env),
);
debug!(?ct, ?self.param_env);
ct.super_fold_with(self)
}
}
20 changes: 0 additions & 20 deletions tests/crashes/125801.rs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//~ ERROR overflow normalizing the opaque type
#![feature(type_alias_impl_trait)]

type T = impl Copy;
//~^ ERROR cannot resolve opaque type

static STATIC: T = None::<&'static T>;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
error[E0720]: cannot resolve opaque type
--> $DIR/infinite-cycle-involving-weak.rs:3:10
error[E0275]: overflow normalizing the opaque type `T::{opaque#0}`
|
LL | type T = impl Copy;
| ^^^^^^^^^ cannot resolve opaque type
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_cycle_involving_weak`)

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0720`.
For more information about this error, try `rustc --explain E0275`.

0 comments on commit 8c6c13e

Please sign in to comment.