Skip to content

Commit 901664a

Browse files
BoxyUwUcamelid
authored andcommitted
setup canonical normalization for const norm
1 parent d85276b commit 901664a

File tree

5 files changed

+125
-98
lines changed

5 files changed

+125
-98
lines changed

compiler/rustc_middle/src/arena.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ macro_rules! arena_types {
4444
rustc_middle::traits::query::DropckOutlivesResult<'tcx>
4545
>
4646
>,
47-
[] normalize_canonicalized_projection_ty:
47+
[] normalize_canonicalized_projection:
4848
rustc_middle::infer::canonical::Canonical<'tcx,
4949
rustc_middle::infer::canonical::QueryResponse<'tcx,
5050
rustc_middle::traits::query::NormalizationResult<'tcx>

compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,7 +2411,7 @@ rustc_queries! {
24112411
/// Do not call this query directly: Invoke `normalize` instead.
24122412
///
24132413
/// </div>
2414-
query normalize_canonicalized_projection_ty(
2414+
query normalize_canonicalized_projection(
24152415
goal: CanonicalAliasGoal<'tcx>
24162416
) -> Result<
24172417
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,
@@ -2439,7 +2439,7 @@ rustc_queries! {
24392439
/// Do not call this query directly: Invoke `normalize` instead.
24402440
///
24412441
/// </div>
2442-
query normalize_canonicalized_inherent_projection_ty(
2442+
query normalize_canonicalized_inherent_projection(
24432443
goal: CanonicalAliasGoal<'tcx>
24442444
) -> Result<
24452445
&'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>,

compiler/rustc_middle/src/traits/query.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub mod type_op {
6666
}
6767

6868
pub type CanonicalAliasGoal<'tcx> =
69-
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTy<'tcx>>>;
69+
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, ty::AliasTerm<'tcx>>>;
7070

7171
pub type CanonicalMethodAutoderefStepsGoal<'tcx> =
7272
CanonicalQueryInput<'tcx, ty::ParamEnvAnd<'tcx, MethodAutoderefSteps<'tcx>>>;
@@ -192,11 +192,11 @@ pub struct MethodAutoderefBadTy<'tcx> {
192192
pub ty: Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>,
193193
}
194194

195-
/// Result of the `normalize_canonicalized_{{,inherent_}projection,free}_ty` queries.
195+
/// Result of the `normalize_canonicalized_{{,inherent_}projection,free}` queries.
196196
#[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable)]
197197
pub struct NormalizationResult<'tcx> {
198198
/// Result of the normalization.
199-
pub normalized_ty: Ty<'tcx>,
199+
pub normalized_term: ty::Term<'tcx>,
200200
}
201201

202202
/// Outlives bounds are relationships between generic parameters,

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

Lines changed: 103 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
//! Code for the 'normalization' query. This consists of a wrapper
22
//! which folds deeply, invoking the underlying
3-
//! `normalize_canonicalized_projection_ty` query when it encounters projections.
3+
//! `normalize_canonicalized_projection` query when it encounters projections.
44
55
use rustc_data_structures::sso::SsoHashMap;
66
use rustc_data_structures::stack::ensure_sufficient_stack;
7+
use rustc_hir::def::DefKind;
78
use rustc_infer::traits::PredicateObligations;
89
use rustc_macros::extension;
910
pub use rustc_middle::traits::query::NormalizationResult;
@@ -255,76 +256,9 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
255256
}
256257
}
257258

258-
ty::Projection | ty::Inherent | ty::Free => {
259-
// See note in `rustc_trait_selection::traits::project`
260-
261-
let infcx = self.infcx;
262-
let tcx = infcx.tcx;
263-
// Just an optimization: When we don't have escaping bound vars,
264-
// we don't need to replace them with placeholders.
265-
let (data, maps) = if data.has_escaping_bound_vars() {
266-
let (data, mapped_regions, mapped_types, mapped_consts) =
267-
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
268-
(data, Some((mapped_regions, mapped_types, mapped_consts)))
269-
} else {
270-
(data, None)
271-
};
272-
let data = data.try_fold_with(self)?;
273-
274-
let mut orig_values = OriginalQueryValues::default();
275-
let c_data = infcx.canonicalize_query(self.param_env.and(data), &mut orig_values);
276-
debug!("QueryNormalizer: c_data = {:#?}", c_data);
277-
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
278-
let result = match kind {
279-
ty::Projection => tcx.normalize_canonicalized_projection_ty(c_data),
280-
ty::Free => tcx.normalize_canonicalized_free_alias(c_data),
281-
ty::Inherent => tcx.normalize_canonicalized_inherent_projection_ty(c_data),
282-
kind => unreachable!("did not expect {kind:?} due to match arm above"),
283-
}?;
284-
// We don't expect ambiguity.
285-
if !result.value.is_proven() {
286-
// Rustdoc normalizes possibly not well-formed types, so only
287-
// treat this as a bug if we're not in rustdoc.
288-
if !tcx.sess.opts.actually_rustdoc {
289-
tcx.dcx()
290-
.delayed_bug(format!("unexpected ambiguity: {c_data:?} {result:?}"));
291-
}
292-
return Err(NoSolution);
293-
}
294-
let InferOk { value: result, obligations } = infcx
295-
.instantiate_query_response_and_region_obligations(
296-
self.cause,
297-
self.param_env,
298-
&orig_values,
299-
result,
300-
)?;
301-
debug!("QueryNormalizer: result = {:#?}", result);
302-
debug!("QueryNormalizer: obligations = {:#?}", obligations);
303-
self.obligations.extend(obligations);
304-
let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps {
305-
PlaceholderReplacer::replace_placeholders(
306-
infcx,
307-
mapped_regions,
308-
mapped_types,
309-
mapped_consts,
310-
&self.universes,
311-
result.normalized_ty,
312-
)
313-
} else {
314-
result.normalized_ty
315-
};
316-
// `tcx.normalize_canonicalized_projection_ty` may normalize to a type that
317-
// still has unevaluated consts, so keep normalizing here if that's the case.
318-
// Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer
319-
// of type and we need to continue folding it to reveal the TAIT behind it.
320-
if res != ty
321-
&& (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || kind == ty::Free)
322-
{
323-
res.try_fold_with(self)?
324-
} else {
325-
res
326-
}
327-
}
259+
ty::Projection | ty::Inherent | ty::Free => self
260+
.try_fold_free_or_assoc(ty::AliasTerm::new(self.cx(), data.def_id, data.args))?
261+
.expect_type(),
328262
};
329263

