mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #120513 - compiler-errors:normalize-regions-for-nll, r=lcnr
Normalize type outlives obligations in NLL for new solver Normalize the type outlives assumptions and obligations in MIR borrowck. This should fix any of the lazy-norm-related MIR borrowck problems. Also some cleanups from last PR: 1. Normalize obligations in a loop in lexical region resolution 2. Use `deeply_normalize_with_skipped_universes` in lexical resolution since we may have, e.g. `for<'a> Alias<'a>: 'b`. r? lcnr
This commit is contained in:
commit
012ce8ae98
@ -5,10 +5,13 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega
|
||||
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
|
||||
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
|
||||
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
|
||||
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
|
||||
|
||||
use crate::{
|
||||
constraints::OutlivesConstraint,
|
||||
@ -33,6 +36,7 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
|
||||
/// our special inference variable there, we would mess that up.
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
@ -47,6 +51,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
universal_regions: &'a UniversalRegions<'tcx>,
|
||||
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
locations: Locations,
|
||||
span: Span,
|
||||
@ -59,6 +64,7 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
universal_regions,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
locations,
|
||||
span,
|
||||
@ -137,36 +143,68 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
// Extract out various useful fields we'll need below.
|
||||
let ConstraintConversion {
|
||||
tcx,
|
||||
infcx,
|
||||
region_bound_pairs,
|
||||
implicit_region_bound,
|
||||
known_type_outlives_obligations,
|
||||
..
|
||||
} = *self;
|
||||
|
||||
let ty::OutlivesPredicate(k1, r2) = predicate;
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||
let mut outlives_predicates = vec![(predicate, constraint_category)];
|
||||
for iteration in 0.. {
|
||||
if outlives_predicates.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
GenericArgKind::Type(t1) => {
|
||||
// we don't actually use this for anything, but
|
||||
// the `TypeOutlives` code needs an origin.
|
||||
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
Some(implicit_region_bound),
|
||||
known_type_outlives_obligations,
|
||||
)
|
||||
.type_must_outlive(origin, t1, r2, constraint_category);
|
||||
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {outlives_predicates:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => unreachable!(),
|
||||
let mut next_outlives_predicates = vec![];
|
||||
for (ty::OutlivesPredicate(k1, r2), constraint_category) in outlives_predicates {
|
||||
match k1.unpack() {
|
||||
GenericArgKind::Lifetime(r1) => {
|
||||
let r1_vid = self.to_region_vid(r1);
|
||||
let r2_vid = self.to_region_vid(r2);
|
||||
self.add_outlives(r1_vid, r2_vid, constraint_category);
|
||||
}
|
||||
|
||||
GenericArgKind::Type(mut t1) => {
|
||||
// Normalize the type we receive from a `TypeOutlives` obligation
|
||||
// in the new trait solver.
|
||||
if infcx.next_trait_solver() {
|
||||
t1 = self.normalize_and_add_type_outlives_constraints(
|
||||
t1,
|
||||
&mut next_outlives_predicates,
|
||||
);
|
||||
}
|
||||
|
||||
// we don't actually use this for anything, but
|
||||
// the `TypeOutlives` code needs an origin.
|
||||
let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
|
||||
|
||||
TypeOutlives::new(
|
||||
&mut *self,
|
||||
tcx,
|
||||
region_bound_pairs,
|
||||
Some(implicit_region_bound),
|
||||
known_type_outlives_obligations,
|
||||
)
|
||||
.type_must_outlive(
|
||||
origin,
|
||||
t1,
|
||||
r2,
|
||||
constraint_category,
|
||||
);
|
||||
}
|
||||
|
||||
GenericArgKind::Const(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
outlives_predicates = next_outlives_predicates;
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
|
||||
debug!("add_type_test(type_test={:?})", type_test);
|
||||
self.constraints.type_tests.push(type_test);
|
||||
}
|
||||
|
||||
fn normalize_and_add_type_outlives_constraints(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
next_outlives_predicates: &mut Vec<(
|
||||
ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
|
||||
ConstraintCategory<'tcx>,
|
||||
)>,
|
||||
) -> Ty<'tcx> {
|
||||
let result = CustomTypeOp::new(
|
||||
|ocx| {
|
||||
deeply_normalize(
|
||||
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
|
||||
ty,
|
||||
)
|
||||
.map_err(|_| NoSolution)
|
||||
},
|
||||
"normalize type outlives obligation",
|
||||
)
|
||||
.fully_perform(self.infcx, self.span);
|
||||
|
||||
match result {
|
||||
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
|
||||
if let Some(constraints) = constraints {
|
||||
assert!(
|
||||
constraints.member_constraints.is_empty(),
|
||||
"no member constraints expected from normalizing: {:#?}",
|
||||
constraints.member_constraints
|
||||
);
|
||||
next_outlives_predicates.extend(constraints.outlives.iter().copied());
|
||||
}
|
||||
ty
|
||||
}
|
||||
Err(_) => ty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
|
||||
|
@ -8,8 +8,11 @@ use rustc_infer::infer::region_constraints::GenericKind;
|
||||
use rustc_infer::infer::InferCtxt;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
|
||||
use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
|
||||
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
|
||||
use rustc_trait_selection::solve::deeply_normalize;
|
||||
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
|
||||
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
|
||||
use std::rc::Rc;
|
||||
use type_op::TypeOpOutput;
|
||||
@ -52,7 +55,6 @@ pub(crate) struct CreateResult<'tcx> {
|
||||
pub(crate) fn create<'tcx>(
|
||||
infcx: &InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
universal_regions: &Rc<UniversalRegions<'tcx>>,
|
||||
constraints: &mut MirTypeckRegionConstraints<'tcx>,
|
||||
@ -60,7 +62,6 @@ pub(crate) fn create<'tcx>(
|
||||
UniversalRegionRelationsBuilder {
|
||||
infcx,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
implicit_region_bound,
|
||||
constraints,
|
||||
universal_regions: universal_regions.clone(),
|
||||
@ -178,7 +179,6 @@ impl UniversalRegionRelations<'_> {
|
||||
struct UniversalRegionRelationsBuilder<'this, 'tcx> {
|
||||
infcx: &'this InferCtxt<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
known_type_outlives_obligations: &'tcx [ty::PolyTypeOutlivesPredicate<'tcx>],
|
||||
universal_regions: Rc<UniversalRegions<'tcx>>,
|
||||
implicit_region_bound: ty::Region<'tcx>,
|
||||
constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
|
||||
@ -222,6 +222,32 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
self.relate_universal_regions(fr, fr_fn_body);
|
||||
}
|
||||
|
||||
// Normalize the assumptions we use to borrowck the program.
|
||||
let mut constraints = vec![];
|
||||
let mut known_type_outlives_obligations = vec![];
|
||||
for bound in param_env.caller_bounds() {
|
||||
let Some(mut outlives) = bound.as_type_outlives_clause() else { continue };
|
||||
|
||||
// In the new solver, normalize the type-outlives obligation assumptions.
|
||||
if self.infcx.next_trait_solver() {
|
||||
match deeply_normalize(
|
||||
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
|
||||
outlives,
|
||||
) {
|
||||
Ok(normalized_outlives) => {
|
||||
outlives = normalized_outlives;
|
||||
}
|
||||
Err(e) => {
|
||||
self.infcx.err_ctxt().report_fulfillment_errors(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
known_type_outlives_obligations.push(outlives);
|
||||
}
|
||||
let known_type_outlives_obligations =
|
||||
self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);
|
||||
|
||||
let unnormalized_input_output_tys = self
|
||||
.universal_regions
|
||||
.unnormalized_input_tys
|
||||
@ -239,7 +265,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
// the `relations` is built.
|
||||
let mut normalized_inputs_and_output =
|
||||
Vec::with_capacity(self.universal_regions.unnormalized_input_tys.len() + 1);
|
||||
let mut constraints = vec![];
|
||||
for ty in unnormalized_input_output_tys {
|
||||
debug!("build: input_or_output={:?}", ty);
|
||||
// We add implied bounds from both the unnormalized and normalized ty.
|
||||
@ -304,7 +329,19 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
}
|
||||
|
||||
for c in constraints {
|
||||
self.push_region_constraints(c, span);
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
&self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
param_env,
|
||||
known_type_outlives_obligations,
|
||||
Locations::All(span),
|
||||
span,
|
||||
ConstraintCategory::Internal,
|
||||
self.constraints,
|
||||
)
|
||||
.convert_all(c);
|
||||
}
|
||||
|
||||
CreateResult {
|
||||
@ -313,30 +350,12 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
|
||||
outlives: self.outlives.freeze(),
|
||||
inverse_outlives: self.inverse_outlives.freeze(),
|
||||
}),
|
||||
known_type_outlives_obligations: self.known_type_outlives_obligations,
|
||||
known_type_outlives_obligations,
|
||||
region_bound_pairs: self.region_bound_pairs,
|
||||
normalized_inputs_and_output,
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip(self, data), level = "debug")]
|
||||
fn push_region_constraints(&mut self, data: &QueryRegionConstraints<'tcx>, span: Span) {
|
||||
debug!("constraints generated: {:#?}", data);
|
||||
|
||||
constraint_conversion::ConstraintConversion::new(
|
||||
self.infcx,
|
||||
&self.universal_regions,
|
||||
&self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.known_type_outlives_obligations,
|
||||
Locations::All(span),
|
||||
span,
|
||||
ConstraintCategory::Internal,
|
||||
self.constraints,
|
||||
)
|
||||
.convert_all(data);
|
||||
}
|
||||
|
||||
/// Update the type of a single local, which should represent
|
||||
/// either the return type of the MIR or one of its arguments. At
|
||||
/// the same time, compute and add any implied bounds that come
|
||||
|
@ -156,10 +156,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
|
||||
} = free_region_relations::create(
|
||||
infcx,
|
||||
param_env,
|
||||
// FIXME(-Znext-solver): These are unnormalized. Normalize them.
|
||||
infcx.tcx.arena.alloc_from_iter(
|
||||
param_env.caller_bounds().iter().filter_map(|clause| clause.as_type_outlives_clause()),
|
||||
),
|
||||
implicit_region_bound,
|
||||
universal_regions,
|
||||
&mut constraints,
|
||||
@ -1144,6 +1140,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self.borrowck_context.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
locations.span(self.body),
|
||||
@ -2759,6 +2756,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
self.borrowck_context.universal_regions,
|
||||
self.region_bound_pairs,
|
||||
self.implicit_region_bound,
|
||||
self.param_env,
|
||||
self.known_type_outlives_obligations,
|
||||
locations,
|
||||
DUMMY_SP, // irrelevant; will be overridden.
|
||||
|
@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem;
|
||||
use rustc_middle::dep_graph::DepContext;
|
||||
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
|
||||
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
|
||||
use rustc_middle::ty::ToPredicate;
|
||||
use rustc_middle::ty::{
|
||||
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
|
||||
TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
|
||||
@ -519,10 +520,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
|
||||
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
|
||||
}
|
||||
|
||||
RegionResolutionError::CannotNormalize(ty, origin) => {
|
||||
RegionResolutionError::CannotNormalize(clause, origin) => {
|
||||
let clause: ty::Clause<'tcx> =
|
||||
clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx);
|
||||
self.tcx
|
||||
.dcx()
|
||||
.struct_span_err(origin.span(), format!("cannot normalize `{ty}`"))
|
||||
.struct_span_err(origin.span(), format!("cannot normalize `{clause}`"))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ pub enum RegionResolutionError<'tcx> {
|
||||
Region<'tcx>, // the placeholder `'b`
|
||||
),
|
||||
|
||||
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
|
||||
CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> RegionResolutionError<'tcx> {
|
||||
|
@ -4,8 +4,8 @@ use super::region_constraints::RegionConstraintData;
|
||||
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
|
||||
use crate::infer::free_regions::RegionRelations;
|
||||
use crate::infer::lexical_region_resolve;
|
||||
use rustc_middle::traits::query::OutlivesBound;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_middle::traits::query::{NoSolution, OutlivesBound};
|
||||
use rustc_middle::ty;
|
||||
|
||||
pub mod components;
|
||||
pub mod env;
|
||||
@ -49,12 +49,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
pub fn resolve_regions_with_normalize(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
|
||||
deeply_normalize_ty: impl Fn(
|
||||
ty::PolyTypeOutlivesPredicate<'tcx>,
|
||||
SubregionOrigin<'tcx>,
|
||||
) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
|
||||
) -> Vec<RegionResolutionError<'tcx>> {
|
||||
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
|
||||
Ok(()) => {}
|
||||
Err((ty, origin)) => {
|
||||
return vec![RegionResolutionError::CannotNormalize(ty, origin)];
|
||||
Err((clause, origin)) => {
|
||||
return vec![RegionResolutionError::CannotNormalize(clause, origin)];
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -68,8 +68,9 @@ use crate::infer::{
|
||||
use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use rustc_data_structures::undo_log::UndoLogs;
|
||||
use rustc_middle::mir::ConstraintCategory;
|
||||
use rustc_middle::ty::GenericArgKind;
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
|
||||
use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
|
||||
use rustc_span::DUMMY_SP;
|
||||
use smallvec::smallvec;
|
||||
|
||||
@ -125,11 +126,15 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
/// invoked after all type-inference variables have been bound --
|
||||
/// right before lexical region resolution.
|
||||
#[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
|
||||
pub fn process_registered_region_obligations<E>(
|
||||
pub fn process_registered_region_obligations(
|
||||
&self,
|
||||
outlives_env: &OutlivesEnvironment<'tcx>,
|
||||
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, E>,
|
||||
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
|
||||
mut deeply_normalize_ty: impl FnMut(
|
||||
PolyTypeOutlivesPredicate<'tcx>,
|
||||
SubregionOrigin<'tcx>,
|
||||
)
|
||||
-> Result<PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
|
||||
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
|
||||
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
|
||||
|
||||
let normalized_caller_bounds: Vec<_> = outlives_env
|
||||
@ -137,38 +142,53 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||
.caller_bounds()
|
||||
.iter()
|
||||
.filter_map(|clause| {
|
||||
let bound_clause = clause.kind();
|
||||
let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else {
|
||||
return None;
|
||||
};
|
||||
let outlives = clause.as_type_outlives_clause()?;
|
||||
Some(
|
||||
deeply_normalize_ty(
|
||||
outlives.0,
|
||||
outlives,
|
||||
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
|
||||
)
|
||||
.map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))),
|
||||
// FIXME(-Znext-solver): How do we accurately report an error span here :(
|
||||
.map_err(|NoSolution| {
|
||||
(outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP))
|
||||
}),
|
||||
)
|
||||
})
|
||||
// FIXME(-Znext-solver): How do we accurately report an error here :(
|
||||
.try_collect()
|
||||
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
|
||||
.try_collect()?;
|
||||
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
// Must loop since the process of normalizing may itself register region obligations.
|
||||
for iteration in 0.. {
|
||||
let my_region_obligations = self.take_registered_region_obligations();
|
||||
if my_region_obligations.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||
let sup_type =
|
||||
deeply_normalize_ty(sup_type, origin.clone()).map_err(|e| (e, origin.clone()))?;
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
if !self.tcx.recursion_limit().value_within_limit(iteration) {
|
||||
bug!(
|
||||
"FIXME(-Znext-solver): Overflowed when processing region obligations: {my_region_obligations:#?}"
|
||||
);
|
||||
}
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
self.tcx,
|
||||
outlives_env.region_bound_pairs(),
|
||||
None,
|
||||
&normalized_caller_bounds,
|
||||
);
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
|
||||
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
|
||||
let ty::OutlivesPredicate(sup_type, sub_region) =
|
||||
deeply_normalize_ty(outlives, origin.clone())
|
||||
.map_err(|NoSolution| (outlives, origin.clone()))?
|
||||
.no_bound_vars()
|
||||
.expect("started with no bound vars, should end with no bound vars");
|
||||
|
||||
debug!(?sup_type, ?sub_region, ?origin);
|
||||
|
||||
let outlives = &mut TypeOutlives::new(
|
||||
self,
|
||||
self.tcx,
|
||||
outlives_env.region_bound_pairs(),
|
||||
None,
|
||||
&normalized_caller_bounds,
|
||||
);
|
||||
let category = origin.to_constraint_category();
|
||||
outlives.type_must_outlive(origin, sup_type, sub_region, category);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1,5 +1,6 @@
|
||||
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
|
||||
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
|
||||
use rustc_middle::traits::query::NoSolution;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
|
||||
pub trait InferCtxtRegionExt<'tcx> {
|
||||
@ -31,7 +32,7 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
|
||||
),
|
||||
ty,
|
||||
)
|
||||
.map_err(|_| ty)
|
||||
.map_err(|_| NoSolution)
|
||||
} else {
|
||||
Ok(ty)
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
|
||||
}
|
||||
|
||||
let outlives_env = OutlivesEnvironment::new(full_env);
|
||||
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty, _| Ok(ty));
|
||||
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();
|
||||
|
@ -1,4 +1,4 @@
|
||||
// revisions: normalize_param_env normalize_obligation
|
||||
// revisions: normalize_param_env normalize_obligation hrtb
|
||||
// check-pass
|
||||
// compile-flags: -Znext-solver
|
||||
|
||||
@ -7,16 +7,23 @@ trait Foo {
|
||||
type Gat<'a> where <Self as Mirror>::Assoc: 'a;
|
||||
#[cfg(normalize_obligation)]
|
||||
type Gat<'a> where Self: 'a;
|
||||
#[cfg(hrtb)]
|
||||
type Gat<'b> where for<'a> <Self as MirrorRegion<'a>>::Assoc: 'b;
|
||||
}
|
||||
|
||||
trait Mirror { type Assoc: ?Sized; }
|
||||
impl<T: ?Sized> Mirror for T { type Assoc = T; }
|
||||
|
||||
trait MirrorRegion<'a> { type Assoc: ?Sized; }
|
||||
impl<'a, T> MirrorRegion<'a> for T { type Assoc = T; }
|
||||
|
||||
impl<T> Foo for T {
|
||||
#[cfg(normalize_param_env)]
|
||||
type Gat<'a> = i32 where T: 'a;
|
||||
#[cfg(normalize_obligation)]
|
||||
type Gat<'a> = i32 where <T as Mirror>::Assoc: 'a;
|
||||
#[cfg(hrtb)]
|
||||
type Gat<'b> = i32 where Self: 'b;
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
@ -0,0 +1,18 @@
|
||||
// check-pass
|
||||
// compile-flags: -Znext-solver
|
||||
|
||||
trait Mirror {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
impl<T> Mirror for T {
|
||||
type Assoc = T;
|
||||
}
|
||||
|
||||
fn is_static<T: 'static>() {}
|
||||
|
||||
fn test<T>() where <T as Mirror>::Assoc: 'static {
|
||||
is_static::<T>();
|
||||
}
|
||||
|
||||
fn main() {}
|
13
tests/ui/traits/next-solver/normalize-type-outlives.rs
Normal file
13
tests/ui/traits/next-solver/normalize-type-outlives.rs
Normal file
@ -0,0 +1,13 @@
|
||||
// check-pass
|
||||
|
||||
trait Tr<'a> {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
fn outlives<'o, T: 'o>() {}
|
||||
|
||||
fn foo<'a, 'b, T: Tr<'a, Assoc = ()>>() {
|
||||
outlives::<'b, T::Assoc>();
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -1,5 +1,5 @@
|
||||
// compile-flags: -Znext-solver
|
||||
//~^ ERROR cannot normalize `<T as Default>::Id`
|
||||
//~^ ERROR cannot normalize `<T as Default>::Id: '_`
|
||||
|
||||
#![feature(specialization)]
|
||||
//~^ WARN the feature `specialization` is incomplete
|
||||
|
@ -8,7 +8,7 @@ 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: cannot normalize `<T as Default>::Id: '_`
|
||||
|
||||
error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id == _`
|
||||
--> $DIR/specialization-transmute.rs:16:23
|
||||
|
Loading…
Reference in New Issue
Block a user