Skip to content

Commit e951bcf

Browse files
Normalize the whole PolyTypeOutlivesPredicate, more simplifications
1 parent a371059 commit e951bcf

File tree

10 files changed

+92
-81
lines changed

10 files changed

+92
-81
lines changed

compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

+42-42
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega
55
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
66
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
77
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
8+
use rustc_middle::traits::query::NoSolution;
89
use rustc_middle::traits::ObligationCause;
9-
use rustc_middle::ty::GenericArgKind;
10-
use rustc_middle::ty::{self, TyCtxt};
11-
use rustc_middle::ty::{TypeFoldable, TypeVisitableExt};
10+
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
1211
use rustc_span::{Span, DUMMY_SP};
1312
use rustc_trait_selection::solve::deeply_normalize;
14-
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
1513
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1614
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
1715

@@ -146,7 +144,6 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
146144
let ConstraintConversion {
147145
tcx,
148146
infcx,
149-
param_env,
150147
region_bound_pairs,
151148
implicit_region_bound,
152149
known_type_outlives_obligations,
@@ -178,43 +175,10 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
178175
// Normalize the type we receive from a `TypeOutlives` obligation
179176
// in the new trait solver.
180177
if infcx.next_trait_solver() {
181-
let result = CustomTypeOp::new(
182-
|ocx| {
183-
match deeply_normalize(
184-
ocx.infcx.at(
185-
&ObligationCause::dummy_with_span(self.span),
186-
param_env,
187-
),
188-
t1,
189-
) {
190-
Ok(normalized_ty) => {
191-
t1 = normalized_ty;
192-
}
193-
Err(e) => {
194-
infcx.err_ctxt().report_fulfillment_errors(e);
195-
}
196-
}
197-
198-
Ok(())
199-
},
200-
"normalize type outlives obligation",
201-
)
202-
.fully_perform(infcx, self.span);
203-
204-
match result {
205-
Ok(TypeOpOutput { output: (), constraints, .. }) => {
206-
if let Some(constraints) = constraints {
207-
assert!(
208-
constraints.member_constraints.is_empty(),
209-
"no member constraints expected from normalizing: {:#?}",
210-
constraints.member_constraints
211-
);
212-
next_outlives_predicates
213-
.extend(constraints.outlives.iter().copied());
214-
}
215-
}
216-
Err(_) => {}
217-
}
178+
t1 = self.normalize_and_add_type_outlives_constraints(
179+
t1,
180+
&mut next_outlives_predicates,
181+
);
218182
}
219183

220184
// we don't actually use this for anything, but
@@ -306,6 +270,42 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
306270
debug!("add_type_test(type_test={:?})", type_test);
307271
self.constraints.type_tests.push(type_test);
308272
}
273+
274+
fn normalize_and_add_type_outlives_constraints(
275+
&self,
276+
ty: Ty<'tcx>,
277+
next_outlives_predicates: &mut Vec<(
278+
ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
279+
ConstraintCategory<'tcx>,
280+
)>,
281+
) -> Ty<'tcx> {
282+
let result = CustomTypeOp::new(
283+
|ocx| {
284+
deeply_normalize(
285+
ocx.infcx.at(&ObligationCause::dummy_with_span(self.span), self.param_env),
286+
ty,
287+
)
288+
.map_err(|_| NoSolution)
289+
},
290+
"normalize type outlives obligation",
291+
)
292+
.fully_perform(self.infcx, self.span);
293+
294+
match result {
295+
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
296+
if let Some(constraints) = constraints {
297+
assert!(
298+
constraints.member_constraints.is_empty(),
299+
"no member constraints expected from normalizing: {:#?}",
300+
constraints.member_constraints
301+
);
302+
next_outlives_predicates.extend(constraints.outlives.iter().copied());
303+
}
304+
ty
305+
}
306+
Err(_) => ty,
307+
}
308+
}
309309
}
310310

