Skip to content

Commit 113e815

Browse files
authored
Rollup merge of #109171 - oli-obk:normalization_cleanup, r=compiler-errors
Some cleanups in our normalization logic Changed a match to be exhaustive and deduplicated some code. r? ```@compiler-errors``` this pulls out the uncontroversial part of #108860
2 parents f0205d5 + d87fbb9 commit 113e815

File tree

2 files changed

+48
-77
lines changed

2 files changed

+48
-77
lines changed

compiler/rustc_trait_selection/src/traits/project.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,11 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
468468
return ty;
469469
}
470470

471+
let (kind, data) = match *ty.kind() {
472+
ty::Alias(kind, alias_ty) => (kind, alias_ty),
473+
_ => return ty.super_fold_with(self),
474+
};
475+
471476
// We try to be a little clever here as a performance optimization in
472477
// cases where there are nested projections under binders.
473478
// For example:
@@ -491,13 +496,11 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
491496
// replace bound vars if the current type is a `Projection` and we need
492497
// to make sure we don't forget to fold the substs regardless.
493498

494-
match *ty.kind() {
499+
match kind {
495500
// This is really important. While we *can* handle this, this has
496501
// severe performance implications for large opaque types with
497502
// late-bound regions. See `issue-88862` benchmark.
498-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
499-
if !substs.has_escaping_bound_vars() =>
500-
{
503+
ty::Opaque if !data.substs.has_escaping_bound_vars() => {
501504
// Only normalize `impl Trait` outside of type inference, usually in codegen.
502505
match self.param_env.reveal() {
503506
Reveal::UserFacing => ty.super_fold_with(self),
@@ -513,8 +516,8 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
513516
);
514517
}
515518

516-
let substs = substs.fold_with(self);
517-
let generic_ty = self.interner().type_of(def_id);
519+
let substs = data.substs.fold_with(self);
520+
let generic_ty = self.interner().type_of(data.def_id);
518521
let concrete_ty = generic_ty.subst(self.interner(), substs);
519522
self.depth += 1;
520523
let folded_ty = self.fold_ty(concrete_ty);
@@ -523,8 +526,9 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
523526
}
524527
}
525528
}
529+
ty::Opaque => ty.super_fold_with(self),
526530

527-
ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
531+
ty::Projection if !data.has_escaping_bound_vars() => {
528532
// This branch is *mostly* just an optimization: when we don't
529533
// have escaping bound vars, we don't need to replace them with
530534
// placeholders (see branch below). *Also*, we know that we can
@@ -563,7 +567,7 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
563567
normalized_ty.ty().unwrap()
564568
}
565569

566-
ty::Alias(ty::Projection, data) => {
570+
ty::Projection => {
567571
// If there are escaping bound vars, we temporarily replace the
568572
// bound vars with placeholders. Note though, that in the case
569573
// that we still can't project for whatever reason (e.g. self
@@ -612,8 +616,6 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
612616
);
613617
normalized_ty
614618
}
615-
616-
_ => ty.super_fold_with(self),
617619
}
618620
}
619621

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

+36-67
Original file line numberDiff line numberDiff line change
@@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
197197
return Ok(*ty);
198198
}
199199

200+
let (kind, data) = match *ty.kind() {
201+
ty::Alias(kind, data) => (kind, data),
202+
_ => {
203+
let res = ty.try_super_fold_with(self)?;
204+
self.cache.insert(ty, res);
205+
return Ok(res);
206+
}
207+
};
208+
200209
// See note in `rustc_trait_selection::traits::project` about why we
201210
// wait to fold the substs.
202211

