Skip to main content

rustc_ast_lowering/
path.rs

1use std::sync::Arc;
2
3use rustc_ast::{self as ast, *};
4use rustc_attr_ir::target::{AstTarget, Target};
5use rustc_errors::StashKey;
6use rustc_hir::def::{DefKind, PerNS, Res};
7use rustc_hir::def_id::DefId;
8use rustc_hir::{self as hir, GenericArg, HirId};
9use rustc_middle::middle::resolve::PartialRes;
10use rustc_middle::ty;
11use rustc_session::diagnostics::add_feature_diagnostics;
12use rustc_span::{BytePos, DUMMY_SP, DesugaringKind, Ident, Span, Symbol, span_bug, sym};
13use smallvec::smallvec;
14use tracing::{debug, instrument};
15
16use crate::diagnostics::{
17    AsyncBoundNotOnTrait, AsyncBoundOnlyForFnTraits, BadReturnTypeNotation,
18    GenericTypeWithParentheses, RTNSuggestion, UseAngleBrackets,
19};
20use crate::{
21    AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
22    LifetimeRes, LoweringContext, ParamMode,
23};
24
25impl<'hir> LoweringContext<'_, 'hir> {
26    {}
#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::TRACE <=
                    ::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("lower_qpath",
                                    "rustc_ast_lowering::path", ::tracing::Level::TRACE,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs"),
                                    ::tracing_core::__macro_support::Option::Some(26u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_ast_lowering::path"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("id")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("id");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("qself")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("qself");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("p")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("p");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("param_mode")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("param_mode");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("allow_return_type_notation")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("allow_return_type_notation");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("itctx")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("itctx");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("modifiers")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("modifiers");
                                                        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::TRACE <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::TRACE <=
                                    ::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(&id)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&qself)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&p)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&param_mode)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&allow_return_type_notation)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&itctx)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&modifiers)
                                                            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: hir::QPath<'hir> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let qself_position = qself.as_ref().map(|q| q.position);
            let qself =
                qself.as_ref().map(|q|
                        {
                            self.lower_ty_alloc(&q.ty,
                                ImplTraitContext::Disallowed(ImplTraitPosition::Path))
                        });
            let partial_res =
                self.get_partial_res(id).unwrap_or_else(||
                        PartialRes::new(Res::Err));
            let base_res = partial_res.base_res();
            let unresolved_segments = partial_res.unresolved_segments();
            let mut res = self.lower_res(base_res);
            if let Some(TraitBoundModifiers {
                    asyncness: BoundAsyncness::Async(_), .. }) = modifiers {
                match res {
                    Res::Def(DefKind::Trait, def_id) => {
                        if let Some(async_def_id) =
                                self.map_trait_to_async_trait(def_id) {
                            res = Res::Def(DefKind::Trait, async_def_id);
                        } else {
                            self.dcx().emit_err(AsyncBoundOnlyForFnTraits {
                                    span: p.span,
                                });
                        }
                    }
                    Res::Err => {}
                    _ => {
                        self.dcx().emit_err(AsyncBoundNotOnTrait {
                                span: p.span,
                                descr: res.descr(),
                            });
                    }
                }
            }
            let bound_modifier_allowed_features =
                if let Res::Def(DefKind::Trait, async_def_id) = res &&
                        self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some()
                    {
                    Some(Arc::clone(&crate::ALLOW_ASYNC_FN_TRAITS))
                } else { None };
            let itctx =
                |i|
                    {
                        if i + 1 == p.segments.len() {
                            itctx
                        } else {
                            ImplTraitContext::Disallowed(ImplTraitPosition::Path)
                        }
                    };
            let path_span_lo = p.span.shrink_to_lo();
            let proj_start = p.segments.len() - unresolved_segments;
            let path =
                self.arena.alloc(hir::Path {
                        res,
                        segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(|(i,
                                        segment)|
                                    {
                                        let param_mode =
                                            match (qself_position, param_mode) {
                                                (Some(j), ParamMode::Optional) if i < j => {
                                                    ParamMode::Explicit
                                                }
                                                _ => param_mode,
                                            };
                                        let generic_args_mode =
                                            match base_res {
                                                Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
                                                    GenericArgsMode::ParenSugar
                                                }
                                                Res::Def(DefKind::AssocFn, _) |
                                                    Res::Def(DefKind::AssocConst, _) |
                                                    Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => {
                                                    GenericArgsMode::ParenSugar
                                                }
                                                Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
                                                    match allow_return_type_notation {
                                                        AllowReturnTypeNotation::Yes =>
                                                            GenericArgsMode::ReturnTypeNotation,
                                                        AllowReturnTypeNotation::No => GenericArgsMode::Err,
                                                    }
                                                }
                                                Res::Err => GenericArgsMode::Silence,
                                                _ => GenericArgsMode::Err,
                                            };
                                        self.lower_path_segment(p.span, segment, param_mode,
                                            generic_args_mode, itctx(i),
                                            bound_modifier_allowed_features.clone())
                                    })),
                        span: self.lower_span(p.segments[..proj_start].last().map_or(path_span_lo,
                                |segment| path_span_lo.to(segment.span()))),
                    });
            if let Some(bound_modifier_allowed_features) =
                    bound_modifier_allowed_features {
                path.span =
                    self.mark_span_with_reason(DesugaringKind::BoundModifier,
                        path.span, Some(bound_modifier_allowed_features));
            }
            if unresolved_segments == 0 {
                return hir::QPath::Resolved(qself, path);
            }
            let mut ty =
                if path.segments.is_empty() {
                    qself.expect("missing QSelf for <T>::...")
                } else {
                    let new_id = self.next_id();
                    self.arena.alloc(self.ty_path(new_id, path.span,
                            hir::QPath::Resolved(qself, path)))
                };
            for (i, segment) in p.segments.iter().enumerate().skip(proj_start)
                {
                let generic_args_mode =
                    if i + 1 == p.segments.len() &&
                            #[allow(non_exhaustive_omitted_patterns)] match allow_return_type_notation
                                {
                                AllowReturnTypeNotation::Yes => true,
                                _ => false,
                            } {
                        GenericArgsMode::ReturnTypeNotation
                    } else { GenericArgsMode::Err };
                let hir_segment =
                    self.arena.alloc(self.lower_path_segment(p.span, segment,
                            param_mode, generic_args_mode, itctx(i), None));
                let qpath = hir::QPath::TypeRelative(ty, hir_segment);
                if i == p.segments.len() - 1 { return qpath; }
                let new_id = self.next_id();
                ty =
                    self.arena.alloc(self.ty_path(new_id,
                            path_span_lo.to(segment.span()), qpath));
            }
            self.dcx().span_bug(p.span,
                ::alloc::__export::must_use({
                        ::alloc::fmt::format(format_args!("lower_qpath: no final extension segment in {0}..{1}",
                                proj_start, p.segments.len()))
                    }));
        }
    }
}#[instrument(level = "trace", skip(self))]
27    pub(crate) fn lower_qpath(
28        &mut self,
29        id: NodeId,
30        qself: &Option<Box<QSelf>>,
31        p: &Path,
32        param_mode: ParamMode,
33        allow_return_type_notation: AllowReturnTypeNotation,
34        itctx: ImplTraitContext,
35        // modifiers of the impl/bound if this is a trait path
36        modifiers: Option<ast::TraitBoundModifiers>,
37    ) -> hir::QPath<'hir> {
38        let qself_position = qself.as_ref().map(|q| q.position);
39        let qself = qself
40            .as_ref()
41            // Reject cases like `<impl Trait>::Assoc` and `<impl Trait as Trait>::Assoc`.
42            .map(|q| {
43                self.lower_ty_alloc(&q.ty, ImplTraitContext::Disallowed(ImplTraitPosition::Path))
44            });
45
46        let partial_res = self.get_partial_res(id).unwrap_or_else(|| PartialRes::new(Res::Err));
47        let base_res = partial_res.base_res();
48        let unresolved_segments = partial_res.unresolved_segments();
49
50        let mut res = self.lower_res(base_res);
51
52        // When we have an `async` kw on a bound, map the trait it resolves to.
53        if let Some(TraitBoundModifiers { asyncness: BoundAsyncness::Async(_), .. }) = modifiers {
54            match res {
55                Res::Def(DefKind::Trait, def_id) => {
56                    if let Some(async_def_id) = self.map_trait_to_async_trait(def_id) {
57                        res = Res::Def(DefKind::Trait, async_def_id);
58                    } else {
59                        self.dcx().emit_err(AsyncBoundOnlyForFnTraits { span: p.span });
60                    }
61                }
62                Res::Err => {
63                    // No additional error.
64                }
65                _ => {
66                    // This error isn't actually emitted AFAICT, but it's best to keep
67                    // it around in case the resolver doesn't always check the defkind
68                    // of an item or something.
69                    self.dcx().emit_err(AsyncBoundNotOnTrait { span: p.span, descr: res.descr() });
70                }
71            }
72        }
73
74        // Ungate the `async_fn_traits` feature in the path if the trait is
75        // named via either `async Fn*()` or `AsyncFn*()`.
76        let bound_modifier_allowed_features = if let Res::Def(DefKind::Trait, async_def_id) = res
77            && self.tcx.async_fn_trait_kind_from_def_id(async_def_id).is_some()
78        {
79            Some(Arc::clone(&crate::ALLOW_ASYNC_FN_TRAITS))
80        } else {
81            None
82        };
83
84        // Only permit `impl Trait` in the final segment. E.g., we permit `Option<impl Trait>`,
85        // `option::Option<T>::Xyz<impl Trait>` and reject `option::Option<impl Trait>::Xyz`.
86        let itctx = |i| {
87            if i + 1 == p.segments.len() {
88                itctx
89            } else {
90                ImplTraitContext::Disallowed(ImplTraitPosition::Path)
91            }
92        };
93
94        let path_span_lo = p.span.shrink_to_lo();
95        let proj_start = p.segments.len() - unresolved_segments;
96        let path = self.arena.alloc(hir::Path {
97            res,
98            segments: self.arena.alloc_from_iter(p.segments[..proj_start].iter().enumerate().map(
99                |(i, segment)| {
100                    let param_mode = match (qself_position, param_mode) {
101                        (Some(j), ParamMode::Optional) if i < j => {
102                            // This segment is part of the trait path in a
103                            // qualified path - one of `a`, `b` or `Trait`
104                            // in `<X as a::b::Trait>::T::U::method`.
105                            ParamMode::Explicit
106                        }
107                        _ => param_mode,
108                    };
109
110                    let generic_args_mode = match base_res {
111                        // `a::b::Trait(Args)`
112                        Res::Def(DefKind::Trait, _) if i + 1 == proj_start => {
113                            GenericArgsMode::ParenSugar
114                        }
115                        // `a::b::Trait(Args)::TraitItem`
116                        Res::Def(DefKind::AssocFn, _)
117                        | Res::Def(DefKind::AssocConst, _)
118                        | Res::Def(DefKind::AssocTy, _)
119                            if i + 2 == proj_start =>
120                        {
121                            GenericArgsMode::ParenSugar
122                        }
123                        Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
124                            match allow_return_type_notation {
125                                AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation,
126                                AllowReturnTypeNotation::No => GenericArgsMode::Err,
127                            }
128                        }
129                        // Avoid duplicated errors.
130                        Res::Err => GenericArgsMode::Silence,
131                        // An error
132                        _ => GenericArgsMode::Err,
133                    };
134
135                    self.lower_path_segment(
136                        p.span,
137                        segment,
138                        param_mode,
139                        generic_args_mode,
140                        itctx(i),
141                        bound_modifier_allowed_features.clone(),
142                    )
143                },
144            )),
145            span: self.lower_span(
146                p.segments[..proj_start]
147                    .last()
148                    .map_or(path_span_lo, |segment| path_span_lo.to(segment.span())),
149            ),
150        });
151
152        if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features {
153            path.span = self.mark_span_with_reason(
154                DesugaringKind::BoundModifier,
155                path.span,
156                Some(bound_modifier_allowed_features),
157            );
158        }
159
160        // Simple case, either no projections, or only fully-qualified.
161        // E.g., `std::mem::size_of` or `<I as Iterator>::Item`.
162        if unresolved_segments == 0 {
163            return hir::QPath::Resolved(qself, path);
164        }
165
166        // Create the innermost type that we're projecting from.
167        let mut ty = if path.segments.is_empty() {
168            // If the base path is empty that means there exists a
169            // syntactical `Self`, e.g., `&i32` in `<&i32>::clone`.
170            qself.expect("missing QSelf for <T>::...")
171        } else {
172            // Otherwise, the base path is an implicit `Self` type path,
173            // e.g., `Vec` in `Vec::new` or `<I as Iterator>::Item` in
174            // `<I as Iterator>::Item::default`.
175            let new_id = self.next_id();
176            self.arena.alloc(self.ty_path(new_id, path.span, hir::QPath::Resolved(qself, path)))
177        };
178
179        // Anything after the base path are associated "extensions",
180        // out of which all but the last one are associated types,
181        // e.g., for `std::vec::Vec::<T>::IntoIter::Item::clone`:
182        // * base path is `std::vec::Vec<T>`
183        // * "extensions" are `IntoIter`, `Item` and `clone`
184        // * type nodes are:
185        //   1. `std::vec::Vec<T>` (created above)
186        //   2. `<std::vec::Vec<T>>::IntoIter`
187        //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
188        // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
189        for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
190            // If this is a type-dependent `T::method(..)`.
191            let generic_args_mode = if i + 1 == p.segments.len()
192                && matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes)
193            {
194                GenericArgsMode::ReturnTypeNotation
195            } else {
196                GenericArgsMode::Err
197            };
198
199            let hir_segment = self.arena.alloc(self.lower_path_segment(
200                p.span,
201                segment,
202                param_mode,
203                generic_args_mode,
204                itctx(i),
205                None,
206            ));
207            let qpath = hir::QPath::TypeRelative(ty, hir_segment);
208
209            // It's finished, return the extension of the right node type.
210            if i == p.segments.len() - 1 {
211                return qpath;
212            }
213
214            // Wrap the associated extension in another type node.
215            let new_id = self.next_id();
216            ty = self.arena.alloc(self.ty_path(new_id, path_span_lo.to(segment.span()), qpath));
217        }
218
219        // We should've returned in the for loop above.
220
221        self.dcx().span_bug(
222            p.span,
223            format!(
224                "lower_qpath: no final extension segment in {}..{}",
225                proj_start,
226                p.segments.len()
227            ),
228        );
229    }
230
231    pub(crate) fn lower_use_path(
232        &mut self,
233        res: PerNS<Option<Res>>,
234        p: &Path,
235        param_mode: ParamMode,
236    ) -> &'hir hir::UsePath<'hir> {
237        if !!res.is_empty() {
    ::core::panicking::panic("assertion failed: !res.is_empty()")
};assert!(!res.is_empty());
238        self.arena.alloc(hir::UsePath {
239            res,
240            segments: self.arena.alloc_from_iter(p.segments.iter().map(|segment| {
241                self.lower_path_segment(
242                    p.span,
243                    segment,
244                    param_mode,
245                    GenericArgsMode::Err,
246                    ImplTraitContext::Disallowed(ImplTraitPosition::Path),
247                    None,
248                )
249            })),
250            span: self.lower_span(p.span),
251        })
252    }
253
254    pub(crate) fn lower_path_segment(
255        &mut self,
256        path_span: Span,
257        segment: &PathSegment,
258        param_mode: ParamMode,
259        generic_args_mode: GenericArgsMode,
260        itctx: ImplTraitContext,
261        // Additional features ungated with a bound modifier like `async`.
262        // This is passed down to the implicit associated type binding in
263        // parenthesized bounds.
264        bound_modifier_allowed_features: Option<Arc<[Symbol]>>,
265    ) -> hir::PathSegment<'hir> {
266        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs:266",
                        "rustc_ast_lowering::path", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs"),
                        ::tracing_core::__macro_support::Option::Some(266u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_ast_lowering::path"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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(&format_args!("path_span: {0:?}, lower_path_segment(segment: {1:?})",
                                                    path_span, segment) as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!("path_span: {:?}, lower_path_segment(segment: {:?})", path_span, segment);