330264
self.cache.insert(ty, res);
@@ -339,12 +273,22 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
339273
return Ok(constant);
340274
}
341275

342-
let constant = crate::traits::with_replaced_escaping_bound_vars(
343-
self.infcx,
344-
&mut self.universes,
345-
constant,
346-
|constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env),
347-
);
276+
let uv = match constant.kind() {
277+
ty::ConstKind::Unevaluated(uv) => uv,
278+
_ => return constant.try_super_fold_with(self),
279+
};
280+
281+
let constant = match self.cx().def_kind(uv.def) {
282+
DefKind::AnonConst => crate::traits::with_replaced_escaping_bound_vars(
283+
self.infcx,
284+
&mut self.universes,
285+
constant,
286+
|constant| crate::traits::evaluate_const(&self.infcx, constant, self.param_env),
287+
),
288+
_ => self
289+
.try_fold_free_or_assoc(ty::AliasTerm::new(self.cx(), uv.def, uv.args))?
290+
.expect_const(),
291+
};
348292
debug!(?constant, ?self.param_env);
349293
constant.try_super_fold_with(self)
350294
}
@@ -361,3 +305,85 @@ impl<'a, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'a, 'tcx> {
361305
}
362306
}
363307
}
308+
309+
impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> {
310+
fn try_fold_free_or_assoc(
311+
&mut self,
312+
term: ty::AliasTerm<'tcx>,
313+
) -> Result<ty::Term<'tcx>, NoSolution> {
314+
let infcx = self.infcx;
315+
let tcx = infcx.tcx;
316+
// Just an optimization: When we don't have escaping bound vars,
317+
// we don't need to replace them with placeholders.
318+
let (term, maps) = if term.has_escaping_bound_vars() {
319+
let (term, mapped_regions, mapped_types, mapped_consts) =
320+
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, term);
321+
(term, Some((mapped_regions, mapped_types, mapped_consts)))
322+
} else {
323+
(term, None)
324+
};
325+
let term = term.try_fold_with(self)?;
326+
327+
let mut orig_values = OriginalQueryValues::default();
328+
let c_term = infcx.canonicalize_query(self.param_env.and(term), &mut orig_values);
329+
debug!("QueryNormalizer: c_term = {:#?}", c_term);
330+
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
331+
let result = match term.kind(tcx) {
332+
ty::AliasTermKind::ProjectionTy | ty::AliasTermKind::ProjectionConst => {
333+
tcx.normalize_canonicalized_projection(c_term)
334+
}
335+
ty::AliasTermKind::FreeTy | ty::AliasTermKind::FreeConst => {
336+
tcx.normalize_canonicalized_free_alias(c_term)
337+
}
338+
ty::AliasTermKind::InherentTy | ty::AliasTermKind::InherentConst => {
339+
tcx.normalize_canonicalized_inherent_projection(c_term)
340+
}
341+
kind @ (ty::AliasTermKind::OpaqueTy | ty::AliasTermKind::UnevaluatedConst) => {
342+
unreachable!("did not expect {kind:?} due to match arm above")
343+
}
344+
}?;
345+
// We don't expect ambiguity.
346+
if !result.value.is_proven() {
347+
// Rustdoc normalizes possibly not well-formed types, so only
348+
// treat this as a bug if we're not in rustdoc.
349+
if !tcx.sess.opts.actually_rustdoc {
350+
tcx.dcx().delayed_bug(format!("unexpected ambiguity: {c_term:?} {result:?}"));
351+
}
352+
return Err(NoSolution);
353+
}
354+
let InferOk { value: result, obligations } = infcx
355+
.instantiate_query_response_and_region_obligations(
356+
self.cause,
357+
self.param_env,
358+
&orig_values,
359+
result,
360+
)?;
361+
debug!("QueryNormalizer: result = {:#?}", result);
362+
debug!("QueryNormalizer: obligations = {:#?}", obligations);
363+
self.obligations.extend(obligations);
364+
let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps {
365+
PlaceholderReplacer::replace_placeholders(
366+
infcx,
367+
mapped_regions,
368+
mapped_types,
369+
mapped_consts,
370+
&self.universes,
371+
result.normalized_term,
372+
)
373+
} else {
374+
result.normalized_term
375+
};
376+
// `tcx.normalize_canonicalized_projection` may normalize to a type that
377+
// still has unevaluated consts, so keep normalizing here if that's the case.
378+
// Similarly, `tcx.normalize_canonicalized_free_alias` will only unwrap one layer
379+
// of type and we need to continue folding it to reveal the TAIT behind it.
380+
if res != term.to_term(tcx)
381+
&& (res.as_type().map_or(false, |t| t.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION))
382+
|| term.kind(tcx) == ty::AliasTermKind::FreeTy)
383+
{
384+
res.try_fold_with(self)
385+
} else {
386+
Ok(res)
387+
}
388+
}
389+
}

