Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 9eb69e8

Browse files
committed
Move ReverseMapper logic onto OpaqueHiddenType
1 parent d643ae1 commit 9eb69e8

File tree

5 files changed

+247
-233
lines changed

5 files changed

+247
-233
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 7 additions & 224 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use rustc_hir::OpaqueTyOrigin;
55
use rustc_infer::infer::TyCtxtInferExt as _;
66
use rustc_infer::infer::{DefiningAnchor, InferCtxt};
77
use rustc_infer::traits::{Obligation, ObligationCause, TraitEngine};
8-
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
9-
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, InternalSubsts};
8+
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts};
109
use rustc_middle::ty::visit::TypeVisitable;
1110
use rustc_middle::ty::{
1211
self, OpaqueHiddenType, OpaqueTypeKey, ToPredicate, Ty, TyCtxt, TypeFoldable,
@@ -15,8 +14,6 @@ use rustc_span::Span;
1514
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
1615
use rustc_trait_selection::traits::TraitEngineExt as _;
1716

18-
use crate::session_diagnostics::ConstNotUsedTraitAlias;
19-
2017
use super::RegionInferenceContext;
2118

2219
impl<'tcx> RegionInferenceContext<'tcx> {
@@ -228,29 +225,9 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
228225
return self.tcx.ty_error();
229226
}
230227

231-
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
232-
233-
// Use substs to build up a reverse map from regions to their
234-
// identity mappings. This is necessary because of `impl
235-
// Trait` lifetimes are computed by replacing existing
236-
// lifetimes with 'static and remapping only those used in the
237-
// `impl Trait` return type, resulting in the parameters
238-
// shifting.
239-
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
240-
debug!(?id_substs);
241-
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
242-
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
243-
debug!("map = {:#?}", map);
244-
245-
// Convert the type from the function into a type valid outside
246-
// the function, by replacing invalid regions with 'static,
247-
// after producing an error for each of them.
248-
let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
249-
self.tcx,
250-
map,
251-
instantiated_ty.span,
252-
));
253-
debug!(?definition_ty);
228+
let definition_ty = instantiated_ty
229+
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx)
230+
.ty;
254231

