Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 6fc8fbd

Browse files
committedJan 25, 2025
Auto merge of #136074 - compiler-errors:deeply-normalize-next-solver, r=<try>
Properly deeply normalize in the next solver r? lcnr
2 parents f7cc13a + 0eab7b0 commit 6fc8fbd

23 files changed

+283
-69
lines changed
 

‎compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_infer::infer::{
99
};
1010
use rustc_infer::traits::ObligationCause;
1111
use rustc_infer::traits::query::{
12-
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpNormalizeGoal,
13-
CanonicalTypeOpProvePredicateGoal,
12+
CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpDeeplyNormalizeGoal,
13+
CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal,
1414
};
1515
use rustc_middle::ty::error::TypeError;
1616
use rustc_middle::ty::{
@@ -109,6 +109,14 @@ impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUnivers
109109
}
110110
}
111111

112+
impl<'tcx, T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx> ToUniverseInfo<'tcx>
113+
for CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>
114+
{
115+
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
116+
UniverseInfo::TypeOp(Rc::new(DeeplyNormalizeQuery { canonical_query: self, base_universe }))
117+
}
118+
}
119+
112120
impl<'tcx> ToUniverseInfo<'tcx> for CanonicalTypeOpAscribeUserTypeGoal<'tcx> {
113121
fn to_universe_info(self, base_universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {
114122
UniverseInfo::TypeOp(Rc::new(AscribeUserTypeQuery { canonical_query: self, base_universe }))
@@ -284,6 +292,53 @@ where
284292
}
285293
}
286294

295+
struct DeeplyNormalizeQuery<'tcx, T> {
296+
canonical_query: CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T>,
297+
base_universe: ty::UniverseIndex,
298+
}
299+
300+
impl<'tcx, T> TypeOpInfo<'tcx> for DeeplyNormalizeQuery<'tcx, T>
301+
where
302+
T: Copy + fmt::Display + TypeFoldable<TyCtxt<'tcx>> + 'tcx,
303+
{
304+
fn fallback_error(&self, tcx: TyCtxt<'tcx>, span: Span) -> Diag<'tcx> {
305+
tcx.dcx().create_err(HigherRankedLifetimeError {
306+
cause: Some(HigherRankedErrorCause::CouldNotNormalize {
307+
value: self.canonical_query.canonical.value.value.value.to_string(),
308+
}),
309+
span,
310+
})
311+
}
312+
313+
fn base_universe(&self) -> ty::UniverseIndex {
314+
self.base_universe
315+
}
316+
317+
fn nice_error<'infcx>(
318+
&self,
319+
mbcx: &mut MirBorrowckCtxt<'_, 'infcx, 'tcx>,
320+
cause: ObligationCause<'tcx>,
321+
placeholder_region: ty::Region<'tcx>,
322+
error_region: Option<ty::Region<'tcx>>,
323+
) -> Option<Diag<'infcx>> {
324+
let (infcx, key, _) =
325+
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
326+
let ocx = ObligationCtxt::new(&infcx);
327+
328+
let (param_env, value) = key.into_parts();
329+
let _ = ocx.deeply_normalize(&cause, param_env, value.value);
330+
331+
let diag = try_extract_error_from_fulfill_cx(
332+
&ocx,
333+
mbcx.mir_def_id(),
334+
placeholder_region,
335+
error_region,
336+
)?
337+
.with_dcx(mbcx.dcx());
338+
Some(diag)
339+
}
340+
}
341+
287342
struct AscribeUserTypeQuery<'tcx> {
288343
canonical_query: CanonicalTypeOpAscribeUserTypeGoal<'tcx>,
289344
base_universe: ty::UniverseIndex,
@@ -310,7 +365,7 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> {
310365
let (infcx, key, _) =
311366
mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query);
312367
let ocx = ObligationCtxt::new(&infcx);
313-
type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?;
368+
type_op_ascribe_user_type_with_span(&ocx, key, cause.span).ok()?;
314369
let diag = try_extract_error_from_fulfill_cx(
315370
&ocx,
316371
mbcx.mir_def_id(),

‎compiler/rustc_borrowck/src/type_check/canonical.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
149149
self.normalize_with_category(value, location, ConstraintCategory::Boring)
150150
}
151151

