Deeply normalize when processing registered region obligations
This commit is contained in:
parent
e11a6a9cac
commit
028d29301f
@ -20,6 +20,7 @@
|
||||
};
|
||||
use rustc_middle::ty::{GenericParamDefKind, TyCtxt};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
|
||||
use rustc_trait_selection::traits::{
|
||||
|
@ -8,6 +8,7 @@
|
||||
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_span::Span;
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::{
|
||||
elaborate, normalize_param_env_or_error, outlives_bounds::InferCtxtExt, ObligationCtxt,
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
use rustc_middle::ty::util::CheckRegions;
|
||||
use rustc_middle::ty::GenericArgsRef;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_trait_selection::regions::InferCtxtRegionExt;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
|
||||
use crate::errors;
|
||||
@ -188,6 +189,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
|
||||
RegionResolutionError::UpperBoundUniverseConflict(a, _, _, _, b) => {
|
||||
format!("{b}: {a}", a = ty::Region::new_var(tcx, a))
|
||||
}
|
||||
RegionResolutionError::CannotNormalize(..) => todo!(),
|
||||
};
|
||||
guar = Some(
|
||||
struct_span_code_err!(
|
||||
|
@ -24,6 +24,7 @@
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
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::misc::{
|
||||
type_allowed_to_implement_const_param_ty, ConstParamTyImplementationError,
|
||||
|
@ -518,6 +518,13 @@ pub fn report_region_errors(
|
||||
|
||||
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 @@ fn process_errors(
|
||||
RegionResolutionError::GenericBoundFailure(..) => true,
|
||||
RegionResolutionError::ConcreteFailure(..)
|
||||
| RegionResolutionError::SubSupConflict(..)
|
||||
| RegionResolutionError::UpperBoundUniverseConflict(..) => false,
|
||||
| RegionResolutionError::UpperBoundUniverseConflict(..)
|
||||
| RegionResolutionError::CannotNormalize(..) => false,
|
||||
};
|
||||
|
||||
let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
|
||||
@ -574,6 +582,7 @@ fn process_errors(
|
||||
RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
|
||||
RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(),
|
||||
RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
|
||||
RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(),
|
||||
});
|
||||
errors
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ pub enum RegionResolutionError<'tcx> {
|
||||
SubregionOrigin<'tcx>, // cause of the constraint
|
||||
Region<'tcx>, // the placeholder `'b`
|
||||
),
|
||||
|
||||
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> RegionResolutionError<'tcx> {
|
||||
@ -106,7 +108,8 @@ pub fn origin(&self) -> &SubregionOrigin<'tcx> {
|
||||
RegionResolutionError::ConcreteFailure(origin, _, _)
|
||||
| RegionResolutionError::GenericBoundFailure(origin, _, _)
|
||||
| RegionResolutionError::SubSupConflict(_, _, origin, _, _, _, _)
|
||||
| RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _) => origin,
|
||||
| RegionResolutionError::UpperBoundUniverseConflict(_, _, _, origin, _)
|
||||
| RegionResolutionError::CannotNormalize(_, origin) => origin,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
use crate::infer::free_regions::RegionRelations;
|
||||
use crate::infer::lexical_region_resolve;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
pub mod components;
|
||||
pub mod env;
|
||||
@ -41,12 +41,22 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// result. After this, no more unification operations should be
|
||||
/// done -- or the compiler will panic -- but it is legal to use
|
||||
/// `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]
|
||||
pub fn resolve_regions(
|
||||
pub fn resolve_regions_with_normalize(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
deeply_normalize_ty: impl Fn(Ty<'tcx>) -> Result<Ty<'tcx>, Ty<'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 mut inner = self.inner.borrow_mut();
|
||||
|
@ -123,15 +123,19 @@ pub fn take_registered_region_obligations(&self) -> Vec<RegionObligation<'tcx>>
|
||||
/// flow of the inferencer. The key point is that it is
|
||||
/// invoked after all type-inference variables have been bound --
|
||||
/// right before lexical region resolution.
|
||||
#[instrument(level = "debug", skip(self, outlives_env))]
|
||||
pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvironment<'tcx>) {
|
||||
#[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
|
||||
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");
|
||||
|
||||
let my_region_obligations = self.take_registered_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);
|
||||
let sup_type = self.resolve_vars_if_possible(sup_type);
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
@ -143,6 +147,8 @@ pub fn process_registered_region_obligations(&self, outlives_env: &OutlivesEnvir
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@
|
||||
|
||||
pub mod errors;
|
||||
pub mod infer;
|
||||
pub mod regions;
|
||||
pub mod solve;
|
||||
pub mod traits;
|
||||
|
||||
|
37
compiler/rustc_trait_selection/src/regions.rs
Normal file
37
compiler/rustc_trait_selection/src/regions.rs
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -179,7 +179,7 @@ pub fn find_auto_trait_generics<A>(
|
||||
}
|
||||
|
||||
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 =
|
||||
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
use crate::infer::outlives::env::OutlivesEnvironment;
|
||||
use crate::infer::InferOk;
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor};
|
||||
use crate::solve::{deeply_normalize_for_diagnostics, inspect};
|
||||
use crate::traits::engine::TraitEngineExt;
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
use super::FulfillmentContext;
|
||||
use super::TraitEngine;
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
use crate::solve::FulfillmentCtxt as NextFulfillmentCtxt;
|
||||
use crate::traits::error_reporting::TypeErrCtxtExt;
|
||||
use crate::traits::NormalizeExt;
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Miscellaneous type-system utilities that are too small to deserve their own modules.
|
||||
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
use crate::traits::{self, ObligationCause, ObligationCtxt};
|
||||
|
||||
use hir::LangItem;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
use crate::infer::outlives::env::OutlivesEnvironment;
|
||||
use crate::infer::{InferCtxt, TyCtxtInferExt};
|
||||
use crate::regions::InferCtxtRegionExt;
|
||||
use crate::traits::error_reporting::TypeErrCtxtExt as _;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// compile-flags: -Znext-solver
|
||||
//~^ ERROR cannot normalize `<T as Default>::Id`
|
||||
|
||||
#![feature(specialization)]
|
||||
//~^ WARN the feature `specialization` is incomplete
|
||||
|
@ -1,5 +1,5 @@
|
||||
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)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -8,12 +8,14 @@ LL | #![feature(specialization)]
|
||||
= help: consider using `min_specialization` instead, which is more stable and complete
|
||||
= note: `#[warn(incomplete_features)]` on by default
|
||||
|
||||
error: cannot normalize `<T as Default>::Id`
|
||||
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/specialization-transmute.rs:13:23
|
||||
--> $DIR/specialization-transmute.rs:14:23
|
||||
|
|
||||
LL | default type Id = T;
|
||||
| ^ 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`.
|
||||
|
Loading…
Reference in New Issue
Block a user