Skip to main content

rustc_hir_analysis/
collect.rs

1//! "Collection" is the process of determining the type and other external
2//! details of each item in Rust. Collection is specifically concerned
3//! with *inter-procedural* things -- for example, for a function
4//! definition, collection will figure out the type and signature of the
5//! function, but it will not visit the *body* of the function in any way,
6//! nor examine type annotations on local variables (that's the job of
7//! type *checking*).
8//!
9//! Collecting is ultimately defined by a bundle of queries that
10//! inquire after various facts about the items in the crate (e.g.,
11//! `type_of`, `generics_of`, `predicates_of`, etc). See the `provide` function
12//! for the full set.
13//!
14//! At present, however, we do run collection across all items in the
15//! crate as a kind of pass. This should eventually be factored away.
16
17use std::cell::Cell;
18use std::iter;
19use std::ops::{Bound, ControlFlow};
20
21use rustc_abi::{ExternAbi, Size};
22use rustc_ast::Recovered;
23use rustc_data_structures::assert_matches;
24use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
25use rustc_errors::{Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey};
26use rustc_hir::def::{DefKind, Res};
27use rustc_hir::def_id::{DefId, LocalDefId};
28use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
29use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr};
30use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
31use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
32use rustc_middle::hir::nested_filter;
33use rustc_middle::query::Providers;
34use rustc_middle::ty::util::{Discr, IntTypeExt};
35use rustc_middle::ty::{
36    self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, fold_regions,
37};
38use rustc_middle::{bug, span_bug};
39use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
40use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
41use rustc_trait_selection::infer::InferCtxtExt;
42use rustc_trait_selection::traits::{
43    FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
44};
45use tracing::{debug, instrument};
46
47use crate::errors;
48use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason};
49
50pub(crate) mod dump;
51mod generics_of;
52mod item_bounds;
53mod predicates_of;
54mod resolve_bound_vars;
55mod type_of;
56
57///////////////////////////////////////////////////////////////////////////
58
59/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
60pub(crate) fn provide(providers: &mut Providers) {
61    resolve_bound_vars::provide(providers);
62    *providers = Providers {
63        type_of: type_of::type_of,
64        type_of_opaque: type_of::type_of_opaque,
65        type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
66        type_alias_is_lazy: type_of::type_alias_is_lazy,
67        item_bounds: item_bounds::item_bounds,
68        explicit_item_bounds: item_bounds::explicit_item_bounds,
69        item_self_bounds: item_bounds::item_self_bounds,
70        explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
71        item_non_self_bounds: item_bounds::item_non_self_bounds,
72        impl_super_outlives: item_bounds::impl_super_outlives,
73        generics_of: generics_of::generics_of,
74        predicates_of: predicates_of::predicates_of,
75        explicit_predicates_of: predicates_of::explicit_predicates_of,
76        explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
77        explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
78        explicit_supertraits_containing_assoc_item:
79            predicates_of::explicit_supertraits_containing_assoc_item,
80        trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
81        const_conditions: predicates_of::const_conditions,
82        explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
83        type_param_predicates: predicates_of::type_param_predicates,
84        trait_def,
85        adt_def,
86        fn_sig,
87        impl_trait_header,
88        coroutine_kind,
89        coroutine_for_closure,
90        opaque_ty_origin,
91        rendered_precise_capturing_args,
92        const_param_default,
93        anon_const_kind,
94        const_of_item,
95        ..*providers
96    };
97}
98
99///////////////////////////////////////////////////////////////////////////
100
101/// Context specific to some particular item. This is what implements [`HirTyLowerer`].
102///
103/// # `ItemCtxt` vs `FnCtxt`
104///
105/// `ItemCtxt` is primarily used to type-check item signatures and lower them
106/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`].
107/// It's also used for the bodies of items like structs where the body (the fields)
108/// are just signatures.
109///
110/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
111/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
112///
113/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
114/// while `FnCtxt` does do inference.
115///
116/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
117///
118/// # Trait predicates
119///
120/// `ItemCtxt` has information about the predicates that are defined
121/// on the trait. Unfortunately, this predicate information is
122/// available in various different forms at various points in the
123/// process. So we can't just store a pointer to e.g., the HIR or the
124/// parsed ty form, we have to be more flexible. To this end, the
125/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
126/// `probe_ty_param_bounds` requests, drawing the information from
127/// the HIR (`hir::Generics`), recursively.
128pub(crate) struct ItemCtxt<'tcx> {
129    tcx: TyCtxt<'tcx>,
130    item_def_id: LocalDefId,
131    tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
132}
133
134///////////////////////////////////////////////////////////////////////////
135
136#[derive(#[automatically_derived]
impl ::core::default::Default for HirPlaceholderCollector {
    #[inline]
    fn default() -> HirPlaceholderCollector {
        HirPlaceholderCollector {
            spans: ::core::default::Default::default(),
            may_contain_const_infer: ::core::default::Default::default(),
        }
    }
}Default)]
137pub(crate) struct HirPlaceholderCollector {
138    pub spans: Vec<Span>,
139    // If any of the spans points to a const infer var, then suppress any messages
140    // that may try to turn that const infer into a type parameter.
141    pub may_contain_const_infer: bool,
142}
143
144impl<'v> Visitor<'v> for HirPlaceholderCollector {
145    fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
146        self.spans.push(inf_span);
147
148        if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
149            self.may_contain_const_infer = true;
150        }
151    }
152}
153
154fn placeholder_type_error_diag<'cx, 'tcx>(
155    cx: &'cx dyn HirTyLowerer<'tcx>,
156    generics: Option<&hir::Generics<'_>>,
157    placeholder_types: Vec<Span>,
158    additional_spans: Vec<Span>,
159    suggest: bool,
160    hir_ty: Option<&hir::Ty<'_>>,
161    kind: &'static str,
162) -> Diag<'cx> {
163    if placeholder_types.is_empty() {
164        return bad_placeholder(cx, additional_spans, kind);
165    }
166
167    let params = generics.map(|g| g.params).unwrap_or_default();
168    let type_name = params.next_type_param_name(None);
169    let mut sugg: Vec<_> =
170        placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
171
172    if let Some(generics) = generics {
173        if let Some(span) = params.iter().find_map(|arg| match arg.name {
174            hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
175            _ => None,
176        }) {
177            // Account for `_` already present in cases like `struct S<_>(_);` and suggest
178            // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
179            sugg.push((span, (*type_name).to_string()));
180        } else if let Some(span) = generics.span_for_param_suggestion() {
181            // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
182            sugg.push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", type_name))
    })format!(", {type_name}")));
183        } else {
184            sugg.push((generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", type_name))
    })format!("<{type_name}>")));
185        }
186    }
187
188    let mut err =
189        bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
190
191    // Suggest, but only if it is not a function in const or static
192    if suggest {
193        let mut is_fn = false;
194        let mut is_const_or_static = false;
195
196        if let Some(hir_ty) = hir_ty
197            && let hir::TyKind::FnPtr(_) = hir_ty.kind
198        {
199            is_fn = true;
200
201            // Check if parent is const or static
202            is_const_or_static = #[allow(non_exhaustive_omitted_patterns)] match cx.tcx().parent_hir_node(hir_ty.hir_id)
    {
    Node::Item(&hir::Item {
        kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), .. }) |
        Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..),
        .. }) |
        Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), ..
        }) => true,
    _ => false,
}matches!(
203                cx.tcx().parent_hir_node(hir_ty.hir_id),
204                Node::Item(&hir::Item {
205                    kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
206                    ..
207                }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
208                    | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
209            );
210        }
211
212        // if function is wrapped around a const or static,
213        // then don't show the suggestion
214        if !(is_fn && is_const_or_static) {
215            err.multipart_suggestion(
216                "use type parameters instead",
217                sugg,
218                Applicability::HasPlaceholders,
219            );
220        }
221    }
222
223    err
224}
225
226///////////////////////////////////////////////////////////////////////////
227// Utility types and common code for the above passes.
228
229fn bad_placeholder<'cx, 'tcx>(
230    cx: &'cx dyn HirTyLowerer<'tcx>,
231    mut spans: Vec<Span>,
232    kind: &'static str,
233) -> Diag<'cx> {
234    let kind = if kind.ends_with('s') { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}es", kind))
    })format!("{kind}es") } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}s", kind))
    })format!("{kind}s") };
235
236    spans.sort();
237    cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
238}
239
240impl<'tcx> ItemCtxt<'tcx> {
241    pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
242        ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
243    }
244
245    pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
246        self.lowerer().lower_ty(hir_ty)
247    }
248
249    pub(crate) fn hir_id(&self) -> hir::HirId {
250        self.tcx.local_def_id_to_hir_id(self.item_def_id)
251    }
252
253    pub(crate) fn node(&self) -> hir::Node<'tcx> {
254        self.tcx.hir_node(self.hir_id())
255    }
256
257    fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
258        match self.tainted_by_errors.get() {
259            Some(err) => Err(err),
260            None => Ok(()),
261        }
262    }
263
264    fn report_placeholder_type_error(
265        &self,
266        placeholder_types: Vec<Span>,
267        infer_replacements: Vec<(Span, String)>,
268    ) -> ErrorGuaranteed {
269        let node = self.tcx.hir_node_by_def_id(self.item_def_id);
270        let generics = node.generics();
271        let kind_id = match node {
272            Node::GenericParam(_) | Node::WherePredicate(_) | Node::Field(_) => {
273                self.tcx.local_parent(self.item_def_id)
274            }
275            _ => self.item_def_id,
276        };
277        let kind = self.tcx.def_descr(kind_id.into());
278        let mut diag = placeholder_type_error_diag(
279            self,
280            generics,
281            placeholder_types,
282            infer_replacements.iter().map(|&(span, _)| span).collect(),
283            false,
284            None,
285            kind,
286        );
287        if !infer_replacements.is_empty() {
288            diag.multipart_suggestion(
289                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("try replacing `_` with the type{0} in the corresponding trait method signature",
                if infer_replacements.len() == 1 { "" } else { "s" }))
    })format!(
290                    "try replacing `_` with the type{} in the corresponding trait method \
291                        signature",
292                    rustc_errors::pluralize!(infer_replacements.len()),
293                ),
294                infer_replacements,
295                Applicability::MachineApplicable,
296            );
297        }
298
299        diag.emit()
300    }
301}
302
303impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
304    fn tcx(&self) -> TyCtxt<'tcx> {
305        self.tcx
306    }
307
308    fn dcx(&self) -> DiagCtxtHandle<'_> {
309        self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
310    }
311
312    fn item_def_id(&self) -> LocalDefId {
313        self.item_def_id
314    }
315
316    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
317        if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason {
318            // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in
319            //        `*const dyn Trait` and `Fn() -> *const dyn Trait`.
320            let guar = self
321                .dcx()
322                .struct_span_err(
323                    span,
324                    "cannot deduce the lifetime bound for this trait object type from context",
325                )
326                .with_code(E0228)
327                .with_span_suggestion_verbose(
328                    sugg_sp,
329                    "please supply an explicit bound",
330                    " + /* 'a */",
331                    Applicability::HasPlaceholders,
332                )
333                .emit();
334            ty::Region::new_error(self.tcx(), guar)
335        } else {
336            // This indicates an illegal lifetime in a non-assoc-trait position
337            ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
338        }
339    }
340
341    fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
342        if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) {
343            self.report_placeholder_type_error(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [span]))vec![span], ::alloc::vec::Vec::new()vec![]);
344        }
345        Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
346    }
347
348    fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
349        self.report_placeholder_type_error(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [span]))vec![span], ::alloc::vec::Vec::new()vec![]);
350        ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
351    }
352
353    fn register_trait_ascription_bounds(
354        &self,
355        _: Vec<(ty::Clause<'tcx>, Span)>,
356        _: HirId,
357        span: Span,
358    ) {
359        self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
360    }
361
362    fn probe_ty_param_bounds(
363        &self,
364        span: Span,
365        def_id: LocalDefId,
366        assoc_ident: Ident,
367    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
368        self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
369    }
370
371    x;#[instrument(level = "debug", skip(self, _span), ret)]
372    fn select_inherent_assoc_candidates(
373        &self,
374        _span: Span,
375        self_ty: Ty<'tcx>,
376        candidates: Vec<InherentAssocCandidate>,
377    ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
378        assert!(!self_ty.has_infer());
379
380        // We don't just call the normal normalization routine here as we can't provide the
381        // correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
382        // the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
383        // this just to make resolution a little bit smarter.
384        let self_ty = self.tcx.expand_free_alias_tys(self_ty);
385        debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
386
387        let candidates = candidates
388            .into_iter()
389            .filter(|&InherentAssocCandidate { impl_, .. }| {
390                let impl_ty = self.tcx().type_of(impl_).instantiate_identity();
391
392                // See comment on doing this operation for `self_ty`
393                let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
394                debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
395
396                // We treat parameters in the self ty as rigid and parameters in the impl ty as infers
397                // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
398                // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
399                //
400                // We don't really care about a depth limit here because we're only working with user-written
401                // types and if they wrote a type that would take hours to walk then that's kind of on them. On
402                // the other hand the default depth limit is relatively low and could realistically be hit by
403                // users in normal cases.
404                //
405                // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
406                // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
407                // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
408                //
409                // Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
410                // resolution, but it probably won't come up in practice and it would be backwards compatible
411                // to switch over to doing that.
412                ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
413                    self_ty,
414                    impl_ty,
415                    usize::MAX,
416                )
417            })
418            .collect();
419
420        (candidates, vec![])
421    }
422
423    fn lower_assoc_item_path(
424        &self,
425        span: Span,
426        item_def_id: DefId,
427        item_segment: &rustc_hir::PathSegment<'tcx>,
428        poly_trait_ref: ty::PolyTraitRef<'tcx>,
429    ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
430        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
431            let item_args = self.lowerer().lower_generic_args_of_assoc_item(
432                span,
433                item_def_id,
434                item_segment,
435                trait_ref.args,
436            );
437            Ok((item_def_id, item_args))
438        } else {
439            // There are no late-bound regions; we can just ignore the binder.
440            let (mut mpart_sugg, mut inferred_sugg) = (None, None);
441            let mut bound = String::new();
442
443            match self.node() {
444                hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
445                    let item = self
446                        .tcx
447                        .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
448                    match &item.kind {
449                        hir::ItemKind::Enum(_, generics, _)
450                        | hir::ItemKind::Struct(_, generics, _)
451                        | hir::ItemKind::Union(_, generics, _) => {
452                            let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
453                            let (lt_sp, sugg) = match generics.params {
454                                [] => (generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", lt_name))
    })format!("<{lt_name}>")),
455                                [bound, ..] => (bound.span.shrink_to_lo(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", lt_name))
    })format!("{lt_name}, ")),
456                            };
457                            mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
458                                fspan: lt_sp,
459                                first: sugg,
460                                sspan: span.with_hi(item_segment.ident.span.lo()),
461                                second: ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::",
                self.tcx.instantiate_bound_regions_uncached(poly_trait_ref,
                    |_|
                        {
                            ty::Region::new_early_param(self.tcx,
                                ty::EarlyParamRegion {
                                    index: 0,
                                    name: Symbol::intern(&lt_name),
                                })
                        })))
    })format!(
462                                    "{}::",
463                                    // Replace the existing lifetimes with a new named lifetime.
464                                    self.tcx.instantiate_bound_regions_uncached(
465                                        poly_trait_ref,
466                                        |_| {
467                                            ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
468                                                index: 0,
469                                                name: Symbol::intern(&lt_name),
470                                            })
471                                        }
472                                    ),
473                                ),
474                            });
475                        }
476                        _ => {}
477                    }
478                }
479                hir::Node::Item(hir::Item {
480                    kind:
481                        hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
482                    ..
483                }) => {}
484                hir::Node::Item(_)
485                | hir::Node::ForeignItem(_)
486                | hir::Node::TraitItem(_)
487                | hir::Node::ImplItem(_) => {
488                    inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
489                    bound = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::",
                self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder()))
    })format!(
490                        "{}::",
491                        // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
492                        self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
493                    );
494                }
495                _ => {}
496            }
497
498            Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
499                span,
500                inferred_sugg,
501                bound,
502                mpart_sugg,
503                what: self.tcx.def_descr(item_def_id),
504            }))
505        }
506    }
507
508    fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
509        // FIXME(#103640): Should we handle the case where `ty` is a projection?
510        ty.ty_adt_def()
511    }
512
513    fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
514        // There's no place to record types from signatures?
515    }
516
517    fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
518        None
519    }
520
521    fn lower_fn_sig(
522        &self,
523        decl: &hir::FnDecl<'tcx>,
524        _generics: Option<&hir::Generics<'_>>,
525        hir_id: rustc_hir::HirId,
526        _hir_ty: Option<&hir::Ty<'_>>,
527    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
528        let tcx = self.tcx();
529
530        let mut infer_replacements = ::alloc::vec::Vec::new()vec![];
531
532        let input_tys = decl
533            .inputs
534            .iter()
535            .enumerate()
536            .map(|(i, a)| {
537                if let hir::TyKind::Infer(()) = a.kind
538                    && let Some(suggested_ty) =
539                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
540                {
541                    infer_replacements.push((a.span, suggested_ty.to_string()));
542                    return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
543                }
544
545                self.lowerer().lower_ty(a)
546            })
547            .collect();
548
549        let output_ty = match decl.output {
550            hir::FnRetTy::Return(output) => {
551                if let hir::TyKind::Infer(()) = output.kind
552                    && let Some(suggested_ty) =
553                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
554                {
555                    infer_replacements.push((output.span, suggested_ty.to_string()));
556                    Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
557                } else {
558                    self.lower_ty(output)
559                }
560            }
561            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
562        };
563
564        if !infer_replacements.is_empty() {
565            self.report_placeholder_type_error(::alloc::vec::Vec::new()vec![], infer_replacements);
566        }
567        (input_tys, output_ty)
568    }
569
570    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
571        hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
572    }
573}
574
575/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
576fn get_new_lifetime_name<'tcx>(
577    tcx: TyCtxt<'tcx>,
578    poly_trait_ref: ty::PolyTraitRef<'tcx>,
579    generics: &hir::Generics<'tcx>,
580) -> String {
581    let existing_lifetimes = tcx
582        .collect_referenced_late_bound_regions(poly_trait_ref)
583        .into_iter()
584        .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
585        .chain(generics.params.iter().filter_map(|param| {
586            if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
587                Some(param.name.ident().as_str().to_string())
588            } else {
589                None
590            }
591        }))
592        .collect::<FxHashSet<String>>();
593
594    let a_to_z_repeat_n = |n| {
595        (b'a'..=b'z').map(move |c| {
596            let mut s = '\''.to_string();
597            s.extend(std::iter::repeat_n(char::from(c), n));
598            s
599        })
600    };
601
602    // If all single char lifetime names are present, we wrap around and double the chars.
603    (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
604}
605
606pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
607    tcx.ensure_ok().generics_of(def_id);
608    tcx.ensure_ok().type_of(def_id);
609    tcx.ensure_ok().predicates_of(def_id);
610}
611
612pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: LocalDefId) {
613    let def = tcx.adt_def(def_id);
614    let repr_type = def.repr().discr_type();
615    let initial = repr_type.initial_discriminant(tcx);
616    let mut prev_discr = None::<Discr<'_>>;
617    // Some of the logic below relies on `i128` being able to hold all c_int and c_uint values.
618    if !(tcx.sess.target.c_int_width < 128) {
    ::core::panicking::panic("assertion failed: tcx.sess.target.c_int_width < 128")
};assert!(tcx.sess.target.c_int_width < 128);
619    let mut min_discr = i128::MAX;
620    let mut max_discr = i128::MIN;
621
622    // fill the discriminant values and field types
623    for variant in def.variants() {
624        let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
625        let cur_discr = if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
626            def.eval_explicit_discr(tcx, const_def_id).ok()
627        } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
628            Some(discr)
629        } else {
630            let span = tcx.def_span(variant.def_id);
631            tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
632                span,
633                discr: prev_discr.unwrap().to_string(),
634                item_name: tcx.item_ident(variant.def_id),
635                wrapped_discr: wrapped_discr.to_string(),
636            });
637            None
638        }
639        .unwrap_or(wrapped_discr);
640
641        if def.repr().c() {
642            let c_int = Size::from_bits(tcx.sess.target.c_int_width);
643            let c_uint_max = i128::try_from(c_int.unsigned_int_max()).unwrap();
644            // c_int is a signed type, so get a proper signed version of the discriminant
645            let discr_size = cur_discr.ty.int_size_and_signed(tcx).0;
646            let discr_val = discr_size.sign_extend(cur_discr.val);
647            min_discr = min_discr.min(discr_val);
648            max_discr = max_discr.max(discr_val);
649
650            // The discriminant range must either fit into c_int or c_uint.
651            if !(min_discr >= c_int.signed_int_min() && max_discr <= c_int.signed_int_max())
652                && !(min_discr >= 0 && max_discr <= c_uint_max)
653            {
654                let span = tcx.def_span(variant.def_id);
655                let msg = if discr_val < c_int.signed_int_min() || discr_val > c_uint_max {
656                    "`repr(C)` enum discriminant does not fit into C `int` nor into C `unsigned int`"
657                } else if discr_val < 0 {
658                    "`repr(C)` enum discriminant does not fit into C `unsigned int`, and a previous discriminant does not fit into C `int`"
659                } else {
660                    "`repr(C)` enum discriminant does not fit into C `int`, and a previous discriminant does not fit into C `unsigned int`"
661                };
662                tcx.node_span_lint(
663                    rustc_session::lint::builtin::REPR_C_ENUMS_LARGER_THAN_INT,
664                    tcx.local_def_id_to_hir_id(def_id),
665                    span,
666                    |d| {
667                        d.primary_message(msg)
668                        .note("`repr(C)` enums with big discriminants are non-portable, and their size in Rust might not match their size in C")
669                        .help("use `repr($int_ty)` instead to explicitly set the size of this enum");
670                    }
671                );
672            }
673        }
674
675        prev_discr = Some(cur_discr);
676
677        for f in &variant.fields {
678            tcx.ensure_ok().generics_of(f.did);
679            tcx.ensure_ok().type_of(f.did);
680            tcx.ensure_ok().predicates_of(f.did);
681        }
682
683        // Lower the ctor, if any. This also registers the variant as an item.
684        if let Some(ctor_def_id) = variant.ctor_def_id() {
685            lower_variant_ctor(tcx, ctor_def_id.expect_local());
686        }
687    }
688}
689
690#[derive(#[automatically_derived]
impl ::core::clone::Clone for NestedSpan {
    #[inline]
    fn clone(&self) -> NestedSpan {
        let _: ::core::clone::AssertParamIsClone<Span>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for NestedSpan { }Copy)]
691struct NestedSpan {
692    span: Span,
693    nested_field_span: Span,
694}
695
696impl NestedSpan {
697    fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
698        errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
699    }
700}
701
702#[derive(#[automatically_derived]
impl ::core::clone::Clone for FieldDeclSpan {
    #[inline]
    fn clone(&self) -> FieldDeclSpan {
        let _: ::core::clone::AssertParamIsClone<Span>;
        let _: ::core::clone::AssertParamIsClone<NestedSpan>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FieldDeclSpan { }Copy)]
703enum FieldDeclSpan {
704    NotNested(Span),
705    Nested(NestedSpan),
706}
707
708impl From<Span> for FieldDeclSpan {
709    fn from(span: Span) -> Self {
710        Self::NotNested(span)
711    }
712}
713
714impl From<NestedSpan> for FieldDeclSpan {
715    fn from(span: NestedSpan) -> Self {
716        Self::Nested(span)
717    }
718}
719
720struct FieldUniquenessCheckContext<'tcx> {
721    tcx: TyCtxt<'tcx>,
722    seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
723}
724
725impl<'tcx> FieldUniquenessCheckContext<'tcx> {
726    fn new(tcx: TyCtxt<'tcx>) -> Self {
727        Self { tcx, seen_fields: FxIndexMap::default() }
728    }
729
730    /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
731    fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
732        use FieldDeclSpan::*;
733        let field_name = field_name.normalize_to_macros_2_0();
734        match (field_decl, self.seen_fields.get(&field_name).copied()) {
735            (NotNested(span), Some(NotNested(prev_span))) => {
736                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
737                    field_name,
738                    span,
739                    prev_span,
740                });
741            }
742            (NotNested(span), Some(Nested(prev))) => {
743                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
744                    field_name,
745                    span,
746                    prev_span: prev.span,
747                    prev_nested_field_span: prev.nested_field_span,
748                    prev_help: prev.to_field_already_declared_nested_help(),
749                });
750            }
751            (
752                Nested(current @ NestedSpan { span, nested_field_span, .. }),
753                Some(NotNested(prev_span)),
754            ) => {
755                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
756                    field_name,
757                    span,
758                    nested_field_span,
759                    help: current.to_field_already_declared_nested_help(),
760                    prev_span,
761                });
762            }
763            (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
764                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
765                    field_name,
766                    span,
767                    nested_field_span,
768                    help: current.to_field_already_declared_nested_help(),
769                    prev_span: prev.span,
770                    prev_nested_field_span: prev.nested_field_span,
771                    prev_help: prev.to_field_already_declared_nested_help(),
772                });
773            }
774            (field_decl, None) => {
775                self.seen_fields.insert(field_name, field_decl);
776            }
777        }
778    }
779}
780
781fn lower_variant<'tcx>(
782    tcx: TyCtxt<'tcx>,
783    variant_did: Option<LocalDefId>,
784    ident: Ident,
785    discr: ty::VariantDiscr,
786    def: &hir::VariantData<'tcx>,
787    adt_kind: ty::AdtKind,
788    parent_did: LocalDefId,
789) -> ty::VariantDef {
790    let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
791    let fields = def
792        .fields()
793        .iter()
794        .inspect(|field| {
795            field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
796        })
797        .map(|f| ty::FieldDef {
798            did: f.def_id.to_def_id(),
799            name: f.ident.name,
800            vis: tcx.visibility(f.def_id),
801            safety: f.safety,
802            value: f.default.map(|v| v.def_id.to_def_id()),
803        })
804        .collect();
805    let recovered = match def {
806        hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
807        _ => None,
808    };
809    ty::VariantDef::new(
810        ident.name,
811        variant_did.map(LocalDefId::to_def_id),
812        def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
813        discr,
814        fields,
815        parent_did.to_def_id(),
816        recovered,
817        adt_kind == AdtKind::Struct && {

        #[allow(deprecated)]
        {
            {
                'done:
                    {
                    for i in tcx.get_all_attrs(parent_did) {
                        #[allow(unused_imports)]
                        use rustc_hir::attrs::AttributeKind::*;
                        let i: &rustc_hir::Attribute = i;
                        match i {
                            rustc_hir::Attribute::Parsed(NonExhaustive(..)) => {
                                break 'done Some(());
                            }
                            rustc_hir::Attribute::Unparsed(..) =>
                                {}
                                #[deny(unreachable_patterns)]
                                _ => {}
                        }
                    }
                    None
                }
            }
        }
    }.is_some()find_attr!(tcx, parent_did, NonExhaustive(..))
818            || variant_did
819                .is_some_and(|variant_did| {

        #[allow(deprecated)]
        {
            {
                'done:
                    {
                    for i in tcx.get_all_attrs(variant_did) {
                        #[allow(unused_imports)]
                        use rustc_hir::attrs::AttributeKind::*;
                        let i: &rustc_hir::Attribute = i;
                        match i {
                            rustc_hir::Attribute::Parsed(NonExhaustive(..)) => {
                                break 'done Some(());
                            }
                            rustc_hir::Attribute::Unparsed(..) =>
                                {}
                                #[deny(unreachable_patterns)]
                                _ => {}
                        }
                    }
                    None
                }
            }
        }
    }.is_some()find_attr!(tcx, variant_did, NonExhaustive(..))),
820    )
821}
822
823fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
824    use rustc_hir::*;
825
826    let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
827        ::rustc_middle::util::bug::bug_fmt(format_args!("expected ADT to be an item"));bug!("expected ADT to be an item");
828    };
829
830    let repr = tcx.repr_options_of_def(def_id);
831    let (kind, variants) = match &item.kind {
832        ItemKind::Enum(_, _, def) => {
833            let mut distance_from_explicit = 0;
834            let variants = def
835                .variants
836                .iter()
837                .map(|v| {
838                    let discr = if let Some(e) = &v.disr_expr {
839                        distance_from_explicit = 0;
840                        ty::VariantDiscr::Explicit(e.def_id.to_def_id())
841                    } else {
842                        ty::VariantDiscr::Relative(distance_from_explicit)
843                    };
844                    distance_from_explicit += 1;
845
846                    lower_variant(
847                        tcx,
848                        Some(v.def_id),
849                        v.ident,
850                        discr,
851                        &v.data,
852                        AdtKind::Enum,
853                        def_id,
854                    )
855                })
856                .collect();
857
858            (AdtKind::Enum, variants)
859        }
860        ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
861            let adt_kind = match item.kind {
862                ItemKind::Struct(..) => AdtKind::Struct,
863                _ => AdtKind::Union,
864            };
865            let variants = std::iter::once(lower_variant(
866                tcx,
867                None,
868                *ident,
869                ty::VariantDiscr::Relative(0),
870                def,
871                adt_kind,
872                def_id,
873            ))
874            .collect();
875
876            (adt_kind, variants)
877        }
878        _ => ::rustc_middle::util::bug::bug_fmt(format_args!("{0:?} is not an ADT",
        item.owner_id.def_id))bug!("{:?} is not an ADT", item.owner_id.def_id),
879    };
880    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
881}
882
883fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
884    let item = tcx.hir_expect_item(def_id);
885
886    let (constness, is_alias, is_auto, safety) = match item.kind {
887        hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
888            (constness, false, is_auto == hir::IsAuto::Yes, safety)
889        }
890        hir::ItemKind::TraitAlias(constness, ..) => (constness, true, false, hir::Safety::Safe),
891        _ => ::rustc_middle::util::bug::span_bug_fmt(item.span,
    format_args!("trait_def_of_item invoked on non-trait"))span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
892    };
893
894    // we do a bunch of find_attr calls here, probably faster to get them from the tcx just once.
895    #[allow(deprecated)]
896    let attrs = tcx.get_all_attrs(def_id);
897
898    let paren_sugar = {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcParenSugar(_)) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, RustcParenSugar(_));
899    if paren_sugar && !tcx.features().unboxed_closures() {
900        tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
901    }
902
903    // Only regular traits can be marker.
904    let is_marker = !is_alias && {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(Marker(_)) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, Marker(_));
905
906    let rustc_coinductive = {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcCoinductive(_)) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, RustcCoinductive(_));
907    let is_fundamental = {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(Fundamental) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, Fundamental);
908
909    let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = {
    'done:
        {
        for i in attrs {
            #[allow(unused_imports)]
            use rustc_hir::attrs::AttributeKind::*;
            let i: &rustc_hir::Attribute = i;
            match i {
                rustc_hir::Attribute::Parsed(RustcSkipDuringMethodDispatch {
                    array, boxed_slice, span: _ }) => {
                    break 'done Some([*array, *boxed_slice]);
                }
                rustc_hir::Attribute::Unparsed(..) =>
                    {}
                    #[deny(unreachable_patterns)]
                    _ => {}
            }
        }
        None
    }
}find_attr!(
910        attrs,
911        RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
912    )
913    .unwrap_or([false; 2]);
914
915    let specialization_kind = if {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcUnsafeSpecializationMarker(_))
                            => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, RustcUnsafeSpecializationMarker(_)) {
916        ty::trait_def::TraitSpecializationKind::Marker
917    } else if {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcSpecializationTrait(_)) =>
                            {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, RustcSpecializationTrait(_)) {
918        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
919    } else {
920        ty::trait_def::TraitSpecializationKind::None
921    };
922
923    let must_implement_one_of = {
    'done:
        {
        for i in attrs {
            #[allow(unused_imports)]
            use rustc_hir::attrs::AttributeKind::*;
            let i: &rustc_hir::Attribute = i;
            match i {
                rustc_hir::Attribute::Parsed(RustcMustImplementOneOf {
                    fn_names, .. }) => {
                    break 'done
                        Some(fn_names.iter().cloned().collect::<Box<[_]>>());
                }
                rustc_hir::Attribute::Unparsed(..) =>
                    {}
                    #[deny(unreachable_patterns)]
                    _ => {}
            }
        }
        None
    }
}find_attr!(
924        attrs,
925        RustcMustImplementOneOf { fn_names, .. } =>
926            fn_names
927                .iter()
928                .cloned()
929                .collect::<Box<[_]>>()
930    );
931
932    let deny_explicit_impl = {
    {
            'done:
                {
                for i in attrs {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcDenyExplicitImpl(_)) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }.is_some()
}find_attr!(attrs, RustcDenyExplicitImpl(_));
933    let force_dyn_incompatible = {
    'done:
        {
        for i in attrs {
            #[allow(unused_imports)]
            use rustc_hir::attrs::AttributeKind::*;
            let i: &rustc_hir::Attribute = i;
            match i {
                rustc_hir::Attribute::Parsed(RustcDynIncompatibleTrait(span))
                    => {
                    break 'done Some(*span);
                }
                rustc_hir::Attribute::Unparsed(..) =>
                    {}
                    #[deny(unreachable_patterns)]
                    _ => {}
            }
        }
        None
    }
}find_attr!(attrs, RustcDynIncompatibleTrait(span) => *span);
934
935    ty::TraitDef {
936        def_id: def_id.to_def_id(),
937        safety,
938        constness,
939        paren_sugar,
940        has_auto_impl: is_auto,
941        is_marker,
942        is_coinductive: rustc_coinductive || is_auto,
943        is_fundamental,
944        skip_array_during_method_dispatch,
945        skip_boxed_slice_during_method_dispatch,
946        specialization_kind,
947        must_implement_one_of,
948        force_dyn_incompatible,
949        deny_explicit_impl,
950    }
951}
952
953x;#[instrument(level = "debug", skip(tcx), ret)]
954fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
955    use rustc_hir::Node::*;
956    use rustc_hir::*;
957
958    let hir_id = tcx.local_def_id_to_hir_id(def_id);
959
960    let icx = ItemCtxt::new(tcx, def_id);
961
962    let output = match tcx.hir_node(hir_id) {
963        TraitItem(hir::TraitItem {
964            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
965            generics,
966            ..
967        })
968        | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
969            lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
970        }
971
972        ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
973            // Do not try to infer the return type for a impl method coming from a trait
974            if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
975                && i.of_trait.is_some()
976            {
977                icx.lowerer().lower_fn_ty(
978                    hir_id,
979                    sig.header.safety(),
980                    sig.header.abi,
981                    sig.decl,
982                    Some(generics),
983                    None,
984                )
985            } else {
986                lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
987            }
988        }
989
990        TraitItem(hir::TraitItem {
991            kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
992            generics,
993            ..
994        }) => icx.lowerer().lower_fn_ty(
995            hir_id,
996            header.safety(),
997            header.abi,
998            decl,
999            Some(generics),
1000            None,
1001        ),
1002
1003        ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1004            let abi = tcx.hir_get_foreign_abi(hir_id);
1005            compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1006        }
1007
1008        Ctor(data) => {
1009            assert_matches!(data.ctor(), Some(_));
1010            let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1011            let ty = tcx.type_of(adt_def_id).instantiate_identity();
1012            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1013            // constructors for structs with `layout_scalar_valid_range` are unsafe to call
1014            let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1015                (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1016                _ => hir::Safety::Unsafe,
1017            };
1018            ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1019        }
1020
1021        Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1022            // Closure signatures are not like other function
1023            // signatures and cannot be accessed through `fn_sig`. For
1024            // example, a closure signature excludes the `self`
1025            // argument. In any case they are embedded within the
1026            // closure type as part of the `ClosureArgs`.
1027            //
1028            // To get the signature of a closure, you should use the
1029            // `sig` method on the `ClosureArgs`:
1030            //
1031            //    args.as_closure().sig(def_id, tcx)
1032            bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1033        }
1034
1035        x => {
1036            bug!("unexpected sort of node in fn_sig(): {:?}", x);
1037        }
1038    };
1039    ty::EarlyBinder::bind(output)
1040}
1041
1042fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1043    icx: &ItemCtxt<'tcx>,
1044    sig: &'tcx hir::FnSig<'tcx>,
1045    generics: &'tcx hir::Generics<'tcx>,
1046    def_id: LocalDefId,
1047) -> ty::PolyFnSig<'tcx> {
1048    if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1049        return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1050    }
1051
1052    icx.lowerer().lower_fn_ty(
1053        icx.tcx().local_def_id_to_hir_id(def_id),
1054        sig.header.safety(),
1055        sig.header.abi,
1056        sig.decl,
1057        Some(generics),
1058        None,
1059    )
1060}
1061
1062/// Convert `ReLateParam`s in `value` back into `ReBound`s and bind it with `bound_vars`.
1063fn late_param_regions_to_bound<'tcx, T>(
1064    tcx: TyCtxt<'tcx>,
1065    scope: DefId,
1066    bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
1067    value: T,
1068) -> ty::Binder<'tcx, T>
1069where
1070    T: ty::TypeFoldable<TyCtxt<'tcx>>,
1071{
1072    let value = fold_regions(tcx, value, |r, debruijn| match r.kind() {
1073        ty::ReLateParam(lp) => {
1074            // Should be in scope, otherwise inconsistency happens somewhere.
1075            match (&lp.scope, &scope) {
    (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::None);
        }
    }
};assert_eq!(lp.scope, scope);
1076
1077            let br = match lp.kind {
1078                // These variants preserve the bound var index.
1079                kind @ (ty::LateParamRegionKind::Anon(idx)
1080                | ty::LateParamRegionKind::NamedAnon(idx, _)) => {
1081                    let idx = idx as usize;
1082                    let var = ty::BoundVar::from_usize(idx);
1083
1084                    let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied()
1085                    else {
1086                        ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected late-bound region {0:?} for bound vars {1:?}",
        kind, bound_vars));bug!("unexpected late-bound region {kind:?} for bound vars {bound_vars:?}");
1087                    };
1088
1089                    ty::BoundRegion { var, kind }
1090                }
1091
1092                // For named regions, look up the corresponding bound var.
1093                ty::LateParamRegionKind::Named(def_id) => bound_vars
1094                    .iter()
1095                    .enumerate()
1096                    .find_map(|(idx, bv)| match bv {
1097                        ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did))
1098                            if did == def_id =>
1099                        {
1100                            Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1101                        }
1102                        _ => None,
1103                    })
1104                    .unwrap(),
1105
1106                ty::LateParamRegionKind::ClosureEnv => bound_vars
1107                    .iter()
1108                    .enumerate()
1109                    .find_map(|(idx, bv)| match bv {
1110                        ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => {
1111                            Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1112                        }
1113                        _ => None,
1114                    })
1115                    .unwrap(),
1116            };
1117
1118            ty::Region::new_bound(tcx, debruijn, br)
1119        }
1120        _ => r,
1121    });
1122
1123    ty::Binder::bind_with_vars(value, bound_vars)
1124}
1125
1126fn recover_infer_ret_ty<'tcx>(
1127    icx: &ItemCtxt<'tcx>,
1128    infer_ret_ty: &'tcx hir::Ty<'tcx>,
1129    generics: &'tcx hir::Generics<'tcx>,
1130    def_id: LocalDefId,
1131) -> ty::PolyFnSig<'tcx> {
1132    let tcx = icx.tcx;
1133    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1134
1135    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1136
1137    // Typeck doesn't expect erased regions to be returned from `type_of`.
1138    // This is a heuristic approach. If the scope has region parameters,
1139    // we should change fn_sig's lifetime from `ReErased` to `ReError`,
1140    // otherwise to `ReStatic`.
1141    let has_region_params = generics.params.iter().any(|param| match param.kind {
1142        GenericParamKind::Lifetime { .. } => true,
1143        _ => false,
1144    });
1145    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1146        ty::ReErased => {
1147            if has_region_params {
1148                ty::Region::new_error_with_message(
1149                    tcx,
1150                    DUMMY_SP,
1151                    "erased region is not allowed here in return type",
1152                )
1153            } else {
1154                tcx.lifetimes.re_static
1155            }
1156        }
1157        _ => r,
1158    });
1159
1160    let mut visitor = HirPlaceholderCollector::default();
1161    visitor.visit_ty_unambig(infer_ret_ty);
1162
1163    let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1164    let ret_ty = fn_sig.output();
1165
1166    // Don't leak types into signatures unless they're nameable!
1167    // For example, if a function returns itself, we don't want that
1168    // recursive function definition to leak out into the fn sig.
1169    let mut recovered_ret_ty = None;
1170    if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1171        diag.span_suggestion_verbose(
1172            infer_ret_ty.span,
1173            "replace with the correct return type",
1174            suggestable_ret_ty,
1175            Applicability::MachineApplicable,
1176        );
1177        recovered_ret_ty = Some(suggestable_ret_ty);
1178    } else if let Some(sugg) = suggest_impl_trait(
1179        &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1180        tcx.param_env(def_id),
1181        ret_ty,
1182    ) {
1183        diag.span_suggestion_verbose(
1184            infer_ret_ty.span,
1185            "replace with an appropriate return type",
1186            sugg,
1187            Applicability::MachineApplicable,
1188        );
1189    } else if ret_ty.is_closure() {
1190        diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1191    }
1192
1193    // Also note how `Fn` traits work just in case!
1194    if ret_ty.is_closure() {
1195        diag.note(
1196            "for more information on `Fn` traits and closure types, see \
1197                     https://doc.rust-lang.org/book/ch13-01-closures.html",
1198        );
1199    }
1200    let guar = diag.emit();
1201
1202    // If we return a dummy binder here, we can ICE later in borrowck when it encounters
1203    // `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the
1204    // signature binder. See #135845.
1205    let bound_vars = tcx.late_bound_vars(hir_id);
1206    let scope = def_id.to_def_id();
1207
1208    let fn_sig = tcx.mk_fn_sig(
1209        fn_sig.inputs().iter().copied(),
1210        recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1211        fn_sig.c_variadic,
1212        fn_sig.safety,
1213        fn_sig.abi,
1214    );
1215
1216    late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
1217}
1218
1219pub fn suggest_impl_trait<'tcx>(
1220    infcx: &InferCtxt<'tcx>,
1221    param_env: ty::ParamEnv<'tcx>,
1222    ret_ty: Ty<'tcx>,
1223) -> Option<String> {
1224    let format_as_assoc: fn(_, _, _, _, _) -> _ =
1225        |tcx: TyCtxt<'tcx>,
1226         _: ty::GenericArgsRef<'tcx>,
1227         trait_def_id: DefId,
1228         assoc_item_def_id: DefId,
1229         item_ty: Ty<'tcx>| {
1230            let trait_name = tcx.item_name(trait_def_id);
1231            let assoc_name = tcx.item_name(assoc_item_def_id);
1232            Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("impl {0}<{1} = {2}>", trait_name,
                assoc_name, item_ty))
    })format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1233        };
