Skip to main content

rustc_middle/ty/
closure.rs

1use std::cmp;
2use std::fmt::Write;
3
4use rustc_data_structures::fx::FxIndexMap;
5use rustc_hir as hir;
6use rustc_hir::HirId;
7use rustc_hir::def_id::LocalDefId;
8use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
9use rustc_span::def_id::LocalDefIdMap;
10use rustc_span::{Ident, Span, Symbol, bug};
11
12use super::TyCtxt;
13use crate::hir::place::{
14    Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind,
15};
16use crate::query::Providers;
17use crate::{mir, ty};
18
19/// Captures are represented using fields inside a structure.
20/// This represents accessing self in the closure structure
21pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::arg(0);
22
23#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UpvarPath { }
#[automatically_derived]
impl ::core::clone::Clone for UpvarPath {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<HirId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for UpvarPath { }Copy, #[automatically_derived]
impl ::core::fmt::Debug for UpvarPath {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f, "UpvarPath",
            "hir_id", &&self.hir_id)
    }
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for UpvarPath { }
#[automatically_derived]
impl ::core::cmp::PartialEq for UpvarPath {
    #[inline]
    fn eq(&self, other: &Self) -> bool { self.hir_id == other.hir_id }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for UpvarPath {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<HirId>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for UpvarPath {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.hir_id, state)
    }
}Hash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for UpvarPath {
            fn encode(&self, __encoder: &mut __E) {
                let UpvarPath { hir_id: ref __binding_0 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for UpvarPath {
            fn decode(__decoder: &mut __D) -> Self {
                UpvarPath {
                    hir_id: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for UpvarPath {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    UpvarPath { hir_id: ref __binding_0 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
24#[derive(const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarPath {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        UpvarPath { hir_id: __binding_0 } => {
                            UpvarPath {
                                hir_id: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    UpvarPath { hir_id: __binding_0 } => {
                        UpvarPath {
                            hir_id: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarPath {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    UpvarPath { hir_id: ref __binding_0 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
25pub struct UpvarPath {
26    pub hir_id: HirId,
27}
28
29/// Upvars do not get their own `NodeId`. Instead, we use the pair of
30/// the original var ID (that is, the root variable that is referenced
31/// by the upvar) and the ID of the closure expression.
32#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UpvarId { }
#[automatically_derived]
impl ::core::clone::Clone for UpvarId {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<UpvarPath>;
        let _: ::core::clone::AssertParamIsClone<LocalDefId>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for UpvarId { }Copy, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for UpvarId { }
#[automatically_derived]
impl ::core::cmp::PartialEq for UpvarId {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.var_path == other.var_path &&
            self.closure_expr_id == other.closure_expr_id
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for UpvarId {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<UpvarPath>;
        let _: ::core::cmp::AssertParamIsEq<LocalDefId>;
    }
}Eq, #[automatically_derived]
impl ::core::hash::Hash for UpvarId {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.var_path, state);
        ::core::hash::Hash::hash(&self.closure_expr_id, state)
    }
}Hash, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for UpvarId {
            fn encode(&self, __encoder: &mut __E) {
                let UpvarId {
                        var_path: ref __binding_0, closure_expr_id: ref __binding_1
                        } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for UpvarId {
            fn decode(__decoder: &mut __D) -> Self {
                UpvarId {
                    var_path: ::rustc_serialize::Decodable::decode(__decoder),
                    closure_expr_id: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for UpvarId {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    UpvarId {
                        var_path: ref __binding_0, closure_expr_id: ref __binding_1
                        } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
33#[derive(const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarId {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        UpvarId {
                            var_path: __binding_0, closure_expr_id: __binding_1 } => {
                            UpvarId {
                                var_path: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                closure_expr_id: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    UpvarId {
                        var_path: __binding_0, closure_expr_id: __binding_1 } => {
                        UpvarId {
                            var_path: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            closure_expr_id: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarId {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    UpvarId {
                        var_path: ref __binding_0, closure_expr_id: ref __binding_1
                        } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
34pub struct UpvarId {
35    pub var_path: UpvarPath,
36    pub closure_expr_id: LocalDefId,
37}
38
39impl UpvarId {
40    pub fn new(var_hir_id: HirId, closure_def_id: LocalDefId) -> UpvarId {
41        UpvarId { var_path: UpvarPath { hir_id: var_hir_id }, closure_expr_id: closure_def_id }
42    }
43}
44
45/// Information describing the capture of an upvar. This is computed
46/// during `typeck`, specifically by `regionck`.
47#[derive(#[automatically_derived]
impl ::core::cmp::Eq for UpvarCapture {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<BorrowKind>;
    }
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for UpvarCapture { }
#[automatically_derived]
impl ::core::cmp::PartialEq for UpvarCapture {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
                ::core::intrinsics::discriminant_value(other) &&
            match (self, other) {
                (Self::ByRef(__self_0), Self::ByRef(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for UpvarCapture { }
#[automatically_derived]
impl ::core::clone::Clone for UpvarCapture {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<BorrowKind>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for UpvarCapture {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            Self::ByRef(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "ByRef",
                    &__self_0),
            Self::ByUse => ::core::fmt::Formatter::write_str(f, "ByUse"),
            Self::ByValue => ::core::fmt::Formatter::write_str(f, "ByValue"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for UpvarCapture { }Copy, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for UpvarCapture {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        UpvarCapture::ByRef(ref __binding_0) => { 0usize }
                        UpvarCapture::ByUse => { 1usize }
                        UpvarCapture::ByValue => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    UpvarCapture::ByRef(ref __binding_0) => {
                        ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                            __encoder);
                    }
                    UpvarCapture::ByUse => {}
                    UpvarCapture::ByValue => {}
                }
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for UpvarCapture {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => {
                        UpvarCapture::ByRef(::rustc_serialize::Decodable::decode(__decoder))
                    }
                    1usize => { UpvarCapture::ByUse }
                    2usize => { UpvarCapture::ByValue }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `UpvarCapture`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for UpvarCapture
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    UpvarCapture::ByRef(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    UpvarCapture::ByUse => {}
                    UpvarCapture::ByValue => {}
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::hash::Hash for UpvarCapture {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state);
        match self {
            Self::ByRef(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            _ => {}
        }
    }
}Hash)]
48#[derive(const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarCapture {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        UpvarCapture::ByRef(__binding_0) => {
                            UpvarCapture::ByRef(::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?)
                        }
                        UpvarCapture::ByUse => { UpvarCapture::ByUse }
                        UpvarCapture::ByValue => { UpvarCapture::ByValue }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    UpvarCapture::ByRef(__binding_0) => {
                        UpvarCapture::ByRef(::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder))
                    }
                    UpvarCapture::ByUse => { UpvarCapture::ByUse }
                    UpvarCapture::ByValue => { UpvarCapture::ByValue }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for UpvarCapture {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    UpvarCapture::ByRef(ref __binding_0) => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    UpvarCapture::ByUse => {}
                    UpvarCapture::ByValue => {}
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
49pub enum UpvarCapture {
50    /// Upvar is captured by reference.
51    ByRef(BorrowKind),
52
53    /// Upvar is captured by use. This is true when the closure is labeled `use`.
54    ByUse,
55
56    /// Upvar is captured by value. This is always true when the
57    /// closure is labeled `move`, but can also be true in other cases
58    /// depending on inference.
59    ByValue,
60}
61
62// Used in rustc_hir_typeck::upvar::determine_capture_info
63impl PartialOrd for UpvarCapture {
64    #[inline]
65    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
66        match (self, other) {
67            (Self::ByValue, Self::ByValue) | (Self::ByUse, Self::ByUse) => {
68                Some(cmp::Ordering::Equal)
69            }
70            (Self::ByValue | Self::ByUse, Self::ByRef(_)) => Some(cmp::Ordering::Greater),
71            (Self::ByRef(_), Self::ByValue | Self::ByUse) => Some(cmp::Ordering::Less),
72            (Self::ByRef(left), Self::ByRef(right)) => Some(left.cmp(&right)),
73            (Self::ByUse, Self::ByValue) | (Self::ByValue, Self::ByUse) => None,
74        }
75    }
76}
77
78/// Given the closure DefId this map provides a map of root variables to minimum
79/// set of `CapturedPlace`s that need to be tracked to support all captures of that closure.
80pub type MinCaptureInformationMap<'tcx> = LocalDefIdMap<RootVariableMinCaptureList<'tcx>>;
81
82/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.
83/// Used to track the minimum set of `Place`s that need to be captured to support all
84/// Places captured by the closure starting at a given root variable.
85///
86/// This provides a convenient and quick way of checking if a variable being used within
87/// a closure is a capture of a local variable.
88pub type RootVariableMinCaptureList<'tcx> = FxIndexMap<HirId, MinCaptureList<'tcx>>;
89
90/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.
91pub type MinCaptureList<'tcx> = Vec<CapturedPlace<'tcx>>;
92
93/// A composite describing a `Place` that is captured by a closure.
94#[derive(#[automatically_derived]
impl<'tcx> ::core::cmp::Eq for CapturedPlace<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Ident>;
        let _: ::core::cmp::AssertParamIsEq<HirPlace<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<CaptureInfo>;
        let _: ::core::cmp::AssertParamIsEq<hir::Mutability>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for CapturedPlace<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for CapturedPlace<'tcx> {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.var_ident == other.var_ident && self.place == other.place &&
                self.info == other.info && self.mutability == other.mutability
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for CapturedPlace<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        Self {
            var_ident: ::core::clone::Clone::clone(&self.var_ident),
            place: ::core::clone::Clone::clone(&self.place),
            info: ::core::clone::Clone::clone(&self.info),
            mutability: ::core::clone::Clone::clone(&self.mutability),
        }
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for CapturedPlace<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f, "CapturedPlace",
            "var_ident", &self.var_ident, "place", &self.place, "info",
            &self.info, "mutability", &&self.mutability)
    }
}Debug, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for CapturedPlace<'tcx> {
            fn encode(&self, __encoder: &mut __E) {
                let CapturedPlace {
                        var_ident: ref __binding_0,
                        place: ref __binding_1,
                        info: ref __binding_2,
                        mutability: ref __binding_3 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_3,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for CapturedPlace<'tcx> {
            fn decode(__decoder: &mut __D) -> Self {
                CapturedPlace {
                    var_ident: ::rustc_serialize::Decodable::decode(__decoder),
                    place: ::rustc_serialize::Decodable::decode(__decoder),
                    info: ::rustc_serialize::Decodable::decode(__decoder),
                    mutability: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            CapturedPlace<'tcx> {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    CapturedPlace {
                        var_ident: ref __binding_0,
                        place: ref __binding_1,
                        info: ref __binding_2,
                        mutability: ref __binding_3 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                        { __binding_3.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for CapturedPlace<'tcx> {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.var_ident, state);
        ::core::hash::Hash::hash(&self.place, state);
        ::core::hash::Hash::hash(&self.info, state);
        ::core::hash::Hash::hash(&self.mutability, state)
    }
}Hash)]
95#[derive(const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for CapturedPlace<'tcx> {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        CapturedPlace {
                            var_ident: __binding_0,
                            place: __binding_1,
                            info: __binding_2,
                            mutability: __binding_3 } => {
                            CapturedPlace {
                                var_ident: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                place: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                                info: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_2,
                                        __folder)?,
                                mutability: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_3,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    CapturedPlace {
                        var_ident: __binding_0,
                        place: __binding_1,
                        info: __binding_2,
                        mutability: __binding_3 } => {
                        CapturedPlace {
                            var_ident: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            place: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
                                __folder),
                            info: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_2,
                                __folder),
                            mutability: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_3,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for CapturedPlace<'tcx> {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    CapturedPlace {
                        var_ident: ref __binding_0,
                        place: ref __binding_1,
                        info: ref __binding_2,
                        mutability: ref __binding_3 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_2,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_3,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
96pub struct CapturedPlace<'tcx> {
97    /// Name and span where the binding happens.
98    pub var_ident: Ident,
99
100    /// The `Place` that is captured.
101    pub place: HirPlace<'tcx>,
102
103    /// `CaptureKind` and expression(s) that resulted in such capture of `place`.
104    pub info: CaptureInfo,
105
106    /// Represents if `place` can be mutated or not.
107    pub mutability: hir::Mutability,
108}
109
110impl<'tcx> CapturedPlace<'tcx> {
111    pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> String {
112        place_to_string_for_capture(tcx, &self.place)
113    }
114
115    /// Returns a symbol of the captured upvar, which looks like `name__field1__field2`.
116    pub fn to_symbol(&self) -> Symbol {
117        let mut symbol = self.var_ident.to_string();
118
119        let mut ty = self.place.base_ty;
120        for proj in self.place.projections.iter() {
121            match proj.kind {
122                HirProjectionKind::Field(idx, variant) => match ty.kind() {
123                    ty::Tuple(_) => (&mut symbol).write_fmt(format_args!("__{0}", idx.index()))write!(&mut symbol, "__{}", idx.index()).unwrap(),
124                    ty::Adt(def, ..) => {
125                        (&mut symbol).write_fmt(format_args!("__{0}",
        def.variant(variant).fields[idx].name.as_str()))write!(
126                            &mut symbol,
127                            "__{}",
128                            def.variant(variant).fields[idx].name.as_str(),
129                        )
130                        .unwrap();
131                    }
132                    ty => {
133                        ::rustc_span::macros::bug_impl(None,
    format_args!("Unexpected type {0:?} for `Field` projection", ty),
    Location::caller())bug!("Unexpected type {:?} for `Field` projection", ty)
134                    }
135                },
136
137                HirProjectionKind::UnwrapUnsafeBinder => {
138                    (&mut symbol).write_fmt(format_args!("__unwrap"))write!(&mut symbol, "__unwrap").unwrap();
139                }
140
141                // Ignore derefs for now, as they are likely caused by
142                // autoderefs that don't appear in the original code.
143                HirProjectionKind::Deref => {}
144                // Just change the type to the hidden type, so we can actually project.
145                HirProjectionKind::OpaqueCast => {}
146                proj => ::rustc_span::macros::bug_impl(None,
    format_args!("Unexpected projection {0:?} in captured place", proj),
    Location::caller())bug!("Unexpected projection {:?} in captured place", proj),
147            }
148            ty = proj.ty;
149        }
150
151        Symbol::intern(&symbol)
152    }
153
154    /// Returns the hir-id of the root variable for the captured place.
155    /// e.g., if `a.b.c` was captured, would return the hir-id for `a`.
156    pub fn get_root_variable(&self) -> HirId {
157        match self.place.base {
158            HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id,
159            base => ::rustc_span::macros::bug_impl(None,
    format_args!("Expected upvar, found={0:?}", base), Location::caller())bug!("Expected upvar, found={:?}", base),
160        }
161    }
162
163    /// Returns the `LocalDefId` of the closure that captured this Place
164    pub fn get_closure_local_def_id(&self) -> LocalDefId {
165        match self.place.base {
166            HirPlaceBase::Upvar(upvar_id) => upvar_id.closure_expr_id,
167            base => ::rustc_span::macros::bug_impl(None,
    format_args!("expected upvar, found={0:?}", base), Location::caller())bug!("expected upvar, found={:?}", base),
168        }
169    }
170
171    /// Return span pointing to use that resulted in selecting the captured path
172    pub fn get_path_span(&self, tcx: TyCtxt<'tcx>) -> Span {
173        if let Some(path_expr_id) = self.info.path_expr_id {
174            tcx.hir_span(path_expr_id)
175        } else if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id {
176            tcx.hir_span(capture_kind_expr_id)
177        } else {
178            // Fallback on upvars mentioned if neither path or capture expr id is captured
179
180            // Safe to unwrap since we know this place is captured by the closure, therefore the closure must have upvars.
181            tcx.upvars_mentioned(self.get_closure_local_def_id()).unwrap()
182                [&self.get_root_variable()]
183                .span
184        }
185    }
186
187    /// Return span pointing to use that resulted in selecting the current capture kind
188    pub fn get_capture_kind_span(&self, tcx: TyCtxt<'tcx>) -> Span {
189        if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id {
190            tcx.hir_span(capture_kind_expr_id)
191        } else if let Some(path_expr_id) = self.info.path_expr_id {
192            tcx.hir_span(path_expr_id)
193        } else {
194            // Fallback on upvars mentioned if neither path or capture expr id is captured
195
196            // Safe to unwrap since we know this place is captured by the closure, therefore the closure must have upvars.
197            tcx.upvars_mentioned(self.get_closure_local_def_id()).unwrap()
198                [&self.get_root_variable()]
199                .span
200        }
201    }
202
203    pub fn is_by_ref(&self) -> bool {
204        match self.info.capture_kind {
205            ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => false,
206            ty::UpvarCapture::ByRef(..) => true,
207        }
208    }
209}
210
211#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::Copy for ClosureTypeInfo<'tcx> { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for ClosureTypeInfo<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for ClosureTypeInfo<'tcx> {
    #[inline]
    fn clone(&self) -> Self {
        let _:
                ::core::clone::AssertParamIsClone<ty::CanonicalPolyFnSig<'tcx>>;
        let _:
                ::core::clone::AssertParamIsClone<&'tcx ty::List<&'tcx ty::CapturedPlace<'tcx>>>;
        let _:
                ::core::clone::AssertParamIsClone<Option<&'tcx (Span,
                HirPlace<'tcx>)>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ClosureTypeInfo<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "ClosureTypeInfo", "user_provided_sig", &self.user_provided_sig,
            "captures", &self.captures, "kind_origin", &&self.kind_origin)
    }
}Debug, const _: () =
    {
        impl<'tcx> ::rustc_data_structures::stable_hash::StableHash for
            ClosureTypeInfo<'tcx> {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    ClosureTypeInfo {
                        user_provided_sig: ref __binding_0,
                        captures: ref __binding_1,
                        kind_origin: ref __binding_2 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash)]
212pub struct ClosureTypeInfo<'tcx> {
213    user_provided_sig: ty::CanonicalPolyFnSig<'tcx>,
214    captures: &'tcx ty::List<&'tcx ty::CapturedPlace<'tcx>>,
215    kind_origin: Option<&'tcx (Span, HirPlace<'tcx>)>,
216}
217
218fn closure_typeinfo<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ClosureTypeInfo<'tcx> {
219    if true {
    if !tcx.is_closure_like(def.to_def_id()) {
        ::core::panicking::panic("assertion failed: tcx.is_closure_like(def.to_def_id())")
    };
};debug_assert!(tcx.is_closure_like(def.to_def_id()));
220    let typeck_results = tcx.typeck(def);
221    let user_provided_sig = typeck_results.user_provided_sigs[&def];
222    let captures = typeck_results.closure_min_captures_flattened(def);
223    let captures = tcx.mk_captures_from_iter(captures);
224    let hir_id = tcx.local_def_id_to_hir_id(def);
225    let kind_origin = typeck_results.closure_kind_origins().get(hir_id);
226    ClosureTypeInfo { user_provided_sig, captures, kind_origin }
227}
228
229impl<'tcx> TyCtxt<'tcx> {
230    pub fn closure_kind_origin(self, def_id: LocalDefId) -> Option<&'tcx (Span, HirPlace<'tcx>)> {
231        self.closure_typeinfo(def_id).kind_origin
232    }
233
234    pub fn closure_user_provided_sig(self, def_id: LocalDefId) -> ty::CanonicalPolyFnSig<'tcx> {
235        self.closure_typeinfo(def_id).user_provided_sig
236    }
237
238    pub fn closure_captures(self, def_id: LocalDefId) -> &'tcx [&'tcx ty::CapturedPlace<'tcx>] {
239        if !self.is_closure_like(def_id.to_def_id()) {
240            return &[];
241        }
242        self.closure_typeinfo(def_id).captures
243    }
244}
245
246/// Return true if the `proj_possible_ancestor` represents an ancestor path
247/// to `proj_capture` or `proj_possible_ancestor` is same as `proj_capture`,
248/// assuming they both start off of the same root variable.
249///
250/// **Note:** It's the caller's responsibility to ensure that both lists of projections
251///           start off of the same root variable.
252///
253/// Eg: 1. `foo.x` which is represented using `projections=[Field(x)]` is an ancestor of
254///        `foo.x.y` which is represented using `projections=[Field(x), Field(y)]`.
255///        Note both `foo.x` and `foo.x.y` start off of the same root variable `foo`.
256///     2. Since we only look at the projections here function will return `bar.x` as a valid
257///        ancestor of `foo.x.y`. It's the caller's responsibility to ensure that both projections
258///        list are being applied to the same root variable.
259pub fn is_ancestor_or_same_capture(
260    proj_possible_ancestor: &[HirProjectionKind],
261    proj_capture: &[HirProjectionKind],
262) -> bool {
263    // We want to make sure `is_ancestor_or_same_capture("x.0.0", "x.0")` to return false.
264    // Therefore we can't just check if all projections are same in the zipped iterator below.
265    if proj_possible_ancestor.len() > proj_capture.len() {
266        return false;
267    }
268
269    proj_possible_ancestor.iter().zip(proj_capture).all(|(a, b)| a == b)
270}
271
272/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)
273/// for a particular capture as well as identifying the part of the source code
274/// that triggered this capture to occur.
275#[derive(#[automatically_derived]
impl ::core::cmp::Eq for CaptureInfo {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Option<HirId>>;
        let _: ::core::cmp::AssertParamIsEq<Option<HirId>>;
        let _: ::core::cmp::AssertParamIsEq<UpvarCapture>;
    }
}Eq, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for CaptureInfo { }
#[automatically_derived]
impl ::core::cmp::PartialEq for CaptureInfo {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        self.capture_kind_expr_id == other.capture_kind_expr_id &&
                self.path_expr_id == other.path_expr_id &&
            self.capture_kind == other.capture_kind
    }
}PartialEq, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for CaptureInfo { }
#[automatically_derived]
impl ::core::clone::Clone for CaptureInfo {
    #[inline]
    fn clone(&self) -> Self {
        let _: ::core::clone::AssertParamIsClone<Option<HirId>>;
        let _: ::core::clone::AssertParamIsClone<Option<HirId>>;
        let _: ::core::clone::AssertParamIsClone<UpvarCapture>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for CaptureInfo {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f, "CaptureInfo",
            "capture_kind_expr_id", &self.capture_kind_expr_id,
            "path_expr_id", &self.path_expr_id, "capture_kind",
            &&self.capture_kind)
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for CaptureInfo { }Copy, const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for CaptureInfo {
            fn encode(&self, __encoder: &mut __E) {
                let CaptureInfo {
                        capture_kind_expr_id: ref __binding_0,
                        path_expr_id: ref __binding_1,
                        capture_kind: ref __binding_2 } = *self;
                ::rustc_serialize::Encodable::<__E>::encode(__binding_0,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_1,
                    __encoder);
                ::rustc_serialize::Encodable::<__E>::encode(__binding_2,
                    __encoder);
            }
        }
    };TyEncodable, const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for CaptureInfo {
            fn decode(__decoder: &mut __D) -> Self {
                CaptureInfo {
                    capture_kind_expr_id: ::rustc_serialize::Decodable::decode(__decoder),
                    path_expr_id: ::rustc_serialize::Decodable::decode(__decoder),
                    capture_kind: ::rustc_serialize::Decodable::decode(__decoder),
                }
            }
        }
    };TyDecodable, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for CaptureInfo
            {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                match *self {
                    CaptureInfo {
                        capture_kind_expr_id: ref __binding_0,
                        path_expr_id: ref __binding_1,
                        capture_kind: ref __binding_2 } => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                        { __binding_1.stable_hash(__hcx, __hasher); }
                        { __binding_2.stable_hash(__hcx, __hasher); }
                    }
                }
            }
        }
    };StableHash, #[automatically_derived]
impl ::core::hash::Hash for CaptureInfo {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.capture_kind_expr_id, state);
        ::core::hash::Hash::hash(&self.path_expr_id, state);
        ::core::hash::Hash::hash(&self.capture_kind, state)
    }
}Hash)]
276#[derive(const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for CaptureInfo {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        CaptureInfo {
                            capture_kind_expr_id: __binding_0,
                            path_expr_id: __binding_1,
                            capture_kind: __binding_2 } => {
                            CaptureInfo {
                                capture_kind_expr_id: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_0,
                                        __folder)?,
                                path_expr_id: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_1,
                                        __folder)?,
                                capture_kind: ::rustc_middle::ty::TypeFoldable::try_fold_with(__binding_2,
                                        __folder)?,
                            }
                        }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    CaptureInfo {
                        capture_kind_expr_id: __binding_0,
                        path_expr_id: __binding_1,
                        capture_kind: __binding_2 } => {
                        CaptureInfo {
                            capture_kind_expr_id: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_0,
                                __folder),
                            path_expr_id: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_1,
                                __folder),
                            capture_kind: ::rustc_middle::ty::TypeFoldable::fold_with(__binding_2,
                                __folder),
                        }
                    }
                }
            }
        }
    };TypeFoldable, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for CaptureInfo {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    CaptureInfo {
                        capture_kind_expr_id: ref __binding_0,
                        path_expr_id: ref __binding_1,
                        capture_kind: ref __binding_2 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_2,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
277pub struct CaptureInfo {
278    /// Expr Id pointing to use that resulted in selecting the current capture kind
279    ///
280    /// Eg:
281    /// ```rust,no_run
282    /// let mut t = (0,1);
283    ///
284    /// let c = || {
285    ///     println!("{t:?}"); // L1
286    ///     t.1 = 4; // L2
287    /// };
288    /// ```
289    /// `capture_kind_expr_id` will point to the use on L2 and `path_expr_id` will point to the
290    /// use on L1.
291    ///
292    /// If the user doesn't enable feature `capture_disjoint_fields` (RFC 2229) then, it is
293    /// possible that we don't see the use of a particular place resulting in capture_kind_expr_id being
294    /// None. In such case we fallback on uvpars_mentioned for span.
295    ///
296    /// Eg:
297    /// ```rust,no_run
298    /// let x = 5;
299    ///
300    /// let c = || {
301    ///     let _ = x;
302    /// };
303    /// ```
304    ///
305    /// In this example, if `capture_disjoint_fields` is **not** set, then x will be captured,
306    /// but we won't see it being used during capture analysis, since it's essentially a discard.
307    pub capture_kind_expr_id: Option<HirId>,
308    /// Expr Id pointing to use that resulted the corresponding place being captured
309    ///
310    /// See `capture_kind_expr_id` for example.
311    ///
312    pub path_expr_id: Option<HirId>,
313
314    /// Capture mode that was selected
315    pub capture_kind: UpvarCapture,
316}
317
318pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tcx>) -> String {
319    let mut curr_string: String = match place.base {
320        HirPlaceBase::Upvar(upvar_id) => tcx.hir_name(upvar_id.var_path.hir_id).to_string(),
321        _ => ::rustc_span::macros::bug_impl(None,
    format_args!("Capture_information should only contain upvars"),
    Location::caller())bug!("Capture_information should only contain upvars"),
322    };
323
324    for (i, proj) in place.projections.iter().enumerate() {
325        match proj.kind {
326            HirProjectionKind::Deref => {
327                curr_string = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("*{0}", curr_string))
    })format!("*{curr_string}");
328            }
329            HirProjectionKind::Field(idx, variant) => match place.ty_before_projection(i).kind() {
330                ty::Adt(def, ..) => {
331                    curr_string = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}.{1}", curr_string,
                def.variant(variant).fields[idx].name.as_str()))
    })format!(
332                        "{}.{}",
333                        curr_string,
334                        def.variant(variant).fields[idx].name.as_str()
335                    );
336                }
337                ty::Tuple(_) => {
338                    curr_string = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}.{1}", curr_string,
                idx.index()))
    })format!("{}.{}", curr_string, idx.index());
