From a02a982ffc73457caa1849b09da63e84f78541c6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 25 Jan 2025 21:27:06 +0000 Subject: [PATCH] Make DeeplyNormalize a real type op --- .../src/type_check/constraint_conversion.rs | 21 +------ .../src/type_check/free_region_relations.rs | 21 ++----- compiler/rustc_middle/src/traits/query.rs | 7 +++ .../src/traits/query/type_op/normalize.rs | 58 ++++++++++++++++++- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 4b7f53213886..3b48ca305c45 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -4,15 +4,12 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; +use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::bug; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::traits::ObligationCause; -use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::Span; -use rustc_trait_selection::traits::ScrubbedTraitError; -use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput}; use tracing::{debug, instrument}; @@ -270,20 +267,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { ConstraintCategory<'tcx>, )>, ) -> Ty<'tcx> { - let result = CustomTypeOp::new( - |ocx| { - ocx.deeply_normalize( - &ObligationCause::dummy_with_span(self.span), - self.param_env, - ty, - ) - .map_err(|_: Vec>| NoSolution) - }, - "normalize type outlives obligation", - ) - .fully_perform(self.infcx, self.span); - - match result { + match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span) + { Ok(TypeOpOutput { output: ty, constraints, .. }) => { if let Some(QueryRegionConstraints { outlives }) = constraints { next_outlives_predicates.extend(outlives.iter().copied()); diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index edf612f4e97a..2bac084c9643 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -5,14 +5,11 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::{InferCtxt, outlives}; -use rustc_infer::traits::ScrubbedTraitError; +use rustc_infer::traits::query::type_op::DeeplyNormalize; use rustc_middle::mir::ConstraintCategory; -use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::OutlivesBound; use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, Span}; -use rustc_trait_selection::solve::NoSolution; -use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use tracing::{debug, instrument}; use type_op::TypeOpOutput; @@ -360,18 +357,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { output: normalized_outlives, constraints: constraints_normalize, error_info: _, - }) = CustomTypeOp::new( - |ocx| { - ocx.deeply_normalize( - &ObligationCause::dummy_with_span(span), - self.param_env, - outlives, - ) - .map_err(|_: Vec>| NoSolution) - }, - "normalize type outlives obligation", - ) - .fully_perform(self.infcx, span) + }) = self + .param_env + .and(DeeplyNormalize { value: outlives }) + .fully_perform(self.infcx, span) else { self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}")); return; diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 8cd04a6f5e40..5b19d1742cd4 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -41,11 +41,18 @@ pub mod type_op { pub predicate: Predicate<'tcx>, } + /// Normalizes, but not in the new solver. #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct Normalize { pub value: T, } + /// Normalizes, and deeply normalizes in the new solver. + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] + pub struct DeeplyNormalize { + pub value: T, + } + #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)] pub struct ImpliedOutlivesBounds<'tcx> { pub ty: Ty<'tcx>, diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs index e8c2528aa6ee..2f6bbd7f4cf4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_middle::traits::ObligationCause; use rustc_middle::traits::query::NoSolution; -pub use rustc_middle::traits::query::type_op::Normalize; +pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::Span; @@ -27,13 +27,54 @@ where T::type_op_method(tcx, canonicalized) } + fn perform_locally_with_next_solver( + _ocx: &ObligationCtxt<'_, 'tcx>, + key: ParamEnvAnd<'tcx, Self>, + _span: Span, + ) -> Result { + Ok(key.value.value) + } +} + +impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize +where + T: Normalizable<'tcx> + 'tcx, +{ + type QueryResponse = T; + + fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option { + if !key.value.value.has_aliases() { Some(key.value.value) } else { None } + } + + fn perform_query( + tcx: TyCtxt<'tcx>, + canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>, + ) -> Result, NoSolution> { + T::type_op_method( + tcx, + CanonicalQueryInput { + typing_mode: canonicalized.typing_mode, + canonical: canonicalized.canonical.unchecked_map( + |ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd { + param_env, + value: Normalize { value: value.value }, + }, + ), + }, + ) + } + fn perform_locally_with_next_solver( ocx: &ObligationCtxt<'_, 'tcx>, key: ParamEnvAnd<'tcx, Self>, span: Span, ) -> Result { - // FIXME(-Znext-solver): shouldn't be using old normalizer - Ok(ocx.normalize(&ObligationCause::dummy_with_span(span), key.param_env, key.value.value)) + ocx.deeply_normalize( + &ObligationCause::dummy_with_span(span), + key.param_env, + key.value.value, + ) + .map_err(|_| NoSolution) } } @@ -81,3 +122,14 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> { tcx.type_op_normalize_fn_sig(canonicalized) } } + +/// This impl is not needed, since we never normalize type outlives predicates +/// in the old solver, but is required by trait bounds to be happy. +impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> { + fn type_op_method( + _tcx: TyCtxt<'tcx>, + _canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize>>, + ) -> Result, NoSolution> { + unreachable!("we never normalize PolyTypeOutlivesPredicate") + } +}