1234    let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1235        |tcx: TyCtxt<'tcx>,
1236         args: ty::GenericArgsRef<'tcx>,
1237         trait_def_id: DefId,
1238         _: DefId,
1239         item_ty: Ty<'tcx>| {
1240            let trait_name = tcx.item_name(trait_def_id);
1241            let args_tuple = args.type_at(1);
1242            let ty::Tuple(types) = *args_tuple.kind() else {
1243                return None;
1244            };
1245            let types = types.make_suggestable(tcx, false, None)?;
1246            let maybe_ret =
1247                if item_ty.is_unit() { String::new() } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" -> {0}", item_ty))
    })format!(" -> {item_ty}") };
1248            Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("impl {1}({0}){2}",
                types.iter().map(|ty|
                                ty.to_string()).collect::<Vec<_>>().join(", "), trait_name,
                maybe_ret))
    })format!(
1249                "impl {trait_name}({}){maybe_ret}",
1250                types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1251            ))
1252        };
1253
1254    for (trait_def_id, assoc_item_def_id, formatter) in [
1255        (
1256            infcx.tcx.get_diagnostic_item(sym::Iterator),
1257            infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1258            format_as_assoc,
1259        ),
1260        (
1261            infcx.tcx.lang_items().future_trait(),
1262            infcx.tcx.lang_items().future_output(),
1263            format_as_assoc,
1264        ),
1265        (
1266            infcx.tcx.lang_items().async_fn_trait(),
1267            infcx.tcx.lang_items().async_fn_once_output(),
1268            format_as_parenthesized,
1269        ),
1270        (
1271            infcx.tcx.lang_items().async_fn_mut_trait(),
1272            infcx.tcx.lang_items().async_fn_once_output(),
1273            format_as_parenthesized,
1274        ),
1275        (
1276            infcx.tcx.lang_items().async_fn_once_trait(),
1277            infcx.tcx.lang_items().async_fn_once_output(),
1278            format_as_parenthesized,
1279        ),
1280        (
1281            infcx.tcx.lang_items().fn_trait(),
1282            infcx.tcx.lang_items().fn_once_output(),
1283            format_as_parenthesized,
1284        ),
1285        (
1286            infcx.tcx.lang_items().fn_mut_trait(),
1287            infcx.tcx.lang_items().fn_once_output(),
1288            format_as_parenthesized,
1289        ),
1290        (
1291            infcx.tcx.lang_items().fn_once_trait(),
1292            infcx.tcx.lang_items().fn_once_output(),
1293            format_as_parenthesized,
1294        ),
1295    ] {
1296        let Some(trait_def_id) = trait_def_id else {
1297            continue;
1298        };
1299        let Some(assoc_item_def_id) = assoc_item_def_id else {
1300            continue;
1301        };
1302        if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1303            continue;
1304        }
1305        let sugg = infcx.probe(|_| {
1306            let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1307                if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1308            });
1309            if !infcx
1310                .type_implements_trait(trait_def_id, args, param_env)
1311                .must_apply_modulo_regions()
1312            {
1313                return None;
1314            }
1315            let ocx = ObligationCtxt::new(&infcx);
1316            let item_ty = ocx.normalize(
1317                &ObligationCause::dummy(),
1318                param_env,
1319                Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1320            );
1321            // FIXME(compiler-errors): We may benefit from resolving regions here.
1322            if ocx.try_evaluate_obligations().is_empty()
1323                && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1324                && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1325                && let Some(sugg) = formatter(
1326                    infcx.tcx,
1327                    infcx.resolve_vars_if_possible(args),
1328                    trait_def_id,
1329                    assoc_item_def_id,
1330                    item_ty,
1331                )
1332            {
1333                return Some(sugg);
1334            }
1335
1336            None
1337        });
1338
1339        if sugg.is_some() {
1340            return sugg;
1341        }
1342    }
1343    None
1344}
1345
1346fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
1347    let icx = ItemCtxt::new(tcx, def_id);
1348    let item = tcx.hir_expect_item(def_id);
1349    let impl_ = item.expect_impl();
1350    let of_trait = impl_
1351        .of_trait
1352        .unwrap_or_else(|| {
    ::core::panicking::panic_fmt(format_args!("expected impl trait, found inherent impl on {0:?}",
            def_id));
}panic!("expected impl trait, found inherent impl on {def_id:?}"));
1353    let selfty = tcx.type_of(def_id).instantiate_identity();
1354    let is_rustc_reservation = {

        #[allow(deprecated)]
        {
            {
                'done:
                    {
                    for i in tcx.get_all_attrs(def_id) {
                        #[allow(unused_imports)]
                        use rustc_hir::attrs::AttributeKind::*;
                        let i: &rustc_hir::Attribute = i;
                        match i {
                            rustc_hir::Attribute::Parsed(RustcReservationImpl(..)) => {
                                break 'done Some(());
                            }
                            rustc_hir::Attribute::Unparsed(..) =>
                                {}
                                #[deny(unreachable_patterns)]
                                _ => {}
                        }
                    }
                    None
                }
            }
        }
    }.is_some()find_attr!(tcx, def_id, RustcReservationImpl(..));