339                }
340                _ => {
341                    ::rustc_span::macros::bug_impl(None,
    format_args!("Field projection applied to a type other than Adt or Tuple: {0:?}.",
        place.ty_before_projection(i).kind()), Location::caller())bug!(
342                        "Field projection applied to a type other than Adt or Tuple: {:?}.",
343                        place.ty_before_projection(i).kind()
344                    )
345                }
346            },
347            HirProjectionKind::UnwrapUnsafeBinder => {
348                curr_string = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unwrap_binder!({0})", curr_string))
    })format!("unwrap_binder!({curr_string})");
349            }
350            // Just change the type to the hidden type, so we can actually project.
351            HirProjectionKind::OpaqueCast => {}
352            proj => ::rustc_span::macros::bug_impl(None,
    format_args!("{0:?} unexpected because it isn\'t captured", proj),
    Location::caller())bug!("{:?} unexpected because it isn't captured", proj),
353        }
354    }
355
356    curr_string
357}
358
359#[derive(
360    #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for BorrowKind { }
#[automatically_derived]
impl ::core::clone::Clone for BorrowKind {
    #[inline]
    fn clone(&self) -> Self { *self }
}Clone,
361    #[automatically_derived]
impl ::core::marker::Copy for BorrowKind { }Copy,
362    #[automatically_derived]
impl ::core::fmt::Debug for BorrowKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                BorrowKind::Immutable => "Immutable",
                BorrowKind::UniqueImmutable => "UniqueImmutable",
                BorrowKind::Mutable => "Mutable",
            })
    }
}Debug,
363    #[automatically_derived]
impl ::core::marker::StructuralPartialEq for BorrowKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for BorrowKind {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        ::core::intrinsics::discriminant_value(self) ==
            ::core::intrinsics::discriminant_value(other)
    }
}PartialEq,
364    #[automatically_derived]
impl ::core::cmp::Eq for BorrowKind { }Eq,
365    #[automatically_derived]
impl ::core::hash::Hash for BorrowKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self),
            state)
    }
}Hash,
366    #[automatically_derived]
impl ::core::cmp::PartialOrd for BorrowKind {
    #[inline]
    fn partial_cmp(&self, other: &Self)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, // Order of variants is load-bearing
367    #[automatically_derived]
impl ::core::cmp::Ord for BorrowKind {
    #[inline]
    fn cmp(&self, other: &Self) -> ::core::cmp::Ordering {
        ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self),
            &::core::intrinsics::discriminant_value(other))
    }
}Ord,
368    const _: () =
    {
        impl<'tcx, __E: ::rustc_middle::ty::codec::TyEncoder<'tcx>>
            ::rustc_serialize::Encodable<__E> for BorrowKind {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        BorrowKind::Immutable => { 0usize }
                        BorrowKind::UniqueImmutable => { 1usize }
                        BorrowKind::Mutable => { 2usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
            }
        }
    };TyEncodable,
