1
Fork 0

Deeply normalize when processing registered region obligations

This commit is contained in:
Michael Goulet 2023-12-18 22:45:34 +00:00
parent e11a6a9cac
commit 028d29301f
17 changed files with 90 additions and 12 deletions

View file

@ -20,6 +20,7 @@ use rustc_middle::ty::{
}; };
use rustc_middle::ty::{GenericParamDefKind, TyCtxt}; use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _; use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{

View file

@ -8,6 +8,7 @@ use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
}; };
use rustc_span::Span; use rustc_span::Span;
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{ use rustc_trait_selection::traits::{
elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt, elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
}; };

View file

@ -8,6 +8,7 @@ use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt};
use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::util::CheckRegions;
use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::GenericArgsRef;
use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{self, TyCtxt};
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::{self, ObligationCtxt}; use rustc_trait_selection::traits::{self, ObligationCtxt};
use crate::errors; use crate::errors;
@ -188,6 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => { RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
format!("{b}: {a}", a = ty::Region::new_var(tcx, a)) format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
} }
RegionResolutionError::CannotNormalize(..) => todo!(),
}; };
guar = Some( guar = Some(
struct_span_code_err!( struct_span_code_err!(

View file

@ -24,6 +24,7 @@ use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::symbol::{sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP}; use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_trait_selection::regions::InferCtxtRegionExt;
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::misc::{ use rustc_trait_selection::traits::misc::{
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError, type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,

View file

@ -518,6 +518,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit(); self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
} }
RegionResolutionError::CannotNormalize(ty, origin) => {
self.tcx
.dcx()
.struct_span_err(origin.span(), format!("cannot normalize `{ty}`"))
.emit();
}
} }
} }
} }
@ -559,7 +566,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
RegionResolutionError::GenericBoundFailure(..) => true, RegionResolutionError::GenericBoundFailure(..) => true,
RegionResolutionError::ConcreteFailure(..) RegionResolutionError::ConcreteFailure(..)
| RegionResolutionError::SubSupConflict(..) | RegionResolutionError::SubSupConflict(..)
| RegionResolutionError::UpperBoundUniverseConflict(..) => false, | RegionResolutionError::UpperBoundUniverseConflict(..)
| RegionResolutionError::CannotNormalize(..) => false,
}; };
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
@ -574,6 +582,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(),
}); });
errors errors
} }

View file

@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> {
SubregionOrigin<'tcx>, // cause of the constraint SubregionOrigin<'tcx>, // cause of the constraint
Region<'tcx>, // the placeholder `'b` Region<'tcx>, // the placeholder `'b`
), ),
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
} }
impl<'tcx> RegionResolutionError<'tcx> { impl<'tcx> RegionResolutionError<'tcx> {
@ -106,7 +108,8 @@ impl<'tcx> RegionResolutionError<'tcx> {
RegionResolutionError::ConcreteFailure(origin, _, _) RegionResolutionError::ConcreteFailure(origin, _, _)
| RegionResolutionError::GenericBoundFailure(origin, _, _) | RegionResolutionError::GenericBoundFailure(origin, _, _)
| RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _) | RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _)
| RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin, | RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _)
| RegionResolutionError::CannotNormalize(_, origin) => origin,
} }
} }
} }

View file