311311
impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {

compiler/rustc_borrowck/src/type_check/free_region_relations.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_middle::traits::query::OutlivesBound;
1111
use rustc_middle::traits::ObligationCause;
1212
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
1313
use rustc_span::{ErrorGuaranteed, DUMMY_SP};
14-
use rustc_trait_selection::solve::deeply_normalize_with_skipped_universes;
14+
use rustc_trait_selection::solve::deeply_normalize;
1515
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
1616
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
1717
use std::rc::Rc;
@@ -226,27 +226,24 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
226226
let mut constraints = vec![];
227227
let mut known_type_outlives_obligations = vec![];
228228
for bound in param_env.caller_bounds() {
229-
let Some(outlives) = bound.as_type_outlives_clause() else { continue };
230-
let ty::OutlivesPredicate(mut ty, region) = outlives.skip_binder();
229+
let Some(mut outlives) = bound.as_type_outlives_clause() else { continue };
231230

232231
// In the new solver, normalize the type-outlives obligation assumptions.
233232
if self.infcx.next_trait_solver() {
234-
match deeply_normalize_with_skipped_universes(
233+
match deeply_normalize(
235234
self.infcx.at(&ObligationCause::misc(span, defining_ty_def_id), self.param_env),
236-
ty,
237-
vec![None; ty.outer_exclusive_binder().as_usize()],
235+
outlives,
238236
) {
239-
Ok(normalized_ty) => {
240-
ty = normalized_ty;
237+
Ok(normalized_outlives) => {
238+
outlives = normalized_outlives;
241239
}
242240
Err(e) => {
243241
self.infcx.err_ctxt().report_fulfillment_errors(e);
244242
}
245243
}
246244
}
247245

248-
known_type_outlives_obligations
249-
.push(outlives.rebind(ty::OutlivesPredicate(ty, region)));
246+
known_type_outlives_obligations.push(outlives);
250247
}
251248
let known_type_outlives_obligations =
252249
self.infcx.tcx.arena.alloc_slice(&known_type_outlives_obligations);

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ use rustc_hir::lang_items::LangItem;
7171
use rustc_middle::dep_graph::DepContext;
7272
use rustc_middle::ty::print::{with_forced_trimmed_paths, PrintError};
7373
use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
74+
use rustc_middle::ty::ToPredicate;
7475
use rustc_middle::ty::{
7576
self, error::TypeError, IsSuggestable, List, Region, Ty, TyCtxt, TypeFoldable,
7677
TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
@@ -519,10 +520,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
519520
self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
520521
}
521522

522-
RegionResolutionError::CannotNormalize(ty, origin) => {
523+
RegionResolutionError::CannotNormalize(clause, origin) => {
524+
let clause: ty::Clause<'tcx> =
525+
clause.map_bound(ty::ClauseKind::TypeOutlives).to_predicate(self.tcx);
523526
self.tcx
524527
.dcx()
525-
.struct_span_err(origin.span(), format!("cannot normalize `{ty}`"))
528+
.struct_span_err(origin.span(), format!("cannot normalize `{clause}`"))
526529
.emit();
527530
}
528531
}

compiler/rustc_infer/src/infer/lexical_region_resolve/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub enum RegionResolutionError<'tcx> {
9999
Region<'tcx>, // the placeholder `'b`
100100
),
101101

102-
CannotNormalize(Ty<'tcx>, SubregionOrigin<'tcx>),
102+
CannotNormalize(ty::PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>),
103103
}
104104

105105
impl<'tcx> RegionResolutionError<'tcx> {

compiler/rustc_infer/src/infer/outlives/mod.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use super::region_constraints::RegionConstraintData;
44
use super::{InferCtxt, RegionResolutionError, SubregionOrigin};
55
use crate::infer::free_regions::RegionRelations;
66
use crate::infer::lexical_region_resolve;
7-
use rustc_middle::traits::query::OutlivesBound;
8-
use rustc_middle::ty::{self, Ty};
7+
use rustc_middle::traits::query::{NoSolution, OutlivesBound};
8+
use rustc_middle::ty;
99

1010
pub mod components;
1111
pub mod env;
@@ -49,12 +49,15 @@ impl<'tcx> InferCtxt<'tcx> {
4949
pub fn resolve_regions_with_normalize(
5050
&self,
5151
outlives_env: &OutlivesEnvironment<'tcx>,
52-
deeply_normalize_ty: impl Fn(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, Ty<'tcx>>,
52+
deeply_normalize_ty: impl Fn(
53+
ty::PolyTypeOutlivesPredicate<'tcx>,
54+
SubregionOrigin<'tcx>,
55+
) -> Result<ty::PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
5356
) -> Vec<RegionResolutionError<'tcx>> {
5457
match self.process_registered_region_obligations(outlives_env, deeply_normalize_ty) {
5558
Ok(()) => {}
56-
Err((ty, origin)) => {
57-
return vec![RegionResolutionError::CannotNormalize(ty, origin)];
59+
Err((clause, origin)) => {
60+
return vec![RegionResolutionError::CannotNormalize(clause, origin)];
5861
}
5962
};
6063

compiler/rustc_infer/src/infer/outlives/obligations.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ use crate::infer::{
6868
use crate::traits::{ObligationCause, ObligationCauseCode};
6969
use rustc_data_structures::undo_log::UndoLogs;
7070
use rustc_middle::mir::ConstraintCategory;
71-
use rustc_middle::ty::GenericArgKind;
71+
use rustc_middle::traits::query::NoSolution;
7272
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
73+
use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
7374
use rustc_span::DUMMY_SP;
7475
use smallvec::smallvec;
7576

@@ -125,33 +126,35 @@ impl<'tcx> InferCtxt<'tcx> {
125126
/// invoked after all type-inference variables have been bound --
126127
/// right before lexical region resolution.
127128
#[instrument(level = "debug", skip(self, outlives_env, deeply_normalize_ty))]
128-
pub fn process_registered_region_obligations<E>(
129+
pub fn process_registered_region_obligations(
129130
&self,
130131
outlives_env: &OutlivesEnvironment<'tcx>,
131-
mut deeply_normalize_ty: impl FnMut(Ty<'tcx>, SubregionOrigin<'tcx>) -> Result<Ty<'tcx>, E>,
132-
) -> Result<(), (E, SubregionOrigin<'tcx>)> {
132+
mut deeply_normalize_ty: impl FnMut(
133+
PolyTypeOutlivesPredicate<'tcx>,
134+
SubregionOrigin<'tcx>,
135+
)
136+
-> Result<PolyTypeOutlivesPredicate<'tcx>, NoSolution>,
137+
) -> Result<(), (PolyTypeOutlivesPredicate<'tcx>, SubregionOrigin<'tcx>)> {
133138
assert!(!self.in_snapshot(), "cannot process registered region obligations in a snapshot");
134139

135140
let normalized_caller_bounds: Vec<_> = outlives_env
136141
.param_env
137142
.caller_bounds()
138143
.iter()
139144
.filter_map(|clause| {
140-
let bound_clause = clause.kind();
141-
let ty::ClauseKind::TypeOutlives(outlives) = bound_clause.skip_binder() else {
142-
return None;
143-
};
145+
let outlives = clause.as_type_outlives_clause()?;
144146
Some(
145147
deeply_normalize_ty(
146-
outlives.0,
148+
outlives,
147149
SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP),
148150
)
149-
.map(|ty| bound_clause.rebind(ty::OutlivesPredicate(ty, outlives.1))),
151+
// FIXME(-Znext-solver): How do we accurately report an error span here :(
152+
.map_err(|NoSolution| {
153+
(outlives, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP))
154+
}),
150155
)
151156
})
152-
// FIXME(-Znext-solver): How do we accurately report an error here :(
153-
.try_collect()
154-
.map_err(|e| (e, SubregionOrigin::AscribeUserTypeProvePredicate(DUMMY_SP)))?;
157+
.try_collect()?;
155158

156159
// Must loop since the process of normalizing may itself register region obligations.
157160
for iteration in 0.. {
@@ -167,8 +170,13 @@ impl<'tcx> InferCtxt<'tcx> {
167170
}
168171

169172
for RegionObligation { sup_type, sub_region, origin } in my_region_obligations {
170-
let sup_type = deeply_normalize_ty(sup_type, origin.clone())
171-
.map_err(|e| (e, origin.clone()))?;
173+
let outlives = ty::Binder::dummy(ty::OutlivesPredicate(sup_type, sub_region));
174+
let ty::OutlivesPredicate(sup_type, sub_region) =
175+
deeply_normalize_ty(outlives, origin.clone())
176+
.map_err(|NoSolution| (outlives, origin.clone()))?
177+
.no_bound_vars()
178+
.expect("started with no bound vars, should end with no bound vars");
179+
172180
debug!(?sup_type, ?sub_region, ?origin);
173181

174182
let outlives = &mut TypeOutlives::new(

compiler/rustc_trait_selection/src/regions.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
22
use rustc_infer::infer::{InferCtxt, RegionResolutionError};
3+
use rustc_middle::traits::query::NoSolution;
34
use rustc_middle::traits::ObligationCause;
45

56
pub trait InferCtxtRegionExt<'tcx> {
@@ -24,15 +25,14 @@ impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
2425
let ty = self.resolve_vars_if_possible(ty);
2526

2627
if self.next_trait_solver() {
27-
crate::solve::deeply_normalize_with_skipped_universes(
28+
crate::solve::deeply_normalize(
2829
self.at(
2930
&ObligationCause::dummy_with_span(origin.span()),
3031
outlives_env.param_env,
3132
),
3233
ty,
33-
vec![None; ty.outer_exclusive_binder().as_usize()],
3434
)
35-
.map_err(|_| ty)
35+
.map_err(|_| NoSolution)
3636
} else {
3737
Ok(ty)
3838
}

compiler/rustc_trait_selection/src/traits/auto_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ impl<'tcx> AutoTraitFinder<'tcx> {
179179
}
180180

181181
let outlives_env = OutlivesEnvironment::new(full_env);
182-
let _ = infcx.process_registered_region_obligations::<!>(&outlives_env, |ty, _| Ok(ty));
182+
let _ = infcx.process_registered_region_obligations(&outlives_env, |ty, _| Ok(ty));
183183

184184
let region_data =
185185
infcx.inner.borrow_mut().unwrap_region_constraints().region_constraint_data().clone();

tests/ui/traits/next-solver/specialization-transmute.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// compile-flags: -Znext-solver
2-
//~^ ERROR cannot normalize `<T as Default>::Id`
2+
//~^ ERROR cannot normalize `<T as Default>::Id: '_`
33

44
#![feature(specialization)]
55
//~^ WARN the feature `specialization` is incomplete

tests/ui/traits/next-solver/specialization-transmute.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | #![feature(specialization)]
88
= help: consider using `min_specialization` instead, which is more stable and complete
99
= note: `#[warn(incomplete_features)]` on by default
1010

11-
error: cannot normalize `<T as Default>::Id`
11+
error: cannot normalize `<T as Default>::Id: '_`
1212

1313
error[E0282]: type annotations needed
1414
--> $DIR/specialization-transmute.rs:14:23

0 commit comments

Comments
 (0)