369    const _: () =
    {
        impl<'tcx, __D: ::rustc_middle::ty::codec::TyDecoder<'tcx>>
            ::rustc_serialize::Decodable<__D> for BorrowKind {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { BorrowKind::Immutable }
                    1usize => { BorrowKind::UniqueImmutable }
                    2usize => { BorrowKind::Mutable }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `BorrowKind`, expected 0..3, actual {0}",
                                n));
                    }
                }
            }
        }
    };TyDecodable,
370    const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for BorrowKind {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    BorrowKind::Immutable => {}
                    BorrowKind::UniqueImmutable => {}
                    BorrowKind::Mutable => {}
                }
            }
        }
    };StableHash,
371    const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>
            for BorrowKind {
            fn try_fold_with<__F: ::rustc_middle::ty::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Result<Self, __F::Error> {
                Ok(match self {
                        BorrowKind::Immutable => { BorrowKind::Immutable }
                        BorrowKind::UniqueImmutable => {
                            BorrowKind::UniqueImmutable
                        }
                        BorrowKind::Mutable => { BorrowKind::Mutable }
                    })
            }
            fn fold_with<__F: ::rustc_middle::ty::TypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>(self,
                __folder: &mut __F) -> Self {
                match self {
                    BorrowKind::Immutable => { BorrowKind::Immutable }
                    BorrowKind::UniqueImmutable => {
                        BorrowKind::UniqueImmutable
                    }
                    BorrowKind::Mutable => { BorrowKind::Mutable }
                }
            }
        }
    };TypeFoldable,