152+
pub(super) fn deeply_normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
153+
where
154+
T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
155+
{
156+
let result: Result<_, ErrorGuaranteed> = self.fully_perform_op(
157+
location.to_locations(),
158+
ConstraintCategory::Boring,
159+
self.infcx.param_env.and(type_op::normalize::DeeplyNormalize { value }),
160+
);
161+
result.unwrap_or(value)
162+
}
163+
152164
#[instrument(skip(self), level = "debug")]
153165
pub(super) fn normalize_with_category<T>(
154166
&mut self,

‎compiler/rustc_borrowck/src/type_check/constraint_conversion.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ use rustc_infer::infer::outlives::env::RegionBoundPairs;
44
use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
55
use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
66
use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
7+
use rustc_infer::traits::query::type_op::DeeplyNormalize;
78
use rustc_middle::bug;
89
use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
9-
use rustc_middle::traits::ObligationCause;
10-
use rustc_middle::traits::query::NoSolution;
1110
use rustc_middle::ty::fold::fold_regions;
1211
use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt};
1312
use rustc_span::Span;
14-
use rustc_trait_selection::traits::ScrubbedTraitError;
15-
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1613
use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
1714
use tracing::{debug, instrument};
1815

@@ -270,20 +267,8 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
270267
ConstraintCategory<'tcx>,
271268
)>,
272269
) -> Ty<'tcx> {
273-
let result = CustomTypeOp::new(
274-
|ocx| {
275-
ocx.deeply_normalize(
276-
&ObligationCause::dummy_with_span(self.span),
277-
self.param_env,
278-
ty,
279-
)
280-
.map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
281-
},
282-
"normalize type outlives obligation",
283-
)
284-
.fully_perform(self.infcx, self.span);
285-
286-
match result {
270+
match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
271+
{
287272
Ok(TypeOpOutput { output: ty, constraints, .. }) => {
288273
if let Some(QueryRegionConstraints { outlives }) = constraints {
289274
next_outlives_predicates.extend(outlives.iter().copied());

‎compiler/rustc_borrowck/src/type_check/free_region_relations.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,11 @@ use rustc_infer::infer::canonical::QueryRegionConstraints;
55
use rustc_infer::infer::outlives::env::RegionBoundPairs;
66
use rustc_infer::infer::region_constraints::GenericKind;
77
use rustc_infer::infer::{InferCtxt, outlives};
8-
use rustc_infer::traits::ScrubbedTraitError;
8+
use rustc_infer::traits::query::type_op::DeeplyNormalize;
99
use rustc_middle::mir::ConstraintCategory;
10-
use rustc_middle::traits::ObligationCause;
1110
use rustc_middle::traits::query::OutlivesBound;
1211
use rustc_middle::ty::{self, RegionVid, Ty, TypeVisitableExt};
1312
use rustc_span::{ErrorGuaranteed, Span};
14-
use rustc_trait_selection::solve::NoSolution;
15-
use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
1613
use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
1714
use tracing::{debug, instrument};
1815
use type_op::TypeOpOutput;
@@ -267,7 +264,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
267264
}
268265
let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
269266
param_env
270-
.and(type_op::normalize::Normalize { value: ty })
267+
.and(DeeplyNormalize { value: ty })
271268
.fully_perform(self.infcx, span)
272269
.unwrap_or_else(|guar| TypeOpOutput {
273270
output: Ty::new_error(self.infcx.tcx, guar),
@@ -303,9 +300,8 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
303300
// Add implied bounds from impl header.
304301
if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
305302
for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
306-
let result: Result<_, ErrorGuaranteed> = param_env
307-
.and(type_op::normalize::Normalize { value: ty })
308-
.fully_perform(self.infcx, span);
303+
let result: Result<_, ErrorGuaranteed> =
304+
param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
309305
let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
310306
continue;
311307
};
@@ -360,18 +356,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
360356
output: normalized_outlives,
361357
constraints: constraints_normalize,
362358
error_info: _,
363-
}) = CustomTypeOp::new(
364-
|ocx| {
365-
ocx.deeply_normalize(
366-
&ObligationCause::dummy_with_span(span),
367-
self.param_env,
368-
outlives,
369-
)
370-
.map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
371-
},
372-
"normalize type outlives obligation",
373-
)
374-
.fully_perform(self.infcx, span)
359+
}) = self
360+
.param_env
361+
.and(DeeplyNormalize { value: outlives })
362+
.fully_perform(self.infcx, span)
375363
else {
376364
self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}"));
377365
return;