267
268        let res = self.expect_full_res(segment.id);
269        let hir_id = self.lower_node_id(segment.id);
270
271        let (mut generic_args, infer_args) = if let Some(generic_args) = segment.args.as_deref() {
272            match generic_args {
273                GenericArgs::AngleBracketed(data) => {
274                    self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
275                }
276                GenericArgs::Parenthesized(data) => match generic_args_mode {
277                    GenericArgsMode::ReturnTypeNotation => {
278                        let err = match (&data.inputs[..], &data.output) {
279                            ([_, ..], FnRetTy::Default(_)) => {
280                                BadReturnTypeNotation::Inputs { span: data.inputs_span }
281                            }
282                            ([], FnRetTy::Default(_)) => {
283                                BadReturnTypeNotation::NeedsDots { span: data.inputs_span }
284                            }
285                            // The case `T: Trait<method(..) -> Ret>` is handled in the parser.
286                            (_, FnRetTy::Ty(ty)) => {
287                                let span = data.inputs_span.shrink_to_hi().to(ty.span);
288                                BadReturnTypeNotation::Output {
289                                    span,
290                                    suggestion: RTNSuggestion {
291                                        output: span,
292                                        input: data.inputs_span,
293                                    },
294                                }
295                            }
296                        };
297                        let mut err = self.dcx().create_err(err);
298                        if !self.tcx.features().return_type_notation()
299                            && self.tcx.sess.is_nightly_build()
300                        {
301                            add_feature_diagnostics(
302                                &mut err,
303                                &self.tcx.sess,
304                                sym::return_type_notation,
305                            );
306                        }
307                        err.stash(path_span, StashKey::ReturnTypeNotation);
308                        (
309                            GenericArgsCtor {
310                                args: Default::default(),
311                                constraints: &[],
312                                parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
313                                span: path_span,
314                            },
315                            false,
316                        )
317                    }
318                    GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
319                        .lower_parenthesized_parameter_data(
320                            data,
321                            itctx,
322                            bound_modifier_allowed_features,
323                            hir_id,
324                        ),
325                    GenericArgsMode::Err => {
326                        // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
327                        let sub = if !data.inputs.is_empty() {
328                            // Start of the span to the 1st character of 1st argument
329                            let open_param = data.inputs_span.shrink_to_lo().to(data
330                                .inputs
331                                .first()
332                                .unwrap()
333                                .span
334                                .shrink_to_lo());
335                            // Last character position of last argument to the end of the span
336                            let close_param = data
337                                .inputs
338                                .last()
339                                .unwrap()
340                                .span
341                                .shrink_to_hi()
342                                .to(data.inputs_span.shrink_to_hi());
343
344                            Some(UseAngleBrackets { open_param, close_param })
345                        } else {
346                            None
347                        };
348                        let guar = self
349                            .dcx()
350                            .emit_err(GenericTypeWithParentheses { span: data.span, sub });
351                        (
352                            self.lower_angle_bracketed_parameter_data(
353                                &data.as_angle_bracketed_args(),
354                                param_mode,
355                                ImplTraitContext::AlreadyErrored(guar),
356                            )
357                            .0,
358                            false,
359                        )
360                    }
361                },
362                GenericArgs::ParenthesizedElided(span) => {
363                    match generic_args_mode {
364                        GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
365                            // Ok
366                        }
367                        GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
368                            self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
369                        }
370                    }
371                    (
372                        GenericArgsCtor {
373                            args: Default::default(),
374                            constraints: &[],
375                            parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
376                            span: *span,
377                        },
378                        false,
379                    )
380                }
381            }
382        } else {
383            (
384                GenericArgsCtor {
385                    args: Default::default(),
386                    constraints: &[],
387                    parenthesized: hir::GenericArgsParentheses::No,
388                    span: path_span.shrink_to_hi(),
389                },
390                param_mode == ParamMode::Optional,
391            )
392        };
393
394        let has_lifetimes =
395            generic_args.args.iter().any(|arg| #[allow(non_exhaustive_omitted_patterns)] match arg {
    GenericArg::Lifetime(_) => true,
    _ => false,
}matches!(arg, GenericArg::Lifetime(_)));
396
397        // FIXME(return_type_notation): Is this correct? I think so.
398        if generic_args.parenthesized != hir::GenericArgsParentheses::ParenSugar && !has_lifetimes {
399            self.maybe_insert_elided_lifetimes_in_path(
400                path_span,
401                segment.id,
402                segment.ident.span,
403                &mut generic_args,
404            );
405        }
406
407        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs:407",
                        "rustc_ast_lowering::path", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs"),
                        ::tracing_core::__macro_support::Option::Some(407u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_ast_lowering::path"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::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(&format_args!("lower_path_segment: ident={0:?} original-id={1:?} new-id={2:?}",
                                                    segment.ident, segment.id, hir_id) as
                                            &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(
408            "lower_path_segment: ident={:?} original-id={:?} new-id={:?}",
409            segment.ident, segment.id, hir_id,
410        );
411        hir::PathSegment {
412            ident: self.lower_ident(segment.ident),
413            hir_id,
414            res: self.lower_res(res),
415            infer_args,
416            args: if generic_args.is_empty() && generic_args.span.is_empty() {
417                None
418            } else {
419                Some(generic_args.into_generic_args(self))
420            },
421            delegation_child_segment: false,
422        }
423    }
424
425    fn maybe_insert_elided_lifetimes_in_path(
426        &mut self,
427        path_span: Span,
428        segment_id: NodeId,
429        segment_ident_span: Span,
430        generic_args: &mut GenericArgsCtor<'hir>,
431    ) {
432        let (start, end) = match self.curr_owner.owner.get_lifetime_res(segment_id) {
433            Some(LifetimeRes::ElidedAnchor { start, end }) => (start, end),
434            None => return,
435            Some(res) => {
436                ::rustc_span::macros::bug_impl(Some(path_span),
    format_args!("expected an elided lifetime to insert. found {0:?}", res),
    Location::caller())span_bug!(path_span, "expected an elided lifetime to insert. found {res:?}")
437            }
438        };
439        let expected_lifetimes = end.as_usize() - start.as_usize();
440        {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs:440",
                        "rustc_ast_lowering::path", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/92b5b8c87c61b20adc9001b41baf587634a74734/compiler/rustc_ast_lowering/src/path.rs"),
                        ::tracing_core::__macro_support::Option::Some(440u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_ast_lowering::path"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("expected_lifetimes")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("expected_lifetimes");
                                            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(&expected_lifetimes
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(expected_lifetimes);
441
442        // Note: these spans are used for diagnostics when they can't be inferred.
443        // See rustc_resolve::late::lifetimes::LifetimeContext::add_missing_lifetime_specifiers_label
444        let (elided_lifetime_span, angle_brackets) = if generic_args.span.is_empty() {
445            // No brackets, e.g. `Path`: use an empty span just past the end of the identifier.
446            // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
447            // originating from macros, since the segment's span might be from a macro arg.
448            (
449                segment_ident_span.find_ancestor_inside(path_span).unwrap_or(path_span),
450                hir::AngleBrackets::Missing,
451            )
452        } else {
453            // Brackets, e.g. `Path<>` or `Path<T>`: use an empty span just after the `<`.
454            (
455                generic_args.span.with_lo(generic_args.span.lo() + BytePos(1)).shrink_to_lo(),
456                if generic_args.is_empty() {
457                    hir::AngleBrackets::Empty
458                } else {
459                    hir::AngleBrackets::Full
460                },
461            )
462        };
463
464        generic_args.args.insert_many(
465            0,
466            (start..end).map(|id| {
467                let l =
468                    self.lower_lifetime_hidden_in_path(id, elided_lifetime_span, angle_brackets);
469                GenericArg::Lifetime(l)
470            }),
471        );
472    }
473
474    pub(crate) fn lower_angle_bracketed_parameter_data(
475        &mut self,
476        data: &AngleBracketedArgs,
477        param_mode: ParamMode,
478        itctx: ImplTraitContext,
479    ) -> (GenericArgsCtor<'hir>, bool) {
480        let has_non_lt_args = data.args.iter().any(|arg| match arg {
481            AngleBracketedArg::Arg(ast::GenericArg::Lifetime(_))
482            | AngleBracketedArg::Constraint(_) => false,
483            AngleBracketedArg::Arg(ast::GenericArg::Type(_) | ast::GenericArg::Const(_)) => true,
484        });
485        let args = data
486            .args
487            .iter()
488            .filter_map(|arg| match arg {
489                AngleBracketedArg::Arg(arg) => Some(self.lower_generic_arg(arg, itctx)),
490                AngleBracketedArg::Constraint(_) => None,
491            })
492            .collect();
493        let constraints =
494            self.arena.alloc_from_iter(data.args.iter().filter_map(|arg| match arg {
495                AngleBracketedArg::Constraint(c) => {
496                    Some(self.lower_assoc_item_constraint(c, itctx))
497                }
498                AngleBracketedArg::Arg(_) => None,
499            }));
500        let ctor = GenericArgsCtor {
501            args,
502            constraints,
503            parenthesized: hir::GenericArgsParentheses::No,
504            span: data.span,
505        };
506        (ctor, !has_non_lt_args && param_mode == ParamMode::Optional)
507    }
508
509    fn lower_parenthesized_parameter_data(
510        &mut self,
511        data: &ParenthesizedArgs,
512        itctx: ImplTraitContext,
513        bound_modifier_allowed_features: Option<Arc<[Symbol]>>,
514        segment_hir_id: HirId,
515    ) -> (GenericArgsCtor<'hir>, bool) {
516        // Switch to `PassThrough` mode for anonymous lifetimes; this
517        // means that we permit things like `&Ref<T>`, where `Ref` has
518        // a hidden lifetime parameter. This is needed for backwards
519        // compatibility, even in contexts like an impl header where
520        // we generally don't permit such things (see #51008).
521        let ParenthesizedArgs { span, inputs, inputs_span, output } = data;
522
523        // FIXME uses the segments HIR id which is not correct, it should
524        // be the parameters HIR id instead. This is currently not lowered.
525        for input in inputs {
526            self.lower_attrs(
527                segment_hir_id,
528                &input.attrs,
529                input.span,
530                Target::Param,
531                AstTarget::Param(input),
532            );
533        }
534
535        let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| {
536            self.lower_ty(&param.ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitParam))
537        }));
538        let output_ty = match output {
539            // Only allow `impl Trait` in return position. i.e.:
540            // ```rust
541            // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
542            // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
543            // ```
544            FnRetTy::Ty(ty) if #[allow(non_exhaustive_omitted_patterns)] match itctx {
    ImplTraitContext::OpaqueTy { .. } => true,
    _ => false,
}matches!(itctx, ImplTraitContext::OpaqueTy { .. }) => {
545                if self.tcx.features().impl_trait_in_fn_trait_return() {
546                    self.lower_ty_alloc(ty, itctx)
547                } else {
548                    self.lower_ty_alloc(
549                        ty,
550                        ImplTraitContext::FeatureGated(
551                            ImplTraitPosition::FnTraitReturn,
552                            sym::impl_trait_in_fn_trait_return,
553                        ),
554                    )
555                }
556            }
557            FnRetTy::Ty(ty) => self
558                .lower_ty_alloc(ty, ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn)),
559            FnRetTy::Default(_) => self.arena.alloc(self.ty_tup(*span, &[])),
560        };
561        let args = {
    let count = 0usize + 1usize;
    let mut vec = ::smallvec::SmallVec::new();
    if count <= vec.inline_size() {
        vec.push(GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span,
                                inputs)).try_as_ambig_ty().unwrap()));
        vec
    } else {
        ::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
                    [GenericArg::Type(self.arena.alloc(self.ty_tup(*inputs_span,
                                                inputs)).try_as_ambig_ty().unwrap())])))
    }
}smallvec![GenericArg::Type(
562            self.arena.alloc(self.ty_tup(*inputs_span, inputs)).try_as_ambig_ty().unwrap()
563        )];
564
565        // If we have a bound like `async Fn() -> T`, make sure that we mark the
566        // `Output = T` associated type bound with the right feature gates.
567        let mut output_span = output_ty.span;
568        if let Some(bound_modifier_allowed_features) = bound_modifier_allowed_features {
569            output_span = self.mark_span_with_reason(
570                DesugaringKind::BoundModifier,
571                output_span,
572                Some(bound_modifier_allowed_features),
573            );
574        }
575        let constraint = self.assoc_ty_binding(sym::Output, output_span, output_ty);
576
577        (
578            GenericArgsCtor {
579                args,
580                constraints: self.arena.alloc_from_iter([constraint])arena_vec![self; constraint],
581                parenthesized: hir::GenericArgsParentheses::ParenSugar,
582                span: data.inputs_span,
583            },
584            false,
585        )
586    }
587
588    /// An associated type binding (i.e., associated type equality constraint).
589    pub(crate) fn assoc_ty_binding(
590        &mut self,
591        assoc_ty_name: rustc_span::Symbol,
592        span: Span,
593        ty: &'hir hir::Ty<'hir>,
594    ) -> hir::AssocItemConstraint<'hir> {
595        let ident = Ident::with_dummy_span(assoc_ty_name);
596        let kind = hir::AssocItemConstraintKind::Equality { term: ty.into() };
597        let args = self.arena.alloc_from_iter([])arena_vec![self;];
598        let constraints = self.arena.alloc_from_iter([])arena_vec![self;];
599        let gen_args = self.arena.alloc(hir::GenericArgs {
600            args,
601            constraints,
602            parenthesized: hir::GenericArgsParentheses::No,
603            span_ext: DUMMY_SP,
604        });
605        hir::AssocItemConstraint {
606            hir_id: self.next_id(),
607            gen_args,
608            span: self.lower_span(span),
609            ident,
610            kind,
611        }
612    }
613
614    /// When a bound is annotated with `async`, it signals to lowering that the trait
615    /// that the bound refers to should be mapped to the "async" flavor of the trait.
616    ///
617    /// This only needs to be done until we unify `AsyncFn` and `Fn` traits into one
618    /// that is generic over `async`ness, if that's ever possible, or modify the
619    /// lowering of `async Fn()` bounds to desugar to another trait like `LendingFn`.
620    fn map_trait_to_async_trait(&self, def_id: DefId) -> Option<DefId> {
621        let lang_items = self.tcx.lang_items();
622        match self.tcx.fn_trait_kind_from_def_id(def_id)? {
623            ty::ClosureKind::Fn => lang_items.async_fn_trait(),
624            ty::ClosureKind::FnMut => lang_items.async_fn_mut_trait(),
625            ty::ClosureKind::FnOnce => lang_items.async_fn_once_trait(),
626        }
627    }
628}