255232
if !check_opaque_type_parameter_valid(
256233
self.tcx,
@@ -266,6 +243,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
266243
let OpaqueTyOrigin::TyAlias = origin else {
267244
return definition_ty;
268245
};
246+
let def_id = opaque_type_key.def_id;
269247
// This logic duplicates most of `check_opaque_meets_bounds`.
270248
// FIXME(oli-obk): Also do region checks here and then consider removing `check_opaque_meets_bounds` entirely.
271249
let param_env = self.tcx.param_env(def_id);
@@ -281,6 +259,8 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
281259
.to_predicate(infcx.tcx);
282260
let mut fulfillment_cx = <dyn TraitEngine<'tcx>>::new(infcx.tcx);
283261

262+
let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id.to_def_id());
263+
284264
// Require that the hidden type actually fulfills all the bounds of the opaque type, even without
285265
// the bounds that the function supplies.
286266
match infcx.register_hidden_type(
@@ -421,200 +401,3 @@ fn check_opaque_type_parameter_valid(
421401
}
422402
true
423403
}
424-
425-
struct ReverseMapper<'tcx> {
426-
tcx: TyCtxt<'tcx>,
427-
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
428-
do_not_error: bool,
429-
430-
/// Span of function being checked.
431-
span: Span,
432-
}
433-
434-
impl<'tcx> ReverseMapper<'tcx> {
435-
fn new(
436-
tcx: TyCtxt<'tcx>,
437-
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
438-
span: Span,
439-
) -> Self {
440-
Self { tcx, map, do_not_error: false, span }
441-
}
442-
443-
fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
444-
assert!(!self.do_not_error);
445-
self.do_not_error = true;
446-
let kind = kind.fold_with(self);
447-
self.do_not_error = false;
448-
kind
449-
}
450-
451-
fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
452-
assert!(!self.do_not_error);
453-
kind.fold_with(self)
454-
}
455-
}
456-
457-
impl<'tcx> TypeFolder<'tcx> for ReverseMapper<'tcx> {
458-
fn tcx(&self) -> TyCtxt<'tcx> {
459-
self.tcx
460-
}
461-
462-
#[instrument(skip(self), level = "debug")]
463-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
464-
match *r {
465-
// Ignore bound regions and `'static` regions that appear in the
466-
// type, we only need to remap regions that reference lifetimes
467-
// from the function declaration.
468-
// This would ignore `'r` in a type like `for<'r> fn(&'r u32)`.
469-
ty::ReLateBound(..) | ty::ReStatic => return r,
470-
471-
// If regions have been erased (by writeback), don't try to unerase
472-
// them.
473-
ty::ReErased => return r,
474-
475-
// The regions that we expect from borrow checking.
476-
ty::ReEarlyBound(_) | ty::ReFree(_) => {}
477-
478-
ty::RePlaceholder(_) | ty::ReVar(_) => {
479-
// All of the regions in the type should either have been
480-
// erased by writeback, or mapped back to named regions by
481-
// borrow checking.
482-
bug!("unexpected region kind in opaque type: {:?}", r);
483-
}
484-
}
485-
486-
match self.map.get(&r.into()).map(|k| k.unpack()) {
487-
Some(GenericArgKind::Lifetime(r1)) => r1,
488-
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
489-
None if self.do_not_error => self.tcx.lifetimes.re_static,
490-
None => {
491-
self.tcx
492-
.sess
493-
.struct_span_err(self.span, "non-defining opaque type use in defining scope")
494-
.span_label(
495-
self.span,
496-
format!(
497-
"lifetime `{}` is part of concrete type but not used in \
498-
parameter list of the `impl Trait` type alias",
499-
r
500-
),
501-
)
502-
.emit();
503-
504-
self.tcx().lifetimes.re_static
505-
}
506-
}
507-
}
508-
509-
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
510-
match *ty.kind() {
511-
ty::Closure(def_id, substs) => {
512-
// I am a horrible monster and I pray for death. When
513-
// we encounter a closure here, it is always a closure
514-
// from within the function that we are currently
515-
// type-checking -- one that is now being encapsulated
516-
// in an opaque type. Ideally, we would
517-
// go through the types/lifetimes that it references
518-
// and treat them just like we would any other type,
519-
// which means we would error out if we find any
520-
// reference to a type/region that is not in the
521-
// "reverse map".
522-
//
523-
// **However,** in the case of closures, there is a
524-
// somewhat subtle (read: hacky) consideration. The
525-
// problem is that our closure types currently include
526-
// all the lifetime parameters declared on the
527-
// enclosing function, even if they are unused by the
528-
// closure itself. We can't readily filter them out,
529-
// so here we replace those values with `'empty`. This
530-
// can't really make a difference to the rest of the
531-
// compiler; those regions are ignored for the
532-
// outlives relation, and hence don't affect trait
533-
// selection or auto traits, and they are erased
534-
// during codegen.
535-
536-
let generics = self.tcx.generics_of(def_id);
537-
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
538-
if index < generics.parent_count {
539-
// Accommodate missing regions in the parent kinds...
540-
self.fold_kind_no_missing_regions_error(kind)
541-
} else {
542-
// ...but not elsewhere.
543-
self.fold_kind_normally(kind)
544-
}
545-
}));
546-
547-
self.tcx.mk_closure(def_id, substs)
548-
}
549-
550-
ty::Generator(def_id, substs, movability) => {
551-
let generics = self.tcx.generics_of(def_id);
552-
let substs = self.tcx.mk_substs(substs.iter().enumerate().map(|(index, kind)| {
553-
if index < generics.parent_count {
554-
// Accommodate missing regions in the parent kinds...
555-
self.fold_kind_no_missing_regions_error(kind)
556-
} else {
557-
// ...but not elsewhere.
558-
self.fold_kind_normally(kind)
559-
}
560-
}));
561-
562-
self.tcx.mk_generator(def_id, substs, movability)
563-
}
564-
565-
ty::Param(param) => {
566-
// Look it up in the substitution list.
567-
match self.map.get(&ty.into()).map(|k| k.unpack()) {
568-
// Found it in the substitution list; replace with the parameter from the
569-
// opaque type.
570-
Some(GenericArgKind::Type(t1)) => t1,
571-
Some(u) => panic!("type mapped to unexpected kind: {:?}", u),
572-
None => {
573-
debug!(?param, ?self.map);
574-
self.tcx
575-
.sess
576-
.struct_span_err(
577-
self.span,
578-
&format!(
579-
"type parameter `{}` is part of concrete type but not \
580-
used in parameter list for the `impl Trait` type alias",
581-
ty
582-
),
583-
)
584-
.emit();
585-
586-
self.tcx().ty_error()
587-
}
588-
}
589-
}
590-
591-
_ => ty.super_fold_with(self),
592-
}
593-
}
594-
595-
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
596-
trace!("checking const {:?}", ct);
597-
// Find a const parameter
598-
match ct.kind() {
599-
ty::ConstKind::Param(..) => {
600-
// Look it up in the substitution list.
601-
match self.map.get(&ct.into()).map(|k| k.unpack()) {
602-
// Found it in the substitution list, replace with the parameter from the
603-
// opaque type.
604-
Some(GenericArgKind::Const(c1)) => c1,
605-
Some(u) => panic!("const mapped to unexpected kind: {:?}", u),
606-
None => {
607-
self.tcx.sess.emit_err(ConstNotUsedTraitAlias {
608-
ct: ct.to_string(),
609-
span: self.span,
610-
});
611-
612-
self.tcx().const_error(ct.ty())
613-
}
614-
}
615-
}
616-
617-
_ => ct,
618-
}
619-
}
620-
}