‎compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
10941094
ConstraintCategory::Boring,
10951095
);
10961096

1097-
let sig = self.normalize(unnormalized_sig, term_location);
1097+
let sig = self.deeply_normalize(unnormalized_sig, term_location);
10981098
// HACK(#114936): `WF(sig)` does not imply `WF(normalized(sig))`
10991099
// with built-in `Fn` implementations, since the impl may not be
11001100
// well-formed itself.

‎compiler/rustc_middle/src/traits/query.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,18 @@ pub mod type_op {
4242
pub predicate: Predicate<'tcx>,
4343
}
4444

45+
/// Normalizes, but not in the new solver.
4546
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
4647
pub struct Normalize<T> {
4748
pub value: T,
4849
}
4950

51+
/// Normalizes, and deeply normalizes in the new solver.
52+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
53+
pub struct DeeplyNormalize<T> {
54+
pub value: T,
55+
}
56+
5057
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, HashStable, TypeFoldable, TypeVisitable)]
5158
pub struct ImpliedOutlivesBounds<'tcx> {
5259
pub ty: Ty<'tcx>,
@@ -81,6 +88,9 @@ pub type CanonicalTypeOpProvePredicateGoal<'tcx> =
8188
pub type CanonicalTypeOpNormalizeGoal<'tcx, T> =
8289
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::Normalize<T>>>;
8390

91+
pub type CanonicalTypeOpDeeplyNormalizeGoal<'tcx, T> =
92+
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::DeeplyNormalize<T>>>;
93+
8494
pub type CanonicalImpliedOutlivesBoundsGoal<'tcx> =
8595
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, type_op::ImpliedOutlivesBounds<'tcx>>>;
8696

‎compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
9090
pub fn compute_dropck_outlives_inner<'tcx>(
9191
ocx: &ObligationCtxt<'_, 'tcx>,
9292
goal: ParamEnvAnd<'tcx, DropckOutlives<'tcx>>,
93+
span: Span,
9394
) -> Result<DropckOutlivesResult<'tcx>, NoSolution> {
9495
let tcx = ocx.infcx.tcx;
9596
let ParamEnvAnd { param_env, value: DropckOutlives { dropped_ty } } = goal;
@@ -135,7 +136,7 @@ pub fn compute_dropck_outlives_inner<'tcx>(
135136
// Set used to detect infinite recursion.
136137
let mut ty_set = FxHashSet::default();
137138