1355
1356    check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref);
1357
1358    let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
1359
1360    ty::ImplTraitHeader {
1361        trait_ref: ty::EarlyBinder::bind(trait_ref),
1362        safety: of_trait.safety,
1363        polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
1364        constness: impl_.constness,
1365    }
1366}
1367
1368fn check_impl_constness(
1369    tcx: TyCtxt<'_>,
1370    constness: hir::Constness,
1371    hir_trait_ref: &hir::TraitRef<'_>,
1372) {
1373    if let hir::Constness::NotConst = constness {
1374        return;
1375    }
1376
1377    let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1378    if tcx.is_const_trait(trait_def_id) {
1379        return;
1380    }
1381
1382    let trait_name = tcx.item_name(trait_def_id).to_string();
1383    let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build())
1384    {
1385        (Some(trait_def_id), true) => {
1386            let span = tcx.hir_expect_item(trait_def_id).vis_span;
1387            let span = tcx.sess.source_map().span_extend_while_whitespace(span);
1388
1389            (
1390                Some(span.shrink_to_hi()),
1391                if tcx.features().const_trait_impl() {
1392                    ""
1393                } else {
1394                    "enable `#![feature(const_trait_impl)]` in your crate and "
1395                },
1396            )
1397        }
1398        (None, _) | (_, false) => (None, ""),
1399    };
1400    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1401        trait_ref_span: hir_trait_ref.path.span,
1402        trait_name,
1403        suggestion,
1404        suggestion_pre,
1405        marking: (),
1406        adding: (),
1407    });
1408}
1409
1410fn polarity_of_impl(
1411    tcx: TyCtxt<'_>,
1412    of_trait: &hir::TraitImplHeader<'_>,
1413    is_rustc_reservation: bool,
1414) -> ty::ImplPolarity {
1415    match of_trait.polarity {
1416        hir::ImplPolarity::Negative(span) => {
1417            if is_rustc_reservation {
1418                let span = span.to(of_trait.trait_ref.path.span);
1419                tcx.dcx().span_err(span, "reservation impls can't be negative");
1420            }
1421            ty::ImplPolarity::Negative
1422        }
1423        hir::ImplPolarity::Positive => {
1424            if is_rustc_reservation {
1425                ty::ImplPolarity::Reservation
1426            } else {
1427                ty::ImplPolarity::Positive
1428            }
1429        }
1430    }
1431}
1432
1433/// Returns the early-bound lifetimes declared in this generics
1434/// listing. For anything other than fns/methods, this is just all
1435/// the lifetimes that are declared. For fns or methods, we have to
1436/// screen out those that do not appear in any where-clauses etc using
1437/// `resolve_lifetime::early_bound_lifetimes`.
1438fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1439    tcx: TyCtxt<'tcx>,
1440    generics: &'a hir::Generics<'a>,
1441) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1442    generics.params.iter().filter(move |param| match param.kind {
1443        GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1444        _ => false,
1445    })
1446}
1447
1448fn compute_sig_of_foreign_fn_decl<'tcx>(
1449    tcx: TyCtxt<'tcx>,
1450    def_id: LocalDefId,
1451    decl: &'tcx hir::FnDecl<'tcx>,
1452    abi: ExternAbi,
1453    safety: hir::Safety,
1454) -> ty::PolyFnSig<'tcx> {
1455    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1456    let fty =
1457        ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1458
1459    // Feature gate SIMD types in FFI, since I am not sure that the
1460    // ABIs are handled at all correctly. -huonw
1461    if !tcx.features().simd_ffi() {
1462        let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1463            if ty.is_simd() {
1464                let snip = tcx
1465                    .sess
1466                    .source_map()
1467                    .span_to_snippet(hir_ty.span)
1468                    .map_or_else(|_| String::new(), |s| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", s))
    })format!(" `{s}`"));