compiler/rustc_borrowck/src/session_diagnostics.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,6 @@ pub(crate) struct VarNeedNotMut {
5252
#[suggestion_short(applicability = "machine-applicable", code = "")]
5353
pub span: Span,
5454
}
55-
56-
#[derive(Diagnostic)]
57-
#[diag(borrowck::const_not_used_in_type_alias)]
58-
pub(crate) struct ConstNotUsedTraitAlias {
59-
pub ct: String,
60-
#[primary_span]
61-
pub span: Span,
62-
}
63-
6455
#[derive(Diagnostic)]
6556
#[diag(borrowck::var_cannot_escape_closure)]
6657
#[note]

compiler/rustc_middle/src/ty/diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,3 +511,11 @@ impl<'tcx> TypeVisitor<'tcx> for IsSuggestableVisitor<'tcx> {
511511
c.super_visit_with(self)
512512
}
513513
}
514+
515+
#[derive(Diagnostic)]
516+
#[diag(borrowck::const_not_used_in_type_alias)]
517+
pub(super) struct ConstNotUsedTraitAlias {
518+
pub ct: String,
519+
#[primary_span]
520+
pub span: Span,
521+
}

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ mod generics;
131131
mod impls_ty;
132132
mod instance;
133133
mod list;
134+
mod opaque_types;
134135
mod parameterized;
135136
mod rvalue_scopes;
136137
mod structural_impls;
@@ -1300,6 +1301,32 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
13001301
sub: sub_diag,
13011302
});
13021303
}
1304+
1305+
#[instrument(level = "debug", skip(tcx), ret)]
1306+
pub fn remap_generic_params_to_declaration_params(
1307+
self,
1308+
opaque_type_key: OpaqueTypeKey<'tcx>,
1309+
tcx: TyCtxt<'tcx>,
1310+
) -> Self {
1311+
let OpaqueTypeKey { def_id, substs } = opaque_type_key;
1312+
1313+
// Use substs to build up a reverse map from regions to their
1314+
// identity mappings. This is necessary because of `impl
1315+
// Trait` lifetimes are computed by replacing existing
1316+
// lifetimes with 'static and remapping only those used in the
1317+
// `impl Trait` return type, resulting in the parameters
1318+
// shifting.
1319+
let id_substs = InternalSubsts::identity_for_item(tcx, def_id.to_def_id());
1320+
debug!(?id_substs);
1321+
let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> =
1322+
substs.iter().enumerate().map(|(index, subst)| (subst, id_substs[index])).collect();
1323+
debug!("map = {:#?}", map);
1324+
1325+
// Convert the type from the function into a type valid outside
1326+
// the function, by replacing invalid regions with 'static,
1327+
// after producing an error for each of them.
1328+
self.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span))
1329+
}
13031330
}
13041331

13051332
/// The "placeholder index" fully defines a placeholder region, type, or const. Placeholders are

0 commit comments

Comments
 (0)