138-
let cause = ObligationCause::dummy();
139+
let cause = ObligationCause::dummy_with_span(span);
139140
let mut constraints = DropckConstraint::empty();
140141
while let Some((ty, depth)) = ty_stack.pop() {
141142
debug!(

‎compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
3030
fn perform_locally_with_next_solver(
3131
ocx: &ObligationCtxt<'_, 'tcx>,
3232
key: ParamEnvAnd<'tcx, Self>,
33+
span: Span,
3334
) -> Result<Self::QueryResponse, NoSolution> {
34-
type_op_ascribe_user_type_with_span(ocx, key, None)
35+
type_op_ascribe_user_type_with_span(ocx, key, span)
3536
}
3637
}
3738

@@ -41,11 +42,10 @@ impl<'tcx> super::QueryTypeOp<'tcx> for AscribeUserType<'tcx> {
4142
pub fn type_op_ascribe_user_type_with_span<'tcx>(
4243
ocx: &ObligationCtxt<'_, 'tcx>,
4344
key: ParamEnvAnd<'tcx, AscribeUserType<'tcx>>,
44-
span: Option<Span>,
45+
span: Span,
4546
) -> Result<(), NoSolution> {
4647
let (param_env, AscribeUserType { mir_ty, user_ty }) = key.into_parts();
4748
debug!("type_op_ascribe_user_type: mir_ty={:?} user_ty={:?}", mir_ty, user_ty);
48-
let span = span.unwrap_or(DUMMY_SP);
4949
match user_ty.kind {
5050
UserTypeKind::Ty(user_ty) => relate_mir_and_user_ty(ocx, param_env, span, mir_ty, user_ty)?,
5151
UserTypeKind::TypeOf(def_id, user_args) => {

‎compiler/rustc_trait_selection/src/traits/query/type_op/implied_outlives_bounds.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
55
use rustc_middle::infer::canonical::CanonicalQueryResponse;
66
use rustc_middle::traits::ObligationCause;
77
use rustc_middle::ty::{self, ParamEnvAnd, Ty, TyCtxt, TypeFolder, TypeVisitableExt};
8-
use rustc_span::DUMMY_SP;
8+
use rustc_span::Span;
99
use rustc_span::def_id::CRATE_DEF_ID;
1010
use rustc_type_ir::outlives::{Component, push_outlives_components};
1111
use smallvec::{SmallVec, smallvec};
@@ -45,11 +45,12 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
4545
fn perform_locally_with_next_solver(
4646
ocx: &ObligationCtxt<'_, 'tcx>,
4747
key: ParamEnvAnd<'tcx, Self>,
48+
span: Span,
4849
) -> Result<Self::QueryResponse, NoSolution> {
4950
if ocx.infcx.tcx.sess.opts.unstable_opts.no_implied_bounds_compat {
50-
compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty)
51+
compute_implied_outlives_bounds_inner(ocx, key.param_env, key.value.ty, span)
5152
} else {
52-
compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty)
53+
compute_implied_outlives_bounds_compat_inner(ocx, key.param_env, key.value.ty, span)
5354
}
5455
}
5556
}
@@ -58,13 +59,14 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
5859
ocx: &ObligationCtxt<'_, 'tcx>,
5960
param_env: ty::ParamEnv<'tcx>,
6061
ty: Ty<'tcx>,
62+
span: Span,
6163
) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
6264
let normalize_op = |ty| -> Result<_, NoSolution> {
6365
// We must normalize the type so we can compute the right outlives components.
6466
// for example, if we have some constrained param type like `T: Trait<Out = U>`,
6567
// and we know that `&'a T::Out` is WF, then we want to imply `U: 'a`.
6668
let ty = ocx
67-
.deeply_normalize(&ObligationCause::dummy(), param_env, ty)
69+
.deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty)
6870
.map_err(|_| NoSolution)?;
6971
if !ocx.select_all_or_error().is_empty() {
7072
return Err(NoSolution);
@@ -142,6 +144,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
142144
ocx: &ObligationCtxt<'_, 'tcx>,
143145
param_env: ty::ParamEnv<'tcx>,
144146
ty: Ty<'tcx>,
147+
span: Span,
145148
) -> Result<Vec<OutlivesBound<'tcx>>, NoSolution> {
146149
let tcx = ocx.infcx.tcx;
147150

@@ -171,8 +174,8 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
171174
// FIXME(@lcnr): It's not really "always fine", having fewer implied
172175
// bounds can be backward incompatible, e.g. #101951 was caused by
173176
// us not dealing with inference vars in `TypeOutlives` predicates.
174-
let obligations = wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, DUMMY_SP)
175-
.unwrap_or_default();
177+
let obligations =
178+
wf::obligations(ocx.infcx, param_env, CRATE_DEF_ID, 0, arg, span).unwrap_or_default();
176179