1469                tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1470            }
1471        };
1472        for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1473            check(input, *ty)
1474        }
1475        if let hir::FnRetTy::Return(ty) = decl.output {
1476            check(ty, fty.output().skip_binder())
1477        }
1478    }
1479
1480    fty
1481}
1482
1483fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1484    match tcx.hir_node_by_def_id(def_id) {
1485        Node::Expr(&hir::Expr {
1486            kind:
1487                hir::ExprKind::Closure(&rustc_hir::Closure {
1488                    kind: hir::ClosureKind::Coroutine(kind),
1489                    ..
1490                }),
1491            ..
1492        }) => Some(kind),
1493        _ => None,
1494    }
1495}
1496
1497fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1498    let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1499        tcx.hir_node_by_def_id(def_id).expect_closure()
1500    else {
1501        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1502    };
1503
1504    let &hir::Expr {
1505        kind:
1506            hir::ExprKind::Closure(&rustc_hir::Closure {
1507                def_id,
1508                kind: hir::ClosureKind::Coroutine(_),
1509                ..
1510            }),
1511        ..
1512    } = tcx.hir_body(body).value
1513    else {
1514        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1515    };
1516
1517    def_id.to_def_id()
1518}
1519
1520fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1521    match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1522        hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1523            hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1524        }
1525        hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1526            hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1527        }
1528        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1529            hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1530        }
1531    }
1532}
1533
1534fn rendered_precise_capturing_args<'tcx>(
1535    tcx: TyCtxt<'tcx>,
1536    def_id: LocalDefId,
1537) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1538    if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1539        tcx.opt_rpitit_info(def_id.to_def_id())
1540    {
1541        return tcx.rendered_precise_capturing_args(opaque_def_id);
1542    }
1543
1544    tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1545        hir::GenericBound::Use(args, ..) => {
1546            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1547                PreciseCapturingArgKind::Lifetime(_) => {
1548                    PreciseCapturingArgKind::Lifetime(arg.name())
1549                }
1550                PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1551            })))
1552        }
1553        _ => None,
1554    })
1555}
1556
1557fn const_param_default<'tcx>(
1558    tcx: TyCtxt<'tcx>,
1559    local_def_id: LocalDefId,
1560) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1561    let hir::Node::GenericParam(hir::GenericParam {
1562        kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
1563        ..
1564    }) = tcx.hir_node_by_def_id(local_def_id)
1565    else {
1566        ::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(local_def_id),
    format_args!("`const_param_default` expected a generic parameter with a constant"))span_bug!(
1567            tcx.def_span(local_def_id),
1568            "`const_param_default` expected a generic parameter with a constant"
1569        )
1570    };
1571
1572    let icx = ItemCtxt::new(tcx, local_def_id);
1573
1574    let def_id = local_def_id.to_def_id();
1575    let identity_args = ty::GenericArgs::identity_for_item(tcx, tcx.parent(def_id));
1576
1577    let ct = icx
1578        .lowerer()
1579        .lower_const_arg(default_ct, tcx.type_of(def_id).instantiate(tcx, identity_args));
1580    ty::EarlyBinder::bind(ct)
1581}
1582
1583fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1584    let hir_id = tcx.local_def_id_to_hir_id(def);
1585    let const_arg_id = tcx.parent_hir_id(hir_id);
1586    match tcx.hir_node(const_arg_id) {
1587        hir::Node::ConstArg(_) => {
1588            let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id));
1589            if tcx.features().generic_const_exprs() {
1590                ty::AnonConstKind::GCE
1591            } else if tcx.features().opaque_generic_const_args() {
1592                // Only anon consts that are the RHS of a const item can be OGCA.
1593                // Note: We can't just check tcx.parent because it needs to be EXACTLY
1594                // the RHS, not just part of the RHS.
1595                if !is_anon_const_rhs_of_const_item(tcx, def) {
1596                    return ty::AnonConstKind::MCG;
1597                }
1598
1599                let body = tcx.hir_body_owned_by(def);
1600                let mut visitor = OGCAParamVisitor(tcx);
1601                match visitor.visit_body(body) {
1602                    ControlFlow::Break(UsesParam) => ty::AnonConstKind::OGCA,
1603                    ControlFlow::Continue(()) => ty::AnonConstKind::MCG,
1604                }
1605            } else if tcx.features().min_generic_const_args() {
1606                ty::AnonConstKind::MCG
1607            } else if let hir::Node::Expr(hir::Expr {
1608                kind: hir::ExprKind::Repeat(_, repeat_count),
1609                ..
1610            }) = parent_hir_node
1611                && repeat_count.hir_id == const_arg_id
1612            {
1613                ty::AnonConstKind::RepeatExprCount
1614            } else {
1615                ty::AnonConstKind::MCG
1616            }
1617        }
1618        _ => ty::AnonConstKind::NonTypeSystem,
1619    }
1620}
1621
1622fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
1623    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1624    let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false };
1625    let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. })
1626    | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. })
1627    | Node::TraitItem(hir::TraitItem {
1628        kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _),
1629        ..
1630    })) = grandparent_node
1631    else {
1632        return false;
1633    };
1634    let hir::ConstItemRhs::TypeConst(hir::ConstArg {
1635        kind: hir::ConstArgKind::Anon(rhs_anon), ..
1636    }) = ct_rhs
1637    else {
1638        return false;
1639    };
1640    def_id == rhs_anon.def_id
1641}
1642
1643struct OGCAParamVisitor<'tcx>(TyCtxt<'tcx>);
1644
1645struct UsesParam;
1646
1647impl<'tcx> Visitor<'tcx> for OGCAParamVisitor<'tcx> {
1648    type NestedFilter = nested_filter::OnlyBodies;
1649    type Result = ControlFlow<UsesParam>;
1650
1651    fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
1652        self.0
1653    }
1654
1655    fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow<UsesParam> {
1656        if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) =
1657            path.res
1658        {
1659            return ControlFlow::Break(UsesParam);
1660        }
1661
1662        intravisit::walk_path(self, path)
1663    }
1664}
1665
1666x;#[instrument(level = "debug", skip(tcx), ret)]
1667fn const_of_item<'tcx>(
1668    tcx: TyCtxt<'tcx>,
1669    def_id: LocalDefId,
1670) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1671    let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
1672        hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
1673        hir::Node::TraitItem(hir::TraitItem {
1674            kind: hir::TraitItemKind::Const(_, ct, _), ..
1675        }) => ct.expect("no default value for trait assoc const"),
1676        hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
1677        _ => {
1678            span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1679        }
1680    };
1681    let ct_arg = match ct_rhs {
1682        hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1683        hir::ConstItemRhs::Body(_) => {
1684            let e = tcx.dcx().span_delayed_bug(
1685                tcx.def_span(def_id),
1686                "cannot call const_of_item on a non-type_const",
1687            );
1688            return ty::EarlyBinder::bind(Const::new_error(tcx, e));
1689        }
1690    };
1691    let icx = ItemCtxt::new(tcx, def_id);
1692    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1693    let ct = icx
1694        .lowerer()
1695        .lower_const_arg(ct_arg, tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args));
1696    if let Err(e) = icx.check_tainted_by_errors()
1697        && !ct.references_error()
1698    {
1699        ty::EarlyBinder::bind(Const::new_error(tcx, e))
1700    } else {
1701        ty::EarlyBinder::bind(ct)
1702    }
1703}