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, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder,
9TypeSuperFoldable,
10};
1112pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>;
1314/// Converts generic params of a TypeFoldable from one
15/// item's generics to another. Usually from a function's generics
16/// list to the opaque type's own generics.
17pub(super) struct ReverseMapper<'tcx> {
18 tcx: TyCtxt<'tcx>,
19 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
20/// see call sites to fold_kind_no_missing_regions_error
21 /// for an explanation of this field.
22do_not_error: bool,
2324/// Span of function being checked.
25span: Span,
26}
2728impl<'tcx> ReverseMapper<'tcx> {
29pub(super) fn new(
30 tcx: TyCtxt<'tcx>,
31 map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
32 span: Span,
33 ) -> Self {
34Self { tcx, map, do_not_error: false, span }
35 }
3637fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
38if !!self.do_not_error {
::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
39self.do_not_error = true;
40let kind = kind.fold_with(self);
41self.do_not_error = false;
42kind43 }
4445fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
46if !!self.do_not_error {
::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
47kind.fold_with(self)
48 }
4950fn fold_closure_args(
51&mut self,
52 def_id: DefId,
53 args: ty::GenericArgsRef<'tcx>,
54 ) -> ty::GenericArgsRef<'tcx> {
55// I am a horrible monster and I pray for death. When
56 // we encounter a closure here, it is always a closure
57 // from within the function that we are currently
58 // type-checking -- one that is now being encapsulated
59 // in an opaque type. Ideally, we would
60 // go through the types/lifetimes that it references
61 // and treat them just like we would any other type,
62 // which means we would error out if we find any
63 // reference to a type/region that is not in the
64 // "reverse map".
65 //
66 // **However,** in the case of closures, there is a
67 // somewhat subtle (read: hacky) consideration. The
68 // problem is that our closure types currently include
69 // all the lifetime parameters declared on the
70 // enclosing function, even if they are unused by the
71 // closure itself. We can't readily filter them out,
72 // so here we replace those values with `'empty`. This
73 // can't really make a difference to the rest of the
74 // compiler; those regions are ignored for the
75 // outlives relation, and hence don't affect trait
76 // selection or auto traits, and they are erased
77 // during codegen.
7879let generics = self.tcx.generics_of(def_id);
80self.tcx.mk_args_from_iter(args.iter().enumerate().map(|(index, kind)| {
81if index < generics.parent_count {
82// Accommodate missing regions in the parent kinds...
83self.fold_kind_no_missing_regions_error(kind)
84 } else {
85// ...but not elsewhere.
86self.fold_kind_normally(kind)
87 }
88 }))
89 }
90}
9192impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
93fn cx(&self) -> TyCtxt<'tcx> {
94self.tcx
95 }
9697#[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(97u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::opaque_types"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r")
}> =
::tracing::__macro_support::FieldName::new("r");
NAME.as_str()
}], ::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};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r)
as &dyn ::tracing::field::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")]98fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
99match r.kind() {
100// Ignore bound regions and `'static` regions that appear in the
101 // type, we only need to remap regions that reference lifetimes
102 // from the function declaration.
103 //
104 // E.g. We ignore `'r` in a type like `for<'r> fn(&'r u32)`.
105ty::ReBound(..) | ty::ReStatic => return r,
106107// If regions have been erased (by writeback), don't try to unerase
108 // them.
109ty::ReErased => return r,
110111 ty::ReError(_) => return r,
112113// The regions that we expect from borrow checking.
114ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
115116 ty::RePlaceholder(_) | ty::ReVar(_) => {
117// All of the regions in the type should either have been
118 // erased by writeback, or mapped back to named regions by
119 // borrow checking.
120bug!("unexpected region kind in opaque type: {:?}", r);
121 }
122 }
123124match self.map.get(&r.into()).map(|arg| arg.kind()) {
125Some(GenericArgKind::Lifetime(r1)) => r1,
126Some(u) => panic!("region mapped to unexpected kind: {u:?}"),
127None if self.do_not_error => self.tcx.lifetimes.re_static,
128None => {
129let e = self
130.tcx
131 .dcx()
132 .struct_span_err(self.span, "non-defining opaque type use in defining scope")
133 .with_span_label(
134self.span,
135format!(
136"lifetime `{r}` is part of concrete type but not used in \
137 parameter list of the `impl Trait` type alias",
138 ),
139 )
140 .emit();
141142 ty::Region::new_error(self.cx(), e)
143 }
144 }
145 }
146147fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
148match *ty.kind() {
149 ty::Closure(def_id, args) => {
150let args = self.fold_closure_args(def_id, args);
151Ty::new_closure(self.tcx, def_id, args)
152 }
153154 ty::Coroutine(def_id, args) => {
155let args = self.fold_closure_args(def_id, args);
156Ty::new_coroutine(self.tcx, def_id, args)
157 }
158159 ty::CoroutineWitness(def_id, args) => {
160let args = self.fold_closure_args(def_id, args);
161Ty::new_coroutine_witness(self.tcx, def_id, args)
162 }
163164 ty::Param(param) => {
165// Look it up in the generic parameters list.
166match self.map.get(&ty.into()).map(|arg| arg.kind()) {
167// Found it in the generic parameters list; replace with the parameter from the
168 // opaque type.
169Some(GenericArgKind::Type(t1)) => t1,
170Some(u) => {
::core::panicking::panic_fmt(format_args!("type mapped to unexpected kind: {0:?}",
u));
}panic!("type mapped to unexpected kind: {u:?}"),
171None => {
172{
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:172",
"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(172u32),
::tracing_core::__macro_support::Option::Some("rustc_middle::ty::opaque_types"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("param")
}> =
::tracing::__macro_support::FieldName::new("param");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.map")
}> =
::tracing::__macro_support::FieldName::new("self.map");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(¶m)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.map)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?param, ?self.map);
173let guar = self174 .tcx
175 .dcx()
176 .struct_span_err(
177self.span,
178::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!(
179"type parameter `{ty}` is part of concrete type but not \
180 used in parameter list for the `impl Trait` type alias"
181),
182 )
183 .emit();
184Ty::new_error(self.tcx, guar)
185 }
186 }
187 }
188189_ => ty.super_fold_with(self),
190 }
191 }
192193fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
194{
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:194",
"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(194u32),
::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("checking const {0:?}",
ct) as &dyn ::tracing::field::Value))])
});
} else { ; }
};trace!("checking const {:?}", ct);
195// Find a const parameter
196match ct.kind() {
197 ty::ConstKind::Param(..) => {
198// Look it up in the generic parameters list.
199match self.map.get(&ct.into()).map(|arg| arg.kind()) {
200// Found it in the generic parameters list, replace with the parameter from the
201 // opaque type.
202Some(GenericArgKind::Const(c1)) => c1,
203Some(u) => {
::core::panicking::panic_fmt(format_args!("const mapped to unexpected kind: {0:?}",
u));
}panic!("const mapped to unexpected kind: {u:?}"),
204None => {
205let guar = self206 .tcx
207 .dcx()
208 .create_err(ConstNotUsedTraitAlias {
209 ct: ct.to_string(),
210 span: self.span,
211 })
212 .emit();
213 ty::Const::new_error(self.tcx, guar)
214 }
215 }
216 }
217218_ => ct,
219 }
220 }
221}