177180
for obligation in obligations {
178181
debug!(?obligation);
@@ -255,7 +258,7 @@ pub fn compute_implied_outlives_bounds_compat_inner<'tcx>(
255258
// Need to manually normalize in the new solver as `wf::obligations` does not.
256259
if ocx.infcx.next_trait_solver() {
257260
ty_a = ocx
258-
.deeply_normalize(&ObligationCause::dummy(), param_env, ty_a)
261+
.deeply_normalize(&ObligationCause::dummy_with_span(span), param_env, ty_a)
259262
.map_err(|_| NoSolution)?;
260263
}
261264
let mut components = smallvec![];

‎compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ pub trait QueryTypeOp<'tcx>: fmt::Debug + Copy + TypeFoldable<TyCtxt<'tcx>> + 't
9292
fn perform_locally_with_next_solver(
9393
ocx: &ObligationCtxt<'_, 'tcx>,
9494
key: ParamEnvAnd<'tcx, Self>,
95+
span: Span,
9596
) -> Result<Self::QueryResponse, NoSolution>;
9697

9798
fn fully_perform_into(
@@ -152,7 +153,7 @@ where
152153
if infcx.next_trait_solver() {
153154
return Ok(scrape_region_constraints(
154155
infcx,
155-
|ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self),
156+
|ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
156157
"query type op",
157158
span,
158159
)?

‎compiler/rustc_trait_selection/src/traits/query/type_op/normalize.rs

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ use std::fmt;
22

33
use rustc_middle::traits::ObligationCause;
44
use rustc_middle::traits::query::NoSolution;
5-
pub use rustc_middle::traits::query::type_op::Normalize;
5+
pub use rustc_middle::traits::query::type_op::{DeeplyNormalize, Normalize};
66
use rustc_middle::ty::fold::TypeFoldable;
77
use rustc_middle::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
8+
use rustc_span::Span;
89

910
use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
1011
use crate::traits::ObligationCtxt;
@@ -26,12 +27,51 @@ where
2627
T::type_op_method(tcx, canonicalized)
2728
}
2829

30+
fn perform_locally_with_next_solver(
31+
_ocx: &ObligationCtxt<'_, 'tcx>,
32+
key: ParamEnvAnd<'tcx, Self>,
33+
_span: Span,
34+
) -> Result<Self::QueryResponse, NoSolution> {
35+
Ok(key.value.value)
36+
}
37+
}
38+
39+
impl<'tcx, T> super::QueryTypeOp<'tcx> for DeeplyNormalize<T>
40+
where
41+
T: Normalizable<'tcx> + 'tcx,
42+
{
43+
type QueryResponse = T;
44+
45+
fn try_fast_path(_tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>) -> Option<T> {
46+
if !key.value.value.has_aliases() { Some(key.value.value) } else { None }
47+
}
48+
49+
fn perform_query(
50+
tcx: TyCtxt<'tcx>,
51+
canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Self>>,
52+
) -> Result<CanonicalQueryResponse<'tcx, Self::QueryResponse>, NoSolution> {
53+
T::type_op_method(tcx, CanonicalQueryInput {
54+
typing_mode: canonicalized.typing_mode,
55+
canonical: canonicalized.canonical.unchecked_map(
56+
|ty::ParamEnvAnd { param_env, value }| ty::ParamEnvAnd {
57+
param_env,
58+
value: Normalize { value: value.value },
59+
},
60+
),
61+
})
62+
}
63+
2964
fn perform_locally_with_next_solver(
3065
ocx: &ObligationCtxt<'_, 'tcx>,
3166
key: ParamEnvAnd<'tcx, Self>,
67+
span: Span,
3268
) -> Result<Self::QueryResponse, NoSolution> {
33-
// FIXME(-Znext-solver): shouldn't be using old normalizer
34-
Ok(ocx.normalize(&ObligationCause::dummy(), key.param_env, key.value.value))
69+
ocx.deeply_normalize(
70+
&ObligationCause::dummy_with_span(span),
71+
key.param_env,
72+
key.value.value,
73+
)
74+
.map_err(|_| NoSolution)
3575
}
3676
}
3777