@ -5,7 +5,7 @@ use super::{InferCtxt, RegionResolutionError};
use crate::infer::free_regions::RegionRelations; use crate::infer::free_regions::RegionRelations;
use crate::infer::lexical_region_resolve; use crate::infer::lexical_region_resolve;
use rustc_middle::traits::query::OutlivesBound; use rustc_middle::traits::query::OutlivesBound;
use rustc_middle::ty; use rustc_middle::ty::{self, Ty};
pub mod components; pub mod components;
pub mod env; pub mod env;
@ -41,12 +41,22 @@ impl<'tcx> InferCtxt<'tcx> {
/// result. After this, no more unification operations should be /// result. After this, no more unification operations should be
/// done -- or the compiler will panic -- but it is legal to use /// done -- or the compiler will panic -- but it is legal to use
/// `resolve_vars_if_possible` as well as `fully_resolve`. /// `resolve_vars_if_possible` as well as `fully_resolve`.
///
/// If you are in a crate that has access to `rustc_trai_selection`,
/// then it's probably better to use `resolve_regions_normalizing_outlives_obligations`,
/// which knows how to normalize registered region obligations.
#[must_use] #[must_use]
pub fn resolve_regions( pub fn resolve_regions_with_normalize(
&self, &self,
outlives_env: &OutlivesEnvironment<'tcx>, outlives_env: &OutlivesEnvironment<'tcx>,
deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
) -> Vec<RegionResolutionError<'tcx>> { ) -> Vec<RegionResolutionError<'tcx>> {
self.process_registered_region_obligations(outlives_env); match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
Ok(()) => {}
Err((ty, origin)) => {
return vec![RegionResolutionError::CannotNormalize(ty, origin)];
}
};
let (var_infos, data) = { let (var_infos, data) = {
let mut inner = self.inner.borrow_mut(); let mut inner = self.inner.borrow_mut();

View file

@ -123,15 +123,19 @@ impl<'tcx> InferCtxt<'tcx> {
/// flow of the inferencer. The key point is that it is /// flow of the inferencer. The key point is that it is
/// invoked after all type-inference variables have been bound -- /// invoked after all type-inference variables have been bound --
/// right before lexical region resolution. /// right before lexical region resolution.
#[instrument(level = "debug", skip(self, outlives_env))] #[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) { pub fn process_registered_region_obligations<E>(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>) -> Result<Ty<'tcx>, E>,
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot"); assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
let my_region_obligations = self.take_registered_region_obligations(); let my_region_obligations = self.take_registered_region_obligations();
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations { for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
let sup_type = deeply_normalize_ty(sup_type).map_err(|e| (e, origin.clone()))?;
debug!(?sup_type, ?sub_region, ?origin); debug!(?sup_type, ?sub_region, ?origin);
let sup_type = self.resolve_vars_if_possible(sup_type);
let outlives = &mut TypeOutlives::new( let outlives = &mut TypeOutlives::new(
self, self,
@ -143,6 +147,8 @@ impl<'tcx> InferCtxt<'tcx> {
let category = origin.to_constraint_category(); let category = origin.to_constraint_category();
outlives.type_must_outlive(origin, sup_type, sub_region, category); outlives.type_must_outlive(origin, sup_type, sub_region, category);
} }
Ok(())
} }
} }

View file

@ -39,6 +39,7 @@ extern crate smallvec;
pub mod errors; pub mod errors;
pub mod infer; pub mod infer;
pub mod regions;
pub mod solve; pub mod solve;
pub mod traits; pub mod traits;

View file

@ -0,0 +1,37 @@
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
use rustc_middle::traits::ObligationCause;
pub trait InferCtxtRegionExt<'tcx> {
/// Resolve regions, using the deep normalizer to normalize any type-outlives
/// obligations in the process. This is in `rustc_trait_selection` because
/// we need to normalize.
///
/// Prefer this method over `resolve_regions_with_normalize`, unless you are
/// doing something specific for normalization.
fn resolve_regions(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Vec<RegionResolutionError<'tcx>>;
}
impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
fn resolve_regions(
&self,
outlives_env: &OutlivesEnvironment<'tcx>,
) -> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions(outlives_env, |ty| {
let ty = self.resolve_vars_if_possible(ty);
if self.next_trait_solver() {
crate::solve::deeply_normalize(
self.at(&ObligationCause::dummy(), outlives_env.param_env),
ty,
)
.map_err(|_| ty)
} else {
Ok(ty)
}
})
}
}

View file

@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
} }
let outlives_env = OutlivesEnvironment::new(full_env); let outlives_env = OutlivesEnvironment::new(full_env);
infcx.process_registered_region_obligations(&outlives_env); let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty| Ok(ty));
let region_data = let region_data =
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone(); infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();

View file

@ -6,6 +6,7 @@
use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::InferOk; use crate::infer::InferOk;
use crate::regions::InferCtxtRegionExt;
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
use crate::solve::{deeply_normalize_for_diagnostics, inspect}; use crate::solve::{deeply_normalize_for_diagnostics, inspect};
use crate::traits::engine::TraitEngineExt; use crate::traits::engine::TraitEngineExt;

View file

@ -3,6 +3,7 @@ use std::fmt::Debug;
use super::FulfillmentContext; use super::FulfillmentContext;
use super::TraitEngine; use super::TraitEngine;
use crate::regions::InferCtxtRegionExt;
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt; use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
use crate::traits::error_reporting::TypeErrCtxtExt; use crate::traits::error_reporting::TypeErrCtxtExt;
use crate::traits::NormalizeExt; use crate::traits::NormalizeExt;

View file

@ -1,5 +1,6 @@
//! Miscellaneous type-system utilities that are too small to deserve their own modules. //! Miscellaneous type-system utilities that are too small to deserve their own modules.
use crate::regions::InferCtxtRegionExt;
use crate::traits::{self, ObligationCause, ObligationCtxt}; use crate::traits::{self, ObligationCause, ObligationCtxt};
use hir::LangItem; use hir::LangItem;

View file

@ -25,6 +25,7 @@ pub mod wf;
use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::outlives::env::OutlivesEnvironment;
use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::regions::InferCtxtRegionExt;
use crate::traits::error_reporting::TypeErrCtxtExt as _; use crate::traits::error_reporting::TypeErrCtxtExt as _;
use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;

View file

@ -1,4 +1,5 @@
// compile-flags: -Znext-solver // compile-flags: -Znext-solver
//~^ ERROR cannot normalize `<T as Default>::Id`
#![feature(specialization)] #![feature(specialization)]
//~^ WARN the feature `specialization` is incomplete //~^ WARN the feature `specialization` is incomplete

View file

@ -1,5 +1,5 @@
warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/specialization-transmute.rs:3:12 --> $DIR/specialization-transmute.rs:4:12
| |
LL | #![feature(specialization)] LL | #![feature(specialization)]
| ^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^
@ -8,12 +8,14 @@ LL | #![feature(specialization)]
= help: consider using `min_specialization` instead, which is more stable and complete = help: consider using `min_specialization` instead, which is more stable and complete
= note: `#[warn(incomplete_features)]` on by default = note: `#[warn(incomplete_features)]` on by default
error: cannot normalize `<T as Default>::Id`
error[E0282]: type annotations needed error[E0282]: type annotations needed
--> $DIR/specialization-transmute.rs:13:23 --> $DIR/specialization-transmute.rs:14:23
| |
LL | default type Id = T; LL | default type Id = T;
| ^ cannot infer type for associated type `<T as Default>::Id` | ^ cannot infer type for associated type `<T as Default>::Id`
error: aborting due to 1 previous error; 1 warning emitted error: aborting due to 2 previous errors; 1 warning emitted
For more information about this error, try `rustc --explain E0282`. For more information about this error, try `rustc --explain E0282`.