compiler/rustc_traits/src/normalize_projection_ty.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,18 @@ use tracing::debug;
1212

1313
pub(crate) fn provide(p: &mut Providers) {
1414
*p = Providers {
15-
normalize_canonicalized_projection_ty,
15+
normalize_canonicalized_projection,
1616
normalize_canonicalized_free_alias,
17-
normalize_canonicalized_inherent_projection_ty,
17+
normalize_canonicalized_inherent_projection,
1818
..*p
1919
};
2020
}
2121

22-
fn normalize_canonicalized_projection_ty<'tcx>(
22+
fn normalize_canonicalized_projection<'tcx>(
2323
tcx: TyCtxt<'tcx>,
2424
goal: CanonicalAliasGoal<'tcx>,
2525
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
26-
debug!("normalize_canonicalized_projection_ty(goal={:#?})", goal);
26+
debug!("normalize_canonicalized_projection(goal={:#?})", goal);
2727

2828
tcx.infer_ctxt().enter_canonical_trait_query(
2929
&goal,
@@ -32,7 +32,7 @@ fn normalize_canonicalized_projection_ty<'tcx>(
3232
let selcx = &mut SelectionContext::new(ocx.infcx);
3333
let cause = ObligationCause::dummy();
3434
let mut obligations = PredicateObligations::new();
35-
let answer = traits::normalize_projection_term(
35+
let normalized_term = traits::normalize_projection_term(
3636
selcx,
3737
param_env,
3838
goal.into(),
@@ -61,10 +61,7 @@ fn normalize_canonicalized_projection_ty<'tcx>(
6161
return Err(NoSolution);
6262
}
6363

64-
// FIXME(associated_const_equality): All users of normalize_canonicalized_projection_ty
65-
// expected a type, but there is the possibility it could've been a const now.
66-
// Maybe change it to a Term later?
67-
Ok(NormalizationResult { normalized_ty: answer.expect_type() })
64+
Ok(NormalizationResult { normalized_term })
6865
},
6966
)
7067
}
@@ -89,25 +86,29 @@ fn normalize_canonicalized_free_alias<'tcx>(
8986
},
9087
);
9188
ocx.register_obligations(obligations);
92-
let normalized_ty = tcx.type_of(goal.def_id).instantiate(tcx, goal.args);
93-
Ok(NormalizationResult { normalized_ty })
89+
let normalized_term = if goal.kind(tcx).is_type() {
90+
tcx.type_of(goal.def_id).instantiate(tcx, goal.args).into()
91+
} else {
92+
todo!()
93+
};
94+
Ok(NormalizationResult { normalized_term })
9495
},
9596
)
9697
}
9798