@@ -79,3 +119,12 @@ impl<'tcx> Normalizable<'tcx> for ty::FnSig<'tcx> {
79119
tcx.type_op_normalize_fn_sig(canonicalized)
80120
}
81121
}
122+
123+
impl<'tcx> Normalizable<'tcx> for ty::PolyTypeOutlivesPredicate<'tcx> {
124+
fn type_op_method(
125+
_tcx: TyCtxt<'tcx>,
126+
_canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, Normalize<Self>>>,
127+
) -> Result<CanonicalQueryResponse<'tcx, Self>, NoSolution> {
128+
unreachable!("we never normalize PolyTypeOutlivesPredicate")
129+
}
130+
}

‎compiler/rustc_trait_selection/src/traits/query/type_op/outlives.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_middle::traits::query::{DropckOutlivesResult, NoSolution};
22
use rustc_middle::ty::{ParamEnvAnd, TyCtxt};
3+
use rustc_span::Span;
34

45
use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
56
use crate::traits::ObligationCtxt;
@@ -28,7 +29,8 @@ impl<'tcx> super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> {
2829
fn perform_locally_with_next_solver(
2930
ocx: &ObligationCtxt<'_, 'tcx>,
3031
key: ParamEnvAnd<'tcx, Self>,
32+
span: Span,
3133
) -> Result<Self::QueryResponse, NoSolution> {
32-
compute_dropck_outlives_inner(ocx, key.param_env.and(key.value))
34+
compute_dropck_outlives_inner(ocx, key.param_env.and(key.value), span)
3335
}
3436
}

‎compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_middle::traits::ObligationCause;
44
use rustc_middle::traits::query::NoSolution;
55
pub use rustc_middle::traits::query::type_op::ProvePredicate;
66
use rustc_middle::ty::{self, ParamEnvAnd, TyCtxt};
7+
use rustc_span::Span;
78

89
use crate::infer::canonical::{CanonicalQueryInput, CanonicalQueryResponse};
910
use crate::traits::ObligationCtxt;
@@ -57,10 +58,11 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
5758
fn perform_locally_with_next_solver(
5859
ocx: &ObligationCtxt<'_, 'tcx>,
5960
key: ParamEnvAnd<'tcx, Self>,
61+
span: Span,
6062
) -> Result<Self::QueryResponse, NoSolution> {
6163
ocx.register_obligation(Obligation::new(
6264
ocx.infcx.tcx,
63-
ObligationCause::dummy(),
65+
ObligationCause::dummy_with_span(span),
6466
key.param_env,
6567
key.value.predicate,
6668
));

‎compiler/rustc_traits/src/dropck_outlives.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_middle::bug;
66
use rustc_middle::query::Providers;
77
use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult};
88
use rustc_middle::ty::{self, GenericArgs, TyCtxt};
9+
use rustc_span::DUMMY_SP;
910
use rustc_trait_selection::infer::InferCtxtBuilderExt;
1011
use rustc_trait_selection::traits::query::dropck_outlives::{
1112
compute_dropck_outlives_inner, dtorck_constraint_for_ty_inner,
@@ -24,7 +25,7 @@ fn dropck_outlives<'tcx>(
2425
debug!("dropck_outlives(goal={:#?})", canonical_goal);
2526

2627
tcx.infer_ctxt().enter_canonical_trait_query(&canonical_goal, |ocx, goal| {
27-
compute_dropck_outlives_inner(ocx, goal)
28+
compute_dropck_outlives_inner(ocx, goal, DUMMY_SP)
2829
})
2930
}
3031

‎compiler/rustc_traits/src/implied_outlives_bounds.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_infer::traits::query::OutlivesBound;
88
use rustc_infer::traits::query::type_op::ImpliedOutlivesBounds;
99
use rustc_middle::query::Providers;
1010
use rustc_middle::ty::TyCtxt;
11+
use rustc_span::DUMMY_SP;
1112
use rustc_trait_selection::infer::InferCtxtBuilderExt;
1213
use rustc_trait_selection::traits::query::type_op::implied_outlives_bounds::{
1314
compute_implied_outlives_bounds_compat_inner, compute_implied_outlives_bounds_inner,
@@ -28,7 +29,7 @@ fn implied_outlives_bounds_compat<'tcx>(
2829
> {
2930
tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
3031
let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
31-
compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty)
32+
compute_implied_outlives_bounds_compat_inner(ocx, param_env, ty, DUMMY_SP)
3233
})
3334
}
3435