372    const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for BorrowKind {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    BorrowKind::Immutable => {}
                    BorrowKind::UniqueImmutable => {}
                    BorrowKind::Mutable => {}
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable
373)]
374pub enum BorrowKind {
375    /// Data must be immutable and is aliasable.
376    Immutable,
377
378    /// Data must be immutable but not aliasable. This kind of borrow
379    /// cannot currently be expressed by the user and is used only in
380    /// implicit closure bindings. It is needed when the closure
381    /// is borrowing or mutating a mutable referent, e.g.:
382    ///
383    /// ```
384    /// let mut z = 3;
385    /// let x: &mut isize = &mut z;
386    /// let y = || *x += 5;
387    /// ```
388    ///
389    /// If we were to try to translate this closure into a more explicit
390    /// form, we'd encounter an error with the code as written:
391    ///
392    /// ```compile_fail,E0594
393    /// struct Env<'a> { x: &'a &'a mut isize }
394    /// let mut z = 3;
395    /// let x: &mut isize = &mut z;
396    /// let y = (&mut Env { x: &x }, fn_ptr);  // Closure is pair of env and fn
397    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
398    /// ```
399    ///
400    /// This is then illegal because you cannot mutate a `&mut` found
401    /// in an aliasable location. To solve, you'd have to translate with
402    /// an `&mut` borrow:
403    ///
404    /// ```compile_fail,E0596
405    /// struct Env<'a> { x: &'a mut &'a mut isize }
406    /// let mut z = 3;
407    /// let x: &mut isize = &mut z;
408    /// let y = (&mut Env { x: &mut x }, fn_ptr); // changed from &x to &mut x
409    /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
410    /// ```
411    ///
412    /// Now the assignment to `**env.x` is legal, but creating a
413    /// mutable pointer to `x` is not because `x` is not mutable. We
414    /// could fix this by declaring `x` as `let mut x`. This is ok in
415    /// user code, if awkward, but extra weird for closures, since the
416    /// borrow is hidden.
417    ///
418    /// So we introduce a "unique imm" borrow -- the referent is
419    /// immutable, but not aliasable. This solves the problem. For
420    /// simplicity, we don't give users the way to express this
421    /// borrow, it's just used when translating closures.
422    ///
423    /// FIXME: Rename this to indicate the borrow is actually not immutable.
424    UniqueImmutable,
425
426    /// Data is mutable and not aliasable.
427    Mutable,
428}
429
430impl BorrowKind {
431    pub fn from_mutbl(m: hir::Mutability) -> BorrowKind {
432        match m {
433            hir::Mutability::Mut => BorrowKind::Mutable,
434            hir::Mutability::Not => BorrowKind::Immutable,
435        }
436    }
437
438    /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
439    /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
440    /// mutability that is stronger than necessary so that it at least *would permit* the borrow in
441    /// question.
442    pub fn to_mutbl_lossy(self) -> hir::Mutability {
443        match self {
444            BorrowKind::Mutable => hir::Mutability::Mut,
445            BorrowKind::Immutable => hir::Mutability::Not,
446
447            // We have no type corresponding to a unique imm borrow, so
448            // use `&mut`. It gives all the capabilities of a `&uniq`
449            // and hence is a safe "over approximation".
450            BorrowKind::UniqueImmutable => hir::Mutability::Mut,
451        }
452    }
453}
454
455pub fn analyze_coroutine_closure_captures<'a, 'tcx: 'a, T>(
456    parent_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
457    child_captures: impl IntoIterator<Item = &'a CapturedPlace<'tcx>>,
458    mut for_each: impl FnMut((usize, &'a CapturedPlace<'tcx>), (usize, &'a CapturedPlace<'tcx>)) -> T,
459) -> impl Iterator<Item = T> {
460    gen move {
461        let mut child_captures = child_captures.into_iter().enumerate().peekable();
462
463        // One parent capture may correspond to several child captures if we end up
464        // refining the set of captures via edition-2021 precise captures. We want to
465        // match up any number of child captures with one parent capture, so we keep
466        // peeking off this `Peekable` until the child doesn't match anymore.
467        for (parent_field_idx, parent_capture) in parent_captures.into_iter().enumerate() {
468            // Make sure we use every field at least once, b/c why are we capturing something
469            // if it's not used in the inner coroutine.
470            let mut field_used_at_least_once = false;
471
472            // A parent matches a child if they share the same prefix of projections.
473            // The child may have more, if it is capturing sub-fields out of
474            // something that is captured by-move in the parent closure.
475            while child_captures.peek().is_some_and(|(_, child_capture)| {
476                child_prefix_matches_parent_projections(parent_capture, child_capture)
477            }) {
478                let (child_field_idx, child_capture) = child_captures.next().unwrap();
479                // This analysis only makes sense if the parent capture is a
480                // prefix of the child capture.
481                if !(child_capture.place.projections.len() >=
            parent_capture.place.projections.len()) {
    {
        ::core::panicking::panic_fmt(format_args!("parent capture ({0:#?}) expected to be prefix of child capture ({1:#?})",
                parent_capture, child_capture));
    }
};assert!(
482                    child_capture.place.projections.len() >= parent_capture.place.projections.len(),
483                    "parent capture ({parent_capture:#?}) expected to be prefix of \
484                    child capture ({child_capture:#?})"
485                );
486
487                yield for_each(
488                    (parent_field_idx, parent_capture),
489                    (child_field_idx, child_capture),
490                );
491
492                field_used_at_least_once = true;
493            }
494
495            // Make sure the field was used at least once.
496            if !field_used_at_least_once {
    {
        ::core::panicking::panic_fmt(format_args!("we captured {0:#?} but it was not used in the child coroutine?",
                parent_capture));
    }
};assert!(
497                field_used_at_least_once,
498                "we captured {parent_capture:#?} but it was not used in the child coroutine?"
499            );
500        }
501        {
    match (&child_captures.next(), &None) {
        (left_val, right_val) => {
            if !(*left_val == *right_val) {
                let kind = ::core::panicking::AssertKind::Eq;
                ::core::panicking::assert_failed(kind, &*left_val,
                    &*right_val,
                    ::core::option::Option::Some(format_args!("leftover child captures?")));
            }
        }
    }
};assert_eq!(child_captures.next(), None, "leftover child captures?");
502    }
503}
504
505fn child_prefix_matches_parent_projections(
506    parent_capture: &ty::CapturedPlace<'_>,
507    child_capture: &ty::CapturedPlace<'_>,
508) -> bool {
509    let HirPlaceBase::Upvar(parent_base) = parent_capture.place.base else {
510        ::rustc_span::macros::bug_impl(None,
    format_args!("expected capture to be an upvar"), Location::caller());bug!("expected capture to be an upvar");
511    };
512    let HirPlaceBase::Upvar(child_base) = child_capture.place.base else {
513        ::rustc_span::macros::bug_impl(None,
    format_args!("expected capture to be an upvar"), Location::caller());bug!("expected capture to be an upvar");
514    };
515
516    parent_base.var_path.hir_id == child_base.var_path.hir_id
517        && std::iter::zip(&child_capture.place.projections, &parent_capture.place.projections)
518            .all(|(child, parent)| child.kind == parent.kind)
519}
520
521pub fn provide(providers: &mut Providers) {
522    *providers = Providers { closure_typeinfo, ..*providers }
523}