Skip to main content

rustc_middle/ty/
opaque_types.rs

1use rustc_data_structures::fx::FxHashMap;
2use rustc_span::Span;
3use rustc_span::def_id::DefId;
4use tracing::{debug, instrument, trace};
5
6use crate::error::ConstNotUsedTraitAlias;
7use crate::ty::{
8    self, GenericArg, GenericArgKind, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder,
9    TypeSuperFoldable,
10};
11
12pub type OpaqueTypeKey<'tcx> = rustc_type_ir::OpaqueTypeKey<TyCtxt<'tcx>>;
13
14/// 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.
22    do_not_error: bool,
23
24    /// Span of function being checked.
25    span: Span,
26}
27
28impl<'tcx> ReverseMapper<'tcx> {
29    pub(super) fn new(
30        tcx: TyCtxt<'tcx>,
31        map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
32        span: Span,
33    ) -> Self {
34        Self { tcx, map, do_not_error: false, span }
35    }
36
37    fn fold_kind_no_missing_regions_error(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
38        if !!self.do_not_error {
    ::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
39        self.do_not_error = true;
40        let kind = kind.fold_with(self);
41        self.do_not_error = false;
42        kind
43    }
44
45    fn fold_kind_normally(&mut self, kind: GenericArg<'tcx>) -> GenericArg<'tcx> {
46        if !!self.do_not_error {
    ::core::panicking::panic("assertion failed: !self.do_not_error")
};assert!(!self.do_not_error);
47        kind.fold_with(self)
48    }
49
50    fn 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.
78
79        let generics = self.tcx.generics_of(def_id);
80        self.tcx.mk_args_from_iter(args.iter().enumerate().map(|(index, kind)| {
81            if index < generics.parent_count {
82                // Accommodate missing regions in the parent kinds...
83                self.fold_kind_no_missing_regions_error(kind)
84            } else {
85                // ...but not elsewhere.
86                self.fold_kind_normally(kind)
87            }
88        }))
89    }
90}
91
92impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseMapper<'tcx> {
93    fn cx(&self) -> TyCtxt<'tcx> {
94        self.tcx
95    }
96
97    #[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")]
98    fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
99        match 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)`.
105            ty::ReBound(..) | ty::ReStatic => return r,
106
107            // If regions have been erased (by writeback), don't try to unerase
108            // them.
109            ty::ReErased => return r,
110
111            ty::ReError(_) => return r,
112
113            // The regions that we expect from borrow checking.
114            ty::ReEarlyParam(_) | ty::ReLateParam(_) => {}
115
116            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.
120                bug!("unexpected region kind in opaque type: {:?}", r);
121            }
122        }
123
124        match self.map.get(&r.into()).map(|arg| arg.kind()) {
125            Some(GenericArgKind::Lifetime(r1)) => r1,
126            Some(u) => panic!("region mapped to unexpected kind: {u:?}"),
127            None if self.do_not_error => self.tcx.lifetimes.re_static,
128            None => {
129                let e = self
130                    .tcx
131                    .dcx()
132                    .struct_span_err(self.span, "non-defining opaque type use in defining scope")
133                    .with_span_label(
134                        self.span,
135                        format!(
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();
141
142                ty::Region::new_error(self.cx(), e)
143            }
144        }
145    }
146
147    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
148        match *ty.kind() {
149            ty::Closure(def_id, args) => {
150                let args = self.fold_closure_args(def_id, args);
151                Ty::new_closure(self.tcx, def_id, args)
152            }
153
154            ty::Coroutine(def_id, args) => {
155                let args = self.fold_closure_args(def_id, args);
156                Ty::new_coroutine(self.tcx, def_id, args)
157            }
158
159            ty::CoroutineWitness(def_id, args) => {
160                let args = self.fold_closure_args(def_id, args);
161                Ty::new_coroutine_witness(self.tcx, def_id, args)
162            }
163
164            ty::Param(param) => {
165                // Look it up in the generic parameters list.
166                match 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.
169                    Some(GenericArgKind::Type(t1)) => t1,
170                    Some(u) => {
    ::core::panicking::panic_fmt(format_args!("type mapped to unexpected kind: {0:?}",
            u));
}panic!("type mapped to unexpected kind: {u:?}"),
171                    None => {
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(&param)
                                            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);
173                        let guar = self
174                            .tcx
175                            .dcx()
176                            .struct_span_err(
177                                self.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();
184                        Ty::new_error(self.tcx, guar)
185                    }
186                }
187            }
188
189            _ => ty.super_fold_with(self),
190        }
191    }
192
193    fn 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
196        match ct.kind() {
197            ty::ConstKind::Param(..) => {
198                // Look it up in the generic parameters list.
199                match 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.
202                    Some(GenericArgKind::Const(c1)) => c1,
203                    Some(u) => {
    ::core::panicking::panic_fmt(format_args!("const mapped to unexpected kind: {0:?}",
            u));
}panic!("const mapped to unexpected kind: {u:?}"),
204                    None => {
205                        let guar = self
206                            .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            }
217
218            _ => ct,
219        }
220    }
221}