@@ -41,6 +42,6 @@ fn implied_outlives_bounds<'tcx>(
4142
> {
4243
tcx.infer_ctxt().enter_canonical_trait_query(&goal, |ocx, key| {
4344
let (param_env, ImpliedOutlivesBounds { ty }) = key.into_parts();
44-
compute_implied_outlives_bounds_inner(ocx, param_env, ty)
45+
compute_implied_outlives_bounds_inner(ocx, param_env, ty, DUMMY_SP)
4546
})
4647
}

‎compiler/rustc_traits/src/type_op.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_infer::infer::canonical::{Canonical, CanonicalQueryInput, QueryRespons
55
use rustc_middle::query::Providers;
66
use rustc_middle::traits::query::NoSolution;
77
use rustc_middle::ty::{Clause, FnSig, ParamEnvAnd, PolyFnSig, Ty, TyCtxt, TypeFoldable};
8+
use rustc_span::DUMMY_SP;
89
use rustc_trait_selection::infer::InferCtxtBuilderExt;
910
use rustc_trait_selection::traits::query::type_op::ascribe_user_type::{
1011
AscribeUserType, type_op_ascribe_user_type_with_span,
@@ -30,7 +31,7 @@ fn type_op_ascribe_user_type<'tcx>(
3031
canonicalized: CanonicalQueryInput<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>,
3132
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, NoSolution> {
3233
tcx.infer_ctxt().enter_canonical_trait_query(&canonicalized, |ocx, key| {
33-
type_op_ascribe_user_type_with_span(ocx, key, None)
34+
type_op_ascribe_user_type_with_span(ocx, key, DUMMY_SP)
3435
})
3536
}
3637

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
// Make sure that we can normalize `<T as Ref<'a>>::Assoc` to `&'a T` and get
7+
// its implied bounds in impl header.
8+
9+
trait Ref<'a> {
10+
type Assoc;
11+
}
12+
impl<'a, T> Ref<'a> for T where T: 'a {
13+
type Assoc = &'a T;
14+
}
15+
16+
fn outlives<'a, T: 'a>() {}
17+
18+
trait Trait<'a, T> {
19+
fn test();
20+
}
21+
22+
impl<'a, T> Trait<'a, T> for <T as Ref<'a>>::Assoc {
23+
fn test() {
24+
outlives::<'a, T>();
25+
}
26+
}
27+
28+
fn main() {}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ check-pass
2+
//@ revisions: current next
3+
//@ ignore-compare-mode-next-solver (explicit revisions)
4+
//@[next] compile-flags: -Znext-solver
5+
6+
// Make sure that we can normalize `<T as Ref<'a>>::Assoc` to `&'a T` and get
7+
// its implied bounds.
8+
9+
trait Ref<'a> {
10+
type Assoc;
11+
}
12+
impl<'a, T> Ref<'a> for T where T: 'a {
13+
type Assoc = &'a T;
14+
}
15+
16+
fn outlives<'a, T: 'a>() {}
17+
18+
fn test<'a, T>(_: <T as Ref<'a>>::Assoc) {
19+
outlives::<'a, T>();
20+
}
21+
22+
fn main() {}

‎tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0733]: recursion in a coroutine requires boxing
2-
--> $DIR/recursive-coroutine-indirect.rs:11:18
2+
--> $DIR/recursive-coroutine-indirect.rs:13:18
33
|
44
LL | #[coroutine] move || {
55
| ^^^^^^^

‎tests/ui/impl-trait/recursive-coroutine-indirect.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22
//@ ignore-compare-mode-next-solver (explicit revisions)
33
//@[next] compile-flags: -Znext-solver
44

