1use rustc_data_structures::fx::FxHashMap;
2use rustc_span::Span;
3use rustc_span::def_id::DefId;
4use tracing::{debug, instrument, trace};
56use crate::error::ConstNotUsedTraitAlias;
7use crate::ty::{
8self, GenericArg, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
9};
1011pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>;
1213/// Converts generic params of a TypeFoldable from one
14/// item's generics to another. Usually from a function's generics
15/// list to the opaque type's own generics.
16pub(super) struct ReverseMapper<'tcx> {
17 tcx: TyCtxt<'tcx>,
18 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
19/// see call sites to fold_kind_no_missing_regions_error
20 /// for an explanation of this field.
21do_not_error: bool,
2223/// Span of function being checked.
24span: Span,
25}
2627impl<'tcx> ReverseMapper<'tcx> {
28pub(super) fn new(
29 tcx: TyCtxt<'tcx>,
30 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
31 span: Span,
32 ) -> Self {
33Self { tcx, map, do_not_error: false, span }
34 }
3536fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
37if !!self.do_not_error {
::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
38self.do_not_error = true;
39let kind = kind.fold_with(self);
40self.do_not_error = false;
41kind42 }
4344fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
45if !!self.do_not_error {
::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
46kind.fold_with(self)
47 }
4849fn fold_closure_args(
50&mut self,
51 def_id: DefId,
52 args: ty::GenericArgsRef<'tcx>,
53 ) -> ty::GenericArgsRef<'tcx> {
54// I am a horrible monster and I pray for death. When
55 // we encounter a closure here, it is always a closure
56 // from within the function that we are currently
57 // type-checking -- one that is now being encapsulated
58 // in an opaque type. Ideally, we would
59 // go through the types/lifetimes that it references
60 // and treat them just like we would any other type,
61 // which means we would error out if we find any
62 // reference to a type/region that is not in the
63 // "reverse map".
64 //
65 // **However,** in the case of closures, there is a
66 // somewhat subtle (read: hacky) consideration. The
67 // problem is that our closure types currently include
68 // all the lifetime parameters declared on the
69 // enclosing function, even if they are unused by the
70 // closure itself. We can't readily filter them out,
71 // so here we replace those values with `'empty`. This
72 // can't really make a difference to the rest of the
73 // compiler; those regions are ignored for the
74 // outlives relation, and hence don't affect trait
75 // selection or auto traits, and they are erased
76 // during codegen.
7778let generics = self.tcx.generics_of(def_id);
79self.tcx.mk_args_from_iter(args.iter().enumerate().map(|(index, kind)| {
80if index < generics.parent_count {
81// Accommodate missing regions in the parent kinds...
82self.fold_kind_no_missing_regions_error(kind)
83 } else {
84// ...but not elsewhere.
85self.fold_kind_normally(kind)
86 }
87 }))
88 }
89}
9091impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
92fn cx(&self) -> TyCtxt<'tcx> {
93self.tcx
94 }
9596#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("fold_region",
"rustc_middle::ty::opaque_types", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/opaque_types.rs"),
::tracing_core::__macro_support::Option::Some(96u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::opaque_types"),
::tracing_core::field::FieldSet::new(&["r"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: ty::Region<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
match r.kind() {
ty::ReBound(..) | ty::ReStatic => return r,
ty::ReErased => return r,
ty::ReError(_) => return r,
ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
ty::RePlaceholder(_) | ty::ReVar(_) => {
crate::util::bug::bug_fmt(format_args!("unexpected region kind in opaque type: {0:?}",
r));
}
}
match self.map.get(&r.into()).map(|arg| arg.kind()) {
Some(GenericArgKind::Lifetime(r1)) => r1,
Some(u) => {
::core::panicking::panic_fmt(format_args!("region mapped to unexpected kind: {0:?}",
u));
}
None if self.do_not_error => self.tcx.lifetimes.re_static,
None => {
let e =
self.tcx.dcx().struct_span_err(self.span,
"non-defining opaque type use in defining scope").with_span_label(self.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("lifetime `{0}` is part of concrete type but not used in parameter list of the `impl Trait` type alias",
r))
})).emit();
ty::Region::new_error(self.cx(), e)
}
}
}
}
}#[instrument(skip(self), level = "debug")]97fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
98match r.kind() {
99// Ignore bound regions and `'static` regions that appear in the
100 // type, we only need to remap regions that reference lifetimes
101 // from the function declaration.
102 //
103 // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`.
104ty::ReBound(..) | ty::ReStatic => return r,
105106// If regions have been erased (by writeback), don't try to unerase
107 // them.
108ty::ReErased => return r,
109110 ty::ReError(_) => return r,
111112// The regions that we expect from borrow checking.
113ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
114115 ty::RePlaceholder(_) | ty::ReVar(_) => {
116// All of the regions in the type should either have been
117 // erased by writeback, or mapped back to named regions by
118 // borrow checking.
119bug!("unexpected region kind in opaque type: {:?}", r);
120 }
121 }
122123match self.map.get(&r.into()).map(|arg| arg.kind()) {
124Some(GenericArgKind::Lifetime(r1)) => r1,
125Some(u) => panic!("region mapped to unexpected kind: {u:?}"),
126None if self.do_not_error => self.tcx.lifetimes.re_static,
127None => {
128let e = self
129.tcx
130 .dcx()
131 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
132 .with_span_label(
133self.span,
134format!(
135"lifetime `{r}` is part of concrete type but not used in \
136 parameter list of the `impl Trait` type alias"
137),
138 )
139 .emit();
140141 ty::Region::new_error(self.cx(), e)
142 }
143 }
144 }
145146fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
147match *ty.kind() {
148 ty::Closure(def_id, args) => {
149let args = self.fold_closure_args(def_id, args);
150Ty::new_closure(self.tcx, def_id, args)
151 }
152153 ty::Coroutine(def_id, args) => {
154let args = self.fold_closure_args(def_id, args);
155Ty::new_coroutine(self.tcx, def_id, args)
156 }
157158 ty::CoroutineWitness(def_id, args) => {
159let args = self.fold_closure_args(def_id, args);
160Ty::new_coroutine_witness(self.tcx, def_id, args)
161 }
162163 ty::Param(param) => {
164// Look it up in the generic parameters list.
165match self.map.get(&ty.into()).map(|arg| arg.kind()) {
166// Found it in the generic parameters list; replace with the parameter from the
167 // opaque type.
168Some(GenericArgKind::Type(t1)) => t1,
169Some(u) => {
::core::panicking::panic_fmt(format_args!("type mapped to unexpected kind: {0:?}",
u));
}panic!("type mapped to unexpected kind: {u:?}"),
170None => {
171{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/opaque_types.rs:171",
"rustc_middle::ty::opaque_types", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/opaque_types.rs"),
::tracing_core::__macro_support::Option::Some(171u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::opaque_types"),
::tracing_core::field::FieldSet::new(&["param", "self.map"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(¶m) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.map)
as &dyn Value))])
});
} else { ; }
};debug!(?param, ?self.map);
172let guar = self173 .tcx
174 .dcx()
175 .struct_span_err(
176self.span,
177::alloc::__export::must_use({
::alloc::fmt::format(format_args!("type parameter `{0}` is part of concrete type but not used in parameter list for the `impl Trait` type alias",
ty))
})format!(
178"type parameter `{ty}` is part of concrete type but not \
179 used in parameter list for the `impl Trait` type alias"
180),
181 )
182 .emit();
183Ty::new_error(self.tcx, guar)
184 }
185 }
186 }
187188_ => ty.super_fold_with(self),
189 }
190 }
191192fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
193{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_middle/src/ty/opaque_types.rs:193",
"rustc_middle::ty::opaque_types", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_middle/src/ty/opaque_types.rs"),
::tracing_core::__macro_support::Option::Some(193u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::opaque_types"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("checking const {0:?}",
ct) as &dyn Value))])
});
} else { ; }
};trace!("checking const {:?}", ct);
194// Find a const parameter
195match ct.kind() {
196 ty::ConstKind::Param(..) => {
197// Look it up in the generic parameters list.
198match self.map.get(&ct.into()).map(|arg| arg.kind()) {
199// Found it in the generic parameters list, replace with the parameter from the
200 // opaque type.
201Some(GenericArgKind::Const(c1)) => c1,
202Some(u) => {
::core::panicking::panic_fmt(format_args!("const mapped to unexpected kind: {0:?}",
u));
}panic!("const mapped to unexpected kind: {u:?}"),
203None => {
204let guar = self205 .tcx
206 .dcx()
207 .create_err(ConstNotUsedTraitAlias {
208 ct: ct.to_string(),
209 span: self.span,
210 })
211 .emit();
212 ty::Const::new_error(self.tcx, guar)
213 }
214 }
215 }
216217_ => ct,
218 }
219 }
220}