203212
// Wrap this in a closure so we don't accidentally return from the outer function
204-
let res = match *ty.kind() {
213+
let res = match kind {
205214
// This is really important. While we *can* handle this, this has
206215
// severe performance implications for large opaque types with
207216
// late-bound regions. See `issue-88862` benchmark.
208-
ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. })
209-
if !substs.has_escaping_bound_vars() =>
210-
{
217+
ty::Opaque if !data.substs.has_escaping_bound_vars() => {
211218
// Only normalize `impl Trait` outside of type inference, usually in codegen.
212219
match self.param_env.reveal() {
213220
Reveal::UserFacing => ty.try_super_fold_with(self)?,
214221

215222
Reveal::All => {
216-
let substs = substs.try_fold_with(self)?;
223+
let substs = data.substs.try_fold_with(self)?;
217224
let recursion_limit = self.interner().recursion_limit();
218225
if !recursion_limit.value_within_limit(self.anon_depth) {
219226
// A closure or generator may have itself as in its upvars.
@@ -228,7 +235,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
228235
return ty.try_super_fold_with(self);
229236
}
230237

231-
let generic_ty = self.interner().type_of(def_id);
238+
let generic_ty = self.interner().type_of(data.def_id);
232239
let concrete_ty = generic_ty.subst(self.interner(), substs);
233240
self.anon_depth += 1;
234241
if concrete_ty == ty {
@@ -248,62 +255,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
248255
}
249256
}
250257

251-
ty::Alias(ty::Projection, data) if !data.has_escaping_bound_vars() => {
252-
// This branch is just an optimization: when we don't have escaping bound vars,
253-
// we don't need to replace them with placeholders (see branch below).
254-
255-
let tcx = self.infcx.tcx;
256-
let data = data.try_fold_with(self)?;
257-
258-
let mut orig_values = OriginalQueryValues::default();
259-
// HACK(matthewjasper) `'static` is special-cased in selection,
260-
// so we cannot canonicalize it.
261-
let c_data = self
262-
.infcx
263-
.canonicalize_query_keep_static(self.param_env.and(data), &mut orig_values);
264-
debug!("QueryNormalizer: c_data = {:#?}", c_data);
265-
debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
266-
let result = tcx.normalize_projection_ty(c_data)?;
267-
// We don't expect ambiguity.
268-
if result.is_ambiguous() {
269-
// Rustdoc normalizes possibly not well-formed types, so only
270-
// treat this as a bug if we're not in rustdoc.
271-
if !tcx.sess.opts.actually_rustdoc {
272-
tcx.sess.delay_span_bug(
273-
DUMMY_SP,
274-
format!("unexpected ambiguity: {:?} {:?}", c_data, result),
275-
);
276-
}
277-
return Err(NoSolution);
278-
}
279-
let InferOk { value: result, obligations } =
280-
self.infcx.instantiate_query_response_and_region_obligations(
281-
self.cause,
282-
self.param_env,
283-
&orig_values,
284-
result,
285-
)?;
286-
debug!("QueryNormalizer: result = {:#?}", result);
287-
debug!("QueryNormalizer: obligations = {:#?}", obligations);
288-
self.obligations.extend(obligations);
289-
290-
let res = result.normalized_ty;
291-
// `tcx.normalize_projection_ty` may normalize to a type that still has
292-
// unevaluated consts, so keep normalizing here if that's the case.
293-
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
294-
res.try_super_fold_with(self)?
295-
} else {
296-
res
297-
}
298-
}
258+
ty::Opaque => ty.try_super_fold_with(self)?,
299259

300-
ty::Alias(ty::Projection, data) => {
260+
ty::Projection => {
301261
// See note in `rustc_trait_selection::traits::project`
302262

303263
let tcx = self.infcx.tcx;
304264
let infcx = self.infcx;
305-
let (data, mapped_regions, mapped_types, mapped_consts) =
306-
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
265+
// Just an optimization: When we don't have escaping bound vars,
266+
// we don't need to replace them with placeholders.
267+
let (data, maps) = if data.has_escaping_bound_vars() {
268+
let (data, mapped_regions, mapped_types, mapped_consts) =
269+
BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, data);
270+
(data, Some((mapped_regions, mapped_types, mapped_consts)))
271+
} else {
272+
(data, None)
273+
};
307274
let data = data.try_fold_with(self)?;
308275

309276
let mut orig_values = OriginalQueryValues::default();
@@ -337,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
337304
debug!("QueryNormalizer: result = {:#?}", result);
338305
debug!("QueryNormalizer: obligations = {:#?}", obligations);
339306
self.obligations.extend(obligations);
340-
let res = PlaceholderReplacer::replace_placeholders(
341-
infcx,
342-
mapped_regions,
343-
mapped_types,
344-
mapped_consts,
345-
&self.universes,
346-
result.normalized_ty,
347-
);
307+
let res = if let Some((mapped_regions, mapped_types, mapped_consts)) = maps {
308+
PlaceholderReplacer::replace_placeholders(
309+
infcx,
310+
mapped_regions,
311+
mapped_types,
312+
mapped_consts,
313+
&self.universes,
314+
result.normalized_ty,
315+
)
316+
} else {
317+
result.normalized_ty
318+
};
348319
// `tcx.normalize_projection_ty` may normalize to a type that still has
349320
// unevaluated consts, so keep normalizing here if that's the case.
350321
if res != ty && res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) {
@@ -353,8 +324,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
353324
res
354325
}
355326
}
356-
357-
_ => ty.try_super_fold_with(self)?,
358327
};
359328

360329
self.cache.insert(ty, res);

0 commit comments

Comments
 (0)