5-
//@[next] build-fail
5+
//@[next] known-bug: unknown
6+
//@[next] failure-status: 101
7+
//@[next] dont-check-compiler-stderr
68
// Deeply normalizing writeback results of opaques makes this into a post-mono error :(
79

810
#![feature(coroutines)]
911
#![allow(unconditional_recursion)]
1012
fn coroutine_hold() -> impl Sized {
11-
#[coroutine] move || { //~ ERROR recursion in a coroutine requires boxing
13+
#[coroutine] move || { //[current]~ ERROR recursion in a coroutine requires boxing
1214
let x = coroutine_hold();
1315
yield;
1416
x;

‎tests/ui/nll/check-normalized-sig-for-wf.stderr renamed to ‎tests/ui/nll/check-normalized-sig-for-wf.current.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0597]: `s` does not live long enough
2-
--> $DIR/check-normalized-sig-for-wf.rs:7:7
2+
--> $DIR/check-normalized-sig-for-wf.rs:11:7
33
|
44
LL | s: String,
55
| - binding `s` declared here
@@ -14,7 +14,7 @@ LL | }
1414
| - `s` dropped here while still borrowed
1515

1616
error[E0521]: borrowed data escapes outside of function
17-
--> $DIR/check-normalized-sig-for-wf.rs:15:5
17+
--> $DIR/check-normalized-sig-for-wf.rs:19:5
1818
|
1919
LL | fn extend<T>(input: &T) -> &'static T {
2020
| ----- - let's call the lifetime of this reference `'1`
@@ -28,7 +28,7 @@ LL | n(input).0
2828
| argument requires that `'1` must outlive `'static`
2929

3030
error[E0521]: borrowed data escapes outside of function
31-
--> $DIR/check-normalized-sig-for-wf.rs:23:5
31+
--> $DIR/check-normalized-sig-for-wf.rs:27:5
3232
|
3333
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
3434
| -- ----- `input` is a reference that is only valid in the function body
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
error[E0597]: `s` does not live long enough
2+
--> $DIR/check-normalized-sig-for-wf.rs:11:7
3+
|
4+
LL | s: String,
5+
| - binding `s` declared here
6+
...
7+
LL | f(&s).0
8+
| --^^-
9+
| | |
10+
| | borrowed value does not live long enough
11+
| argument requires that `s` is borrowed for `'static`
12+
LL |
13+
LL | }
14+
| - `s` dropped here while still borrowed
15+
16+
error[E0521]: borrowed data escapes outside of function
17+
--> $DIR/check-normalized-sig-for-wf.rs:19:5
18+
|
19+
LL | fn extend<T>(input: &T) -> &'static T {
20+
| ----- - let's call the lifetime of this reference `'1`
21+
| |
22+
| `input` is a reference that is only valid in the function body
23+
...
24+
LL | n(input).0
25+
| ^^^^^^^^
26+
| |
27+
| `input` escapes the function body here
28+
| argument requires that `'1` must outlive `'static`
29+
30+
error[E0521]: borrowed data escapes outside of function
31+
--> $DIR/check-normalized-sig-for-wf.rs:27:5
32+
|
33+
LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T {
34+
| -- ----- `input` is a reference that is only valid in the function body
35+
| |
36+
| lifetime `'a` defined here
37+
...
38+
LL | n(input).0
39+
| ^^^^^^^^
40+
| |
41+
| `input` escapes the function body here
42+
| argument requires that `'a` must outlive `'static`
43+
44+
error: aborting due to 3 previous errors
45+
46+
Some errors have detailed explanations: E0521, E0597.
47+
For more information about an error, try `rustc --explain E0521`.

‎tests/ui/nll/check-normalized-sig-for-wf.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
//@ revisions: current next
2+
//@ ignore-compare-mode-next-solver (explicit revisions)
3+
//@[next] compile-flags: -Znext-solver
4+
15
// <https://github.com/rust-lang/rust/issues/114936>
26
fn whoops(
37
s: String,

0 commit comments

Comments
 (0)
Please sign in to comment.