98-
fn normalize_canonicalized_inherent_projection_ty<'tcx>(
99+
fn normalize_canonicalized_inherent_projection<'tcx>(
99100
tcx: TyCtxt<'tcx>,
100101
goal: CanonicalAliasGoal<'tcx>,
101102
) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution> {
102-
debug!("normalize_canonicalized_inherent_projection_ty(goal={:#?})", goal);
103+
debug!("normalize_canonicalized_inherent_projection(goal={:#?})", goal);
103104

104105
tcx.infer_ctxt().enter_canonical_trait_query(
105106
&goal,
106107
|ocx, ParamEnvAnd { param_env, value: goal }| {
107108
let selcx = &mut SelectionContext::new(ocx.infcx);
108109
let cause = ObligationCause::dummy();
109110
let mut obligations = PredicateObligations::new();
110-
let answer = traits::normalize_inherent_projection(
111+
let normalized_term = traits::normalize_inherent_projection(
111112
selcx,
112113
param_env,
113114
goal.into(),
@@ -117,7 +118,7 @@ fn normalize_canonicalized_inherent_projection_ty<'tcx>(
117118
);
118119
ocx.register_obligations(obligations);
119120

120-
Ok(NormalizationResult { normalized_ty: answer.expect_type() })
121+
Ok(NormalizationResult { normalized_term })
121122
},
122123
)
123124
}

0 commit comments

Comments
 (0)