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::ops::{Bound, ControlFlow};
19use std::{assert_matches, iter};
20
21use rustc_abi::{ExternAbi, Size};
22use rustc_ast::Recovered;
23use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
24use rustc_errors::{
25    Applicability, Diag, DiagCtxtHandle, Diagnostic, E0228, ErrorGuaranteed, Level, StashKey,
26};
27use rustc_hir::def::{DefKind, Res};
28use rustc_hir::def_id::{DefId, LocalDefId};
29use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
30use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr};
31use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
32use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
33use rustc_middle::hir::nested_filter;
34use rustc_middle::query::Providers;
35use rustc_middle::ty::util::{Discr, IntTypeExt};
36use rustc_middle::ty::{
37    self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized,
38    fold_regions,
39};
40use rustc_middle::{bug, span_bug};
41use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
42use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
43use rustc_trait_selection::infer::InferCtxtExt;
44use rustc_trait_selection::traits::{
45    FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
46};
47use tracing::{debug, instrument};
48
49use crate::errors;
50use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason};
51
52pub(crate) mod dump;
53mod generics_of;
54mod item_bounds;
55mod predicates_of;
56mod resolve_bound_vars;
57mod type_of;
58
59///////////////////////////////////////////////////////////////////////////
60
61/// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]
62pub(crate) fn provide(providers: &mut Providers) {
63    resolve_bound_vars::provide(providers);
64    *providers = Providers {
65        type_of: type_of::type_of,
66        type_of_opaque: type_of::type_of_opaque,
67        type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
68        type_alias_is_lazy: type_of::type_alias_is_lazy,
69        item_bounds: item_bounds::item_bounds,
70        explicit_item_bounds: item_bounds::explicit_item_bounds,
71        item_self_bounds: item_bounds::item_self_bounds,
72        explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
73        item_non_self_bounds: item_bounds::item_non_self_bounds,
74        impl_super_outlives: item_bounds::impl_super_outlives,
75        generics_of: generics_of::generics_of,
76        predicates_of: predicates_of::predicates_of,
77        explicit_predicates_of: predicates_of::explicit_predicates_of,
78        explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
79        explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
80        explicit_supertraits_containing_assoc_item:
81            predicates_of::explicit_supertraits_containing_assoc_item,
82        trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
83        const_conditions: predicates_of::const_conditions,
84        explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
85        type_param_predicates: predicates_of::type_param_predicates,
86        trait_def,
87        adt_def,
88        fn_sig,
89        impl_trait_header,
90        coroutine_kind,
91        coroutine_for_closure,
92        opaque_ty_origin,
93        rendered_precise_capturing_args,
94        const_param_default,
95        anon_const_kind,
96        const_of_item,
97        ..*providers
98    };
99}
100
101///////////////////////////////////////////////////////////////////////////
102
103/// Context specific to some particular item. This is what implements [`HirTyLowerer`].
104///
105/// # `ItemCtxt` vs `FnCtxt`
106///
107/// `ItemCtxt` is primarily used to type-check item signatures and lower them
108/// from HIR to their [`ty::Ty`] representation, which is exposed using [`HirTyLowerer`].
109/// It's also used for the bodies of items like structs where the body (the fields)
110/// are just signatures.
111///
112/// This is in contrast to `FnCtxt`, which is used to type-check bodies of
113/// functions, closures, and `const`s -- anywhere that expressions and statements show up.
114///
115/// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
116/// while `FnCtxt` does do inference.
117///
118/// [`InferCtxt`]: rustc_infer::infer::InferCtxt
119///
120/// # Trait predicates
121///
122/// `ItemCtxt` has information about the predicates that are defined
123/// on the trait. Unfortunately, this predicate information is
124/// available in various different forms at various points in the
125/// process. So we can't just store a pointer to e.g., the HIR or the
126/// parsed ty form, we have to be more flexible. To this end, the
127/// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
128/// `probe_ty_param_bounds` requests, drawing the information from
129/// the HIR (`hir::Generics`), recursively.
130pub(crate) struct ItemCtxt<'tcx> {
131    tcx: TyCtxt<'tcx>,
132    item_def_id: LocalDefId,
133    tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
134}
135
136///////////////////////////////////////////////////////////////////////////
137
138#[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)]
139pub(crate) struct HirPlaceholderCollector {
140    pub spans: Vec<Span>,
141    // If any of the spans points to a const infer var, then suppress any messages
142    // that may try to turn that const infer into a type parameter.
143    pub may_contain_const_infer: bool,
144}
145
146impl<'v> Visitor<'v> for HirPlaceholderCollector {
147    fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
148        self.spans.push(inf_span);
149
150        if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
151            self.may_contain_const_infer = true;
152        }
153    }
154}
155
156fn placeholder_type_error_diag<'cx, 'tcx>(
157    cx: &'cx dyn HirTyLowerer<'tcx>,
158    generics: Option<&hir::Generics<'_>>,
159    placeholder_types: Vec<Span>,
160    additional_spans: Vec<Span>,
161    suggest: bool,
162    hir_ty: Option<&hir::Ty<'_>>,
163    kind: &'static str,
164) -> Diag<'cx> {
165    if placeholder_types.is_empty() {
166        return bad_placeholder(cx, additional_spans, kind);
167    }
168
169    let params = generics.map(|g| g.params).unwrap_or_default();
170    let type_name = params.next_type_param_name(None);
171    let mut sugg: Vec<_> =
172        placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
173
174    if let Some(generics) = generics {
175        if let Some(span) = params.iter().find_map(|arg| match arg.name {
176            hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
177            _ => None,
178        }) {
179            // Account for `_` already present in cases like `struct S<_>(_);` and suggest
180            // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
181            sugg.push((span, (*type_name).to_string()));
182        } else if let Some(span) = generics.span_for_param_suggestion() {
183            // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
184            sugg.push((span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(", {0}", type_name))
    })format!(", {type_name}")));
185        } else {
186            sugg.push((generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", type_name))
    })format!("<{type_name}>")));
187        }
188    }
189
190    let mut err =
191        bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
192
193    // Suggest, but only if it is not a function in const or static
194    if suggest {
195        let mut is_fn = false;
196        let mut is_const_or_static = false;
197
198        if let Some(hir_ty) = hir_ty
199            && let hir::TyKind::FnPtr(_) = hir_ty.kind
200        {
201            is_fn = true;
202
203            // Check if parent is const or static
204            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!(
205                cx.tcx().parent_hir_node(hir_ty.hir_id),
206                Node::Item(&hir::Item {
207                    kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
208                    ..
209                }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
210                    | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
211            );
212        }
213
214        // if function is wrapped around a const or static,
215        // then don't show the suggestion
216        if !(is_fn && is_const_or_static) {
217            err.multipart_suggestion(
218                "use type parameters instead",
219                sugg,
220                Applicability::HasPlaceholders,
221            );
222        }
223    }
224
225    err
226}
227
228///////////////////////////////////////////////////////////////////////////
229// Utility types and common code for the above passes.
230
231fn bad_placeholder<'cx, 'tcx>(
232    cx: &'cx dyn HirTyLowerer<'tcx>,
233    mut spans: Vec<Span>,
234    kind: &'static str,
235) -> Diag<'cx> {
236    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") };
237
238    spans.sort();
239    cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
240}
241
242impl<'tcx> ItemCtxt<'tcx> {
243    pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
244        ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
245    }
246
247    pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
248        self.lowerer().lower_ty(hir_ty)
249    }
250
251    pub(crate) fn hir_id(&self) -> hir::HirId {
252        self.tcx.local_def_id_to_hir_id(self.item_def_id)
253    }
254
255    pub(crate) fn node(&self) -> hir::Node<'tcx> {
256        self.tcx.hir_node(self.hir_id())
257    }
258
259    fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
260        match self.tainted_by_errors.get() {
261            Some(err) => Err(err),
262            None => Ok(()),
263        }
264    }
265
266    fn report_placeholder_type_error(
267        &self,
268        placeholder_types: Vec<Span>,
269        infer_replacements: Vec<(Span, String)>,
270    ) -> ErrorGuaranteed {
271        let node = self.tcx.hir_node_by_def_id(self.item_def_id);
272        let generics = node.generics();
273        let kind_id = match node {
274            Node::GenericParam(_) | Node::WherePredicate(_) | Node::Field(_) => {
275                self.tcx.local_parent(self.item_def_id)
276            }
277            _ => self.item_def_id,
278        };
279        let kind = self.tcx.def_descr(kind_id.into());
280        let mut diag = placeholder_type_error_diag(
281            self,
282            generics,
283            placeholder_types,
284            infer_replacements.iter().map(|&(span, _)| span).collect(),
285            false,
286            None,
287            kind,
288        );
289        if !infer_replacements.is_empty() {
290            diag.multipart_suggestion(
291                ::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!(
292                    "try replacing `_` with the type{} in the corresponding trait method \
293                        signature",
294                    rustc_errors::pluralize!(infer_replacements.len()),
295                ),
296                infer_replacements,
297                Applicability::MachineApplicable,
298            );
299        }
300
301        diag.emit()
302    }
303}
304
305impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
306    fn tcx(&self) -> TyCtxt<'tcx> {
307        self.tcx
308    }
309
310    fn dcx(&self) -> DiagCtxtHandle<'_> {
311        self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
312    }
313
314    fn item_def_id(&self) -> LocalDefId {
315        self.item_def_id
316    }
317
318    fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
319        if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason {
320            // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in
321            //        `*const dyn Trait` and `Fn() -> *const dyn Trait`.
322            let guar = self
323                .dcx()
324                .struct_span_err(
325                    span,
326                    "cannot deduce the lifetime bound for this trait object type from context",
327                )
328                .with_code(E0228)
329                .with_span_suggestion_verbose(
330                    sugg_sp,
331                    "please supply an explicit bound",
332                    " + /* 'a */",
333                    Applicability::HasPlaceholders,
334                )
335                .emit();
336            ty::Region::new_error(self.tcx(), guar)
337        } else {
338            // This indicates an illegal lifetime in a non-assoc-trait position
339            ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
340        }
341    }
342
343    fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
344        if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) {
345            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![]);
346        }
347        Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
348    }
349
350    fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
351        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![]);
352        ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
353    }
354
355    fn register_trait_ascription_bounds(
356        &self,
357        _: Vec<(ty::Clause<'tcx>, Span)>,
358        _: HirId,
359        span: Span,
360    ) {
361        self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
362    }
363
364    fn probe_ty_param_bounds(
365        &self,
366        span: Span,
367        def_id: LocalDefId,
368        assoc_ident: Ident,
369    ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
370        self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
371    }
372
373    x;#[instrument(level = "debug", skip(self, _span), ret)]
374    fn select_inherent_assoc_candidates(
375        &self,
376        _span: Span,
377        self_ty: Ty<'tcx>,
378        candidates: Vec<InherentAssocCandidate>,
379    ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
380        assert!(!self_ty.has_infer());
381
382        // We don't just call the normal normalization routine here as we can't provide the
383        // correct `ParamEnv` and it would be wrong to invoke arbitrary trait solving under
384        // the wrong `ParamEnv`. Expanding free aliases doesn't need a `ParamEnv` so we do
385        // this just to make resolution a little bit smarter.
386        let self_ty = self.tcx.expand_free_alias_tys(self_ty);
387        debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
388
389        let candidates = candidates
390            .into_iter()
391            .filter(|&InherentAssocCandidate { impl_, .. }| {
392                let impl_ty = self.tcx().type_of(impl_).instantiate_identity().skip_norm_wip();
393
394                // See comment on doing this operation for `self_ty`
395                let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
396                debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
397
398                // We treat parameters in the self ty as rigid and parameters in the impl ty as infers
399                // because it allows `impl<T> Foo<T>` to unify with `Foo<u8>::IAT`, while also disallowing
400                // `Foo<T>::IAT` from unifying with `impl Foo<u8>`.
401                //
402                // We don't really care about a depth limit here because we're only working with user-written
403                // types and if they wrote a type that would take hours to walk then that's kind of on them. On
404                // the other hand the default depth limit is relatively low and could realistically be hit by
405                // users in normal cases.
406                //
407                // `DeepRejectCtxt` leads to slightly worse IAT resolution than real type equality in cases
408                // where the `impl_ty` has repeated uses of generic parameters. E.g. `impl<T> Foo<T, T>` would
409                // be considered a valid candidate when resolving `Foo<u8, u16>::IAT`.
410                //
411                // Not replacing escaping bound vars in `self_ty` with placeholders also leads to slightly worse
412                // resolution, but it probably won't come up in practice and it would be backwards compatible
413                // to switch over to doing that.
414                ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
415                    self_ty,
416                    impl_ty,
417                    usize::MAX,
418                )
419            })
420            .collect();
421
422        (candidates, vec![])
423    }
424
425    fn lower_assoc_item_path(
426        &self,
427        span: Span,
428        item_def_id: DefId,
429        item_segment: &rustc_hir::PathSegment<'tcx>,
430        poly_trait_ref: ty::PolyTraitRef<'tcx>,
431    ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
432        if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
433            let item_args = self.lowerer().lower_generic_args_of_assoc_item(
434                span,
435                item_def_id,
436                item_segment,
437                trait_ref.args,
438            );
439            Ok((item_def_id, item_args))
440        } else {
441            // There are no late-bound regions; we can just ignore the binder.
442            let (mut mpart_sugg, mut inferred_sugg) = (None, None);
443            let mut bound = String::new();
444
445            match self.node() {
446                hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
447                    let item = self
448                        .tcx
449                        .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
450                    match &item.kind {
451                        hir::ItemKind::Enum(_, generics, _)
452                        | hir::ItemKind::Struct(_, generics, _)
453                        | hir::ItemKind::Union(_, generics, _) => {
454                            let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
455                            let (lt_sp, sugg) = match generics.params {
456                                [] => (generics.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", lt_name))
    })format!("<{lt_name}>")),
457                                [bound, ..] => (bound.span.shrink_to_lo(), ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", lt_name))
    })format!("{lt_name}, ")),
458                            };
459                            mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
460                                fspan: lt_sp,
461                                first: sugg,
462                                sspan: span.with_hi(item_segment.ident.span.lo()),
463                                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!(
464                                    "{}::",
465                                    // Replace the existing lifetimes with a new named lifetime.
466                                    self.tcx.instantiate_bound_regions_uncached(
467                                        poly_trait_ref,
468                                        |_| {
469                                            ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
470                                                index: 0,
471                                                name: Symbol::intern(&lt_name),
472                                            })
473                                        }
474                                    ),
475                                ),
476                            });
477                        }
478                        _ => {}
479                    }
480                }
481                hir::Node::Item(hir::Item {
482                    kind:
483                        hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
484                    ..
485                }) => {}
486                hir::Node::Item(_)
487                | hir::Node::ForeignItem(_)
488                | hir::Node::TraitItem(_)
489                | hir::Node::ImplItem(_) => {
490                    inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
491                    bound = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::",
                self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder()))
    })format!(
492                        "{}::",
493                        // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
494                        self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
495                    );
496                }
497                _ => {}
498            }
499
500            Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
501                span,
502                inferred_sugg,
503                bound,
504                mpart_sugg,
505                what: self.tcx.def_descr(item_def_id),
506            }))
507        }
508    }
509
510    fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
511        // FIXME(#103640): Should we handle the case where `ty` is a projection?
512        ty.ty_adt_def()
513    }
514
515    fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
516        // There's no place to record types from signatures?
517    }
518
519    fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
520        None
521    }
522
523    fn lower_fn_sig(
524        &self,
525        decl: &hir::FnDecl<'tcx>,
526        _generics: Option<&hir::Generics<'_>>,
527        hir_id: rustc_hir::HirId,
528        _hir_ty: Option<&hir::Ty<'_>>,
529    ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
530        let tcx = self.tcx();
531
532        let mut infer_replacements = ::alloc::vec::Vec::new()vec![];
533
534        let input_tys = decl
535            .inputs
536            .iter()
537            .enumerate()
538            .map(|(i, a)| {
539                if let hir::TyKind::Infer(()) = a.kind
540                    && let Some(suggested_ty) =
541                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
542                {
543                    infer_replacements.push((a.span, suggested_ty.to_string()));
544                    return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
545                }
546
547                self.lowerer().lower_ty(a)
548            })
549            .collect();
550
551        let output_ty = match decl.output {
552            hir::FnRetTy::Return(output) => {
553                if let hir::TyKind::Infer(()) = output.kind
554                    && let Some(suggested_ty) =
555                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
556                {
557                    infer_replacements.push((output.span, suggested_ty.to_string()));
558                    Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
559                } else {
560                    self.lower_ty(output)
561                }
562            }
563            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
564        };
565
566        if !infer_replacements.is_empty() {
567            self.report_placeholder_type_error(::alloc::vec::Vec::new()vec![], infer_replacements);
568        }
569        (input_tys, output_ty)
570    }
571
572    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
573        hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
574    }
575}
576
577/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
578fn get_new_lifetime_name<'tcx>(
579    tcx: TyCtxt<'tcx>,
580    poly_trait_ref: ty::PolyTraitRef<'tcx>,
581    generics: &hir::Generics<'tcx>,
582) -> String {
583    let existing_lifetimes = tcx
584        .collect_referenced_late_bound_regions(poly_trait_ref)
585        .into_iter()
586        .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
587        .chain(generics.params.iter().filter_map(|param| {
588            if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
589                Some(param.name.ident().as_str().to_string())
590            } else {
591                None
592            }
593        }))
594        .collect::<FxHashSet<String>>();
595
596    let a_to_z_repeat_n = |n| {
597        (b'a'..=b'z').map(move |c| {
598            let mut s = '\''.to_string();
599            s.extend(std::iter::repeat_n(char::from(c), n));
600            s
601        })
602    };
603
604    // If all single char lifetime names are present, we wrap around and double the chars.
605    (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
606}
607
608pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
609    tcx.ensure_ok().generics_of(def_id);
610    tcx.ensure_ok().type_of(def_id);
611    tcx.ensure_ok().predicates_of(def_id);
612}
613
614pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: LocalDefId) {
615    struct ReprCIssue {
616        msg: &'static str,
617    }
618
619    impl<'a> Diagnostic<'a, ()> for ReprCIssue {
620        fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
621            let Self { msg } = self;
622            Diag::new(dcx, level, msg)
623                .with_note("`repr(C)` enums with big discriminants are non-portable, and their size in Rust might not match their size in C")
624                .with_help("use `repr($int_ty)` instead to explicitly set the size of this enum")
625        }
626    }
627
628    let def = tcx.adt_def(def_id);
629    let repr_type = def.repr().discr_type();
630    let initial = repr_type.initial_discriminant(tcx);
631    let mut prev_discr = None::<Discr<'_>>;
632    // Some of the logic below relies on `i128` being able to hold all c_int and c_uint values.
633    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);
634    let mut min_discr = i128::MAX;
635    let mut max_discr = i128::MIN;
636
637    // fill the discriminant values and field types
638    for variant in def.variants() {
639        let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
640        let cur_discr = if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
641            def.eval_explicit_discr(tcx, const_def_id).ok()
642        } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
643            Some(discr)
644        } else {
645            let span = tcx.def_span(variant.def_id);
646            tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
647                span,
648                discr: prev_discr.unwrap().to_string(),
649                item_name: tcx.item_ident(variant.def_id),
650                wrapped_discr: wrapped_discr.to_string(),
651            });
652            None
653        }
654        .unwrap_or(wrapped_discr);
655
656        if def.repr().c() {
657            let c_int = Size::from_bits(tcx.sess.target.c_int_width);
658            let c_uint_max = i128::try_from(c_int.unsigned_int_max()).unwrap();
659            // c_int is a signed type, so get a proper signed version of the discriminant
660            let discr_size = cur_discr.ty.int_size_and_signed(tcx).0;
661            let discr_val = discr_size.sign_extend(cur_discr.val);
662            min_discr = min_discr.min(discr_val);
663            max_discr = max_discr.max(discr_val);
664
665            // The discriminant range must either fit into c_int or c_uint.
666            if !(min_discr >= c_int.signed_int_min() && max_discr <= c_int.signed_int_max())
667                && !(min_discr >= 0 && max_discr <= c_uint_max)
668            {
669                let span = tcx.def_span(variant.def_id);
670                let msg = if discr_val < c_int.signed_int_min() || discr_val > c_uint_max {
671                    "`repr(C)` enum discriminant does not fit into C `int` nor into C `unsigned int`"
672                } else if discr_val < 0 {
673                    "`repr(C)` enum discriminant does not fit into C `unsigned int`, and a previous discriminant does not fit into C `int`"
674                } else {
675                    "`repr(C)` enum discriminant does not fit into C `int`, and a previous discriminant does not fit into C `unsigned int`"
676                };
677                tcx.emit_node_span_lint(
678                    rustc_session::lint::builtin::REPR_C_ENUMS_LARGER_THAN_INT,
679                    tcx.local_def_id_to_hir_id(def_id),
680                    span,
681                    ReprCIssue { msg },
682                );
683            }
684        }
685
686        prev_discr = Some(cur_discr);
687
688        for f in &variant.fields {
689            tcx.ensure_ok().generics_of(f.did);
690            tcx.ensure_ok().type_of(f.did);
691            tcx.ensure_ok().predicates_of(f.did);
692        }
693
694        // Lower the ctor, if any. This also registers the variant as an item.
695        if let Some(ctor_def_id) = variant.ctor_def_id() {
696            lower_variant_ctor(tcx, ctor_def_id.expect_local());
697        }
698    }
699}
700
701#[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)]
702struct NestedSpan {
703    span: Span,
704    nested_field_span: Span,
705}
706
707impl NestedSpan {
708    fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
709        errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
710    }
711}
712
713#[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)]
714enum FieldDeclSpan {
715    NotNested(Span),
716    Nested(NestedSpan),
717}
718
719impl From<Span> for FieldDeclSpan {
720    fn from(span: Span) -> Self {
721        Self::NotNested(span)
722    }
723}
724
725impl From<NestedSpan> for FieldDeclSpan {
726    fn from(span: NestedSpan) -> Self {
727        Self::Nested(span)
728    }
729}
730
731struct FieldUniquenessCheckContext<'tcx> {
732    tcx: TyCtxt<'tcx>,
733    seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
734}
735
736impl<'tcx> FieldUniquenessCheckContext<'tcx> {
737    fn new(tcx: TyCtxt<'tcx>) -> Self {
738        Self { tcx, seen_fields: FxIndexMap::default() }
739    }
740
741    /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
742    fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
743        use FieldDeclSpan::*;
744        let field_name = field_name.normalize_to_macros_2_0();
745        match (field_decl, self.seen_fields.get(&field_name).copied()) {
746            (NotNested(span), Some(NotNested(prev_span))) => {
747                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
748                    field_name,
749                    span,
750                    prev_span,
751                });
752            }
753            (NotNested(span), Some(Nested(prev))) => {
754                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
755                    field_name,
756                    span,
757                    prev_span: prev.span,
758                    prev_nested_field_span: prev.nested_field_span,
759                    prev_help: prev.to_field_already_declared_nested_help(),
760                });
761            }
762            (
763                Nested(current @ NestedSpan { span, nested_field_span, .. }),
764                Some(NotNested(prev_span)),
765            ) => {
766                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
767                    field_name,
768                    span,
769                    nested_field_span,
770                    help: current.to_field_already_declared_nested_help(),
771                    prev_span,
772                });
773            }
774            (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
775                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
776                    field_name,
777                    span,
778                    nested_field_span,
779                    help: current.to_field_already_declared_nested_help(),
780                    prev_span: prev.span,
781                    prev_nested_field_span: prev.nested_field_span,
782                    prev_help: prev.to_field_already_declared_nested_help(),
783                });
784            }
785            (field_decl, None) => {
786                self.seen_fields.insert(field_name, field_decl);
787            }
788        }
789    }
790}
791
792fn lower_variant<'tcx>(
793    tcx: TyCtxt<'tcx>,
794    variant_did: Option<LocalDefId>,
795    ident: Ident,
796    discr: ty::VariantDiscr,
797    def: &hir::VariantData<'tcx>,
798    adt_kind: ty::AdtKind,
799    parent_did: LocalDefId,
800) -> ty::VariantDef {
801    let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
802    let fields = def
803        .fields()
804        .iter()
805        .inspect(|field| {
806            field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
807        })
808        .map(|f| ty::FieldDef {
809            did: f.def_id.to_def_id(),
810            name: f.ident.name,
811            vis: tcx.visibility(f.def_id),
812            safety: f.safety,
813            value: f.default.map(|v| v.def_id.to_def_id()),
814        })
815        .collect();
816    let recovered = match def {
817        hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
818        _ => None,
819    };
820    ty::VariantDef::new(
821        ident.name,
822        variant_did.map(LocalDefId::to_def_id),
823        def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
824        discr,
825        fields,
826        parent_did.to_def_id(),
827        recovered,
828        adt_kind == AdtKind::Struct && {
        {
            'done:
                {
                for i in
                    ::rustc_hir::attrs::HasAttrs::get_attrs(parent_did, &tcx) {
                    #[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(..))
829            || variant_did
830                .is_some_and(|variant_did| {
        {
            'done:
                {
                for i in
                    ::rustc_hir::attrs::HasAttrs::get_attrs(variant_did, &tcx) {
                    #[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(..))),
831    )
832}
833
834fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
835    use rustc_hir::*;
836
837    let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
838        ::rustc_middle::util::bug::bug_fmt(format_args!("expected ADT to be an item"));bug!("expected ADT to be an item");
839    };
840
841    let repr = tcx.repr_options_of_def(def_id);
842    let (kind, variants) = match &item.kind {
843        ItemKind::Enum(_, _, def) => {
844            let mut distance_from_explicit = 0;
845            let variants = def
846                .variants
847                .iter()
848                .map(|v| {
849                    let discr = if let Some(e) = &v.disr_expr {
850                        distance_from_explicit = 0;
851                        ty::VariantDiscr::Explicit(e.def_id.to_def_id())
852                    } else {
853                        ty::VariantDiscr::Relative(distance_from_explicit)
854                    };
855                    distance_from_explicit += 1;
856
857                    lower_variant(
858                        tcx,
859                        Some(v.def_id),
860                        v.ident,
861                        discr,
862                        &v.data,
863                        AdtKind::Enum,
864                        def_id,
865                    )
866                })
867                .collect();
868
869            (AdtKind::Enum, variants)
870        }
871        ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
872            let adt_kind = match item.kind {
873                ItemKind::Struct(..) => AdtKind::Struct,
874                _ => AdtKind::Union,
875            };
876            let variants = std::iter::once(lower_variant(
877                tcx,
878                None,
879                *ident,
880                ty::VariantDiscr::Relative(0),
881                def,
882                adt_kind,
883                def_id,
884            ))
885            .collect();
886
887            (adt_kind, variants)
888        }
889        _ => ::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),
890    };
891    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
892}
893
894fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
895    let item = tcx.hir_expect_item(def_id);
896
897    let (constness, is_alias, is_auto, safety, impl_restriction) = match item.kind {
898        hir::ItemKind::Trait(constness, is_auto, safety, impl_restriction, ..) => (
899            constness,
900            false,
901            is_auto == hir::IsAuto::Yes,
902            safety,
903            if let hir::RestrictionKind::Restricted(path) = impl_restriction.kind {
904                ty::trait_def::ImplRestrictionKind::Restricted(path.res, impl_restriction.span)
905            } else {
906                ty::trait_def::ImplRestrictionKind::Unrestricted
907            },
908        ),
909        hir::ItemKind::TraitAlias(constness, ..) => (
910            constness,
911            true,
912            false,
913            hir::Safety::Safe,
914            ty::trait_def::ImplRestrictionKind::Unrestricted,
915        ),
916        _ => ::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"),
917    };
918
919    // we do a bunch of find_attr calls here, probably faster to get them from the tcx just once.
920    #[allow(deprecated)]
921    let attrs = tcx.get_all_attrs(def_id);
922
923    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(_));
924    if paren_sugar && !tcx.features().unboxed_closures() {
925        tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
926    }
927
928    // Only regular traits can be marker.
929    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(_));
930
931    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(_));
932    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);
933
934    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!(
935        attrs,
936        RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
937    )
938    .unwrap_or([false; 2]);
939
940    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(_)) {
941        ty::trait_def::TraitSpecializationKind::Marker
942    } 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(_)) {
943        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
944    } else {
945        ty::trait_def::TraitSpecializationKind::None
946    };
947
948    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!(
949        attrs,
950        RustcMustImplementOneOf { fn_names, .. } =>
951            fn_names
952                .iter()
953                .cloned()
954                .collect::<Box<[_]>>()
955    );
956
957    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(_));
958    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);
959
960    ty::TraitDef {
961        def_id: def_id.to_def_id(),
962        safety,
963        constness,
964        impl_restriction,
965        paren_sugar,
966        has_auto_impl: is_auto,
967        is_marker,
968        is_coinductive: rustc_coinductive || is_auto,
969        is_fundamental,
970        skip_array_during_method_dispatch,
971        skip_boxed_slice_during_method_dispatch,
972        specialization_kind,
973        must_implement_one_of,
974        force_dyn_incompatible,
975        deny_explicit_impl,
976    }
977}
978
979x;#[instrument(level = "debug", skip(tcx), ret)]
980fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
981    use rustc_hir::Node::*;
982    use rustc_hir::*;
983
984    let hir_id = tcx.local_def_id_to_hir_id(def_id);
985
986    let icx = ItemCtxt::new(tcx, def_id);
987
988    let output = match tcx.hir_node(hir_id) {
989        TraitItem(hir::TraitItem {
990            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
991            generics,
992            ..
993        })
994        | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
995            lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
996        }
997
998        ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
999            // Do not try to infer the return type for a impl method coming from a trait
1000            if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1001                && i.of_trait.is_some()
1002            {
1003                icx.lowerer().lower_fn_ty(
1004                    hir_id,
1005                    sig.header.safety(),
1006                    sig.header.abi,
1007                    sig.decl,
1008                    Some(generics),
1009                    None,
1010                )
1011            } else {
1012                lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1013            }
1014        }
1015
1016        TraitItem(hir::TraitItem {
1017            kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1018            generics,
1019            ..
1020        }) => icx.lowerer().lower_fn_ty(
1021            hir_id,
1022            header.safety(),
1023            header.abi,
1024            decl,
1025            Some(generics),
1026            None,
1027        ),
1028
1029        ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1030            let abi = tcx.hir_get_foreign_abi(hir_id);
1031            compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1032        }
1033
1034        Ctor(data) => {
1035            assert_matches!(data.ctor(), Some(_));
1036            let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1037            let ty = tcx.type_of(adt_def_id).instantiate_identity().skip_norm_wip();
1038            let inputs = data
1039                .fields()
1040                .iter()
1041                .map(|f| tcx.type_of(f.def_id).instantiate_identity().skip_norm_wip());
1042            // constructors for structs with `layout_scalar_valid_range` are unsafe to call
1043            let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1044                (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1045                _ => hir::Safety::Unsafe,
1046            };
1047            ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(inputs, ty, safety))
1048        }
1049
1050        Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1051            // Closure signatures are not like other function
1052            // signatures and cannot be accessed through `fn_sig`. For
1053            // example, a closure signature excludes the `self`
1054            // argument. In any case they are embedded within the
1055            // closure type as part of the `ClosureArgs`.
1056            //
1057            // To get the signature of a closure, you should use the
1058            // `sig` method on the `ClosureArgs`:
1059            //
1060            //    args.as_closure().sig(def_id, tcx)
1061            bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1062        }
1063
1064        x => {
1065            bug!("unexpected sort of node in fn_sig(): {:?}", x);
1066        }
1067    };
1068    ty::EarlyBinder::bind(output)
1069}
1070
1071fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1072    icx: &ItemCtxt<'tcx>,
1073    sig: &'tcx hir::FnSig<'tcx>,
1074    generics: &'tcx hir::Generics<'tcx>,
1075    def_id: LocalDefId,
1076) -> ty::PolyFnSig<'tcx> {
1077    if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1078        return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1079    }
1080
1081    icx.lowerer().lower_fn_ty(
1082        icx.tcx().local_def_id_to_hir_id(def_id),
1083        sig.header.safety(),
1084        sig.header.abi,
1085        sig.decl,
1086        Some(generics),
1087        None,
1088    )
1089}
1090
1091/// Convert `ReLateParam`s in `value` back into `ReBound`s and bind it with `bound_vars`.
1092fn late_param_regions_to_bound<'tcx, T>(
1093    tcx: TyCtxt<'tcx>,
1094    scope: DefId,
1095    bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
1096    value: T,
1097) -> ty::Binder<'tcx, T>
1098where
1099    T: ty::TypeFoldable<TyCtxt<'tcx>>,
1100{
1101    let value = fold_regions(tcx, value, |r, debruijn| match r.kind() {
1102        ty::ReLateParam(lp) => {
1103            // Should be in scope, otherwise inconsistency happens somewhere.
1104            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);
1105
1106            let br = match lp.kind {
1107                // These variants preserve the bound var index.
1108                kind @ (ty::LateParamRegionKind::Anon(idx)
1109                | ty::LateParamRegionKind::NamedAnon(idx, _)) => {
1110                    let idx = idx as usize;
1111                    let var = ty::BoundVar::from_usize(idx);
1112
1113                    let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied()
1114                    else {
1115                        ::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:?}");
1116                    };
1117
1118                    ty::BoundRegion { var, kind }
1119                }
1120
1121                // For named regions, look up the corresponding bound var.
1122                ty::LateParamRegionKind::Named(def_id) => bound_vars
1123                    .iter()
1124                    .enumerate()
1125                    .find_map(|(idx, bv)| match bv {
1126                        ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did))
1127                            if did == def_id =>
1128                        {
1129                            Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1130                        }
1131                        _ => None,
1132                    })
1133                    .unwrap(),
1134
1135                ty::LateParamRegionKind::ClosureEnv => bound_vars
1136                    .iter()
1137                    .enumerate()
1138                    .find_map(|(idx, bv)| match bv {
1139                        ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => {
1140                            Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1141                        }
1142                        _ => None,
1143                    })
1144                    .unwrap(),
1145            };
1146
1147            ty::Region::new_bound(tcx, debruijn, br)
1148        }
1149        _ => r,
1150    });
1151
1152    ty::Binder::bind_with_vars(value, bound_vars)
1153}
1154
1155fn recover_infer_ret_ty<'tcx>(
1156    icx: &ItemCtxt<'tcx>,
1157    infer_ret_ty: &'tcx hir::Ty<'tcx>,
1158    generics: &'tcx hir::Generics<'tcx>,
1159    def_id: LocalDefId,
1160) -> ty::PolyFnSig<'tcx> {
1161    let tcx = icx.tcx;
1162    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1163
1164    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1165
1166    // Typeck doesn't expect erased regions to be returned from `type_of`.
1167    // This is a heuristic approach. If the scope has region parameters,
1168    // we should change fn_sig's lifetime from `ReErased` to `ReError`,
1169    // otherwise to `ReStatic`.
1170    let has_region_params = generics.params.iter().any(|param| match param.kind {
1171        GenericParamKind::Lifetime { .. } => true,
1172        _ => false,
1173    });
1174    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1175        ty::ReErased => {
1176            if has_region_params {
1177                ty::Region::new_error_with_message(
1178                    tcx,
1179                    DUMMY_SP,
1180                    "erased region is not allowed here in return type",
1181                )
1182            } else {
1183                tcx.lifetimes.re_static
1184            }
1185        }
1186        _ => r,
1187    });
1188
1189    let mut visitor = HirPlaceholderCollector::default();
1190    visitor.visit_ty_unambig(infer_ret_ty);
1191
1192    let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1193    let ret_ty = fn_sig.output();
1194
1195    // Don't leak types into signatures unless they're nameable!
1196    // For example, if a function returns itself, we don't want that
1197    // recursive function definition to leak out into the fn sig.
1198    let mut recovered_ret_ty = None;
1199    if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1200        diag.span_suggestion_verbose(
1201            infer_ret_ty.span,
1202            "replace with the correct return type",
1203            suggestable_ret_ty,
1204            Applicability::MachineApplicable,
1205        );
1206        recovered_ret_ty = Some(suggestable_ret_ty);
1207    } else if let Some(sugg) = suggest_impl_trait(
1208        &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1209        tcx.param_env(def_id),
1210        ret_ty,
1211    ) {
1212        diag.span_suggestion_verbose(
1213            infer_ret_ty.span,
1214            "replace with an appropriate return type",
1215            sugg,
1216            Applicability::MachineApplicable,
1217        );
1218    } else if ret_ty.is_closure() {
1219        diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1220    }
1221
1222    // Also note how `Fn` traits work just in case!
1223    if ret_ty.is_closure() {
1224        diag.note(
1225            "for more information on `Fn` traits and closure types, see \
1226                     https://doc.rust-lang.org/book/ch13-01-closures.html",
1227        );
1228    }
1229    let guar = diag.emit();
1230
1231    // If we return a dummy binder here, we can ICE later in borrowck when it encounters
1232    // `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the
1233    // signature binder. See #135845.
1234    let bound_vars = tcx.late_bound_vars(hir_id);
1235    let scope = def_id.to_def_id();
1236
1237    let fn_sig = tcx.mk_fn_sig(
1238        fn_sig.inputs().iter().copied(),
1239        recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1240        fn_sig.fn_sig_kind,
1241    );
1242
1243    late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
1244}
1245
1246pub fn suggest_impl_trait<'tcx>(
1247    infcx: &InferCtxt<'tcx>,
1248    param_env: ty::ParamEnv<'tcx>,
1249    ret_ty: Ty<'tcx>,
1250) -> Option<String> {
1251    let format_as_assoc: fn(_, _, _, _, _) -> _ =
1252        |tcx: TyCtxt<'tcx>,
1253         _: ty::GenericArgsRef<'tcx>,
1254         trait_def_id: DefId,
1255         assoc_item_def_id: DefId,
1256         item_ty: Ty<'tcx>| {
1257            let trait_name = tcx.item_name(trait_def_id);
1258            let assoc_name = tcx.item_name(assoc_item_def_id);
1259            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}>"))
1260        };
1261    let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1262        |tcx: TyCtxt<'tcx>,
1263         args: ty::GenericArgsRef<'tcx>,
1264         trait_def_id: DefId,
1265         _: DefId,
1266         item_ty: Ty<'tcx>| {
1267            let trait_name = tcx.item_name(trait_def_id);
1268            let args_tuple = args.type_at(1);
1269            let ty::Tuple(types) = *args_tuple.kind() else {
1270                return None;
1271            };
1272            let types = types.make_suggestable(tcx, false, None)?;
1273            let maybe_ret =
1274                if item_ty.is_unit() { String::new() } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" -> {0}", item_ty))
    })format!(" -> {item_ty}") };
1275            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!(
1276                "impl {trait_name}({}){maybe_ret}",
1277                types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1278            ))
1279        };
1280
1281    for (trait_def_id, assoc_item_def_id, formatter) in [
1282        (
1283            infcx.tcx.get_diagnostic_item(sym::Iterator),
1284            infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1285            format_as_assoc,
1286        ),
1287        (
1288            infcx.tcx.lang_items().future_trait(),
1289            infcx.tcx.lang_items().future_output(),
1290            format_as_assoc,
1291        ),
1292        (
1293            infcx.tcx.lang_items().async_fn_trait(),
1294            infcx.tcx.lang_items().async_fn_once_output(),
1295            format_as_parenthesized,
1296        ),
1297        (
1298            infcx.tcx.lang_items().async_fn_mut_trait(),
1299            infcx.tcx.lang_items().async_fn_once_output(),
1300            format_as_parenthesized,
1301        ),
1302        (
1303            infcx.tcx.lang_items().async_fn_once_trait(),
1304            infcx.tcx.lang_items().async_fn_once_output(),
1305            format_as_parenthesized,
1306        ),
1307        (
1308            infcx.tcx.lang_items().fn_trait(),
1309            infcx.tcx.lang_items().fn_once_output(),
1310            format_as_parenthesized,
1311        ),
1312        (
1313            infcx.tcx.lang_items().fn_mut_trait(),
1314            infcx.tcx.lang_items().fn_once_output(),
1315            format_as_parenthesized,
1316        ),
1317        (
1318            infcx.tcx.lang_items().fn_once_trait(),
1319            infcx.tcx.lang_items().fn_once_output(),
1320            format_as_parenthesized,
1321        ),
1322    ] {
1323        let Some(trait_def_id) = trait_def_id else {
1324            continue;
1325        };
1326        let Some(assoc_item_def_id) = assoc_item_def_id else {
1327            continue;
1328        };
1329        if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1330            continue;
1331        }
1332        let sugg = infcx.probe(|_| {
1333            let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1334                if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1335            });
1336            if !infcx
1337                .type_implements_trait(trait_def_id, args, param_env)
1338                .must_apply_modulo_regions()
1339            {
1340                return None;
1341            }
1342            let ocx = ObligationCtxt::new(&infcx);
1343            let item_ty = ocx.normalize(
1344                &ObligationCause::dummy(),
1345                param_env,
1346                Unnormalized::new(Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args)),
1347            );
1348            // FIXME(compiler-errors): We may benefit from resolving regions here.
1349            if ocx.try_evaluate_obligations().is_empty()
1350                && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1351                && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1352                && let Some(sugg) = formatter(
1353                    infcx.tcx,
1354                    infcx.resolve_vars_if_possible(args),
1355                    trait_def_id,
1356                    assoc_item_def_id,
1357                    item_ty,
1358                )
1359            {
1360                return Some(sugg);
1361            }
1362
1363            None
1364        });
1365
1366        if sugg.is_some() {
1367            return sugg;
1368        }
1369    }
1370    None
1371}
1372
1373fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
1374    let icx = ItemCtxt::new(tcx, def_id);
1375    let item = tcx.hir_expect_item(def_id);
1376    let impl_ = item.expect_impl();
1377    let of_trait = impl_
1378        .of_trait
1379        .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:?}"));
1380    let selfty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
1381    let is_rustc_reservation = {
        {
            'done:
                {
                for i in ::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &tcx)
                    {
                    #[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(..));
1382
1383    check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref);
1384
1385    let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
1386
1387    ty::ImplTraitHeader {
1388        trait_ref: ty::EarlyBinder::bind(trait_ref),
1389        safety: of_trait.safety,
1390        polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
1391        constness: impl_.constness,
1392    }
1393}
1394
1395fn check_impl_constness(
1396    tcx: TyCtxt<'_>,
1397    constness: hir::Constness,
1398    hir_trait_ref: &hir::TraitRef<'_>,
1399) {
1400    if let hir::Constness::NotConst = constness {
1401        return;
1402    }
1403
1404    let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1405    if tcx.is_const_trait(trait_def_id) {
1406        return;
1407    }
1408
1409    let trait_name = tcx.item_name(trait_def_id).to_string();
1410    let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build())
1411    {
1412        (Some(trait_def_id), true) => {
1413            let span = tcx.hir_expect_item(trait_def_id).vis_span;
1414            let span = tcx.sess.source_map().span_extend_while_whitespace(span);
1415
1416            (
1417                Some(span.shrink_to_hi()),
1418                if tcx.features().const_trait_impl() {
1419                    ""
1420                } else {
1421                    "enable `#![feature(const_trait_impl)]` in your crate and "
1422                },
1423            )
1424        }
1425        (None, _) | (_, false) => (None, ""),
1426    };
1427    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1428        trait_ref_span: hir_trait_ref.path.span,
1429        trait_name,
1430        suggestion,
1431        suggestion_pre,
1432        marking: (),
1433        adding: (),
1434    });
1435}
1436
1437fn polarity_of_impl(
1438    tcx: TyCtxt<'_>,
1439    of_trait: &hir::TraitImplHeader<'_>,
1440    is_rustc_reservation: bool,
1441) -> ty::ImplPolarity {
1442    match of_trait.polarity {
1443        hir::ImplPolarity::Negative(span) => {
1444            if is_rustc_reservation {
1445                let span = span.to(of_trait.trait_ref.path.span);
1446                tcx.dcx().span_err(span, "reservation impls can't be negative");
1447            }
1448            ty::ImplPolarity::Negative
1449        }
1450        hir::ImplPolarity::Positive => {
1451            if is_rustc_reservation {
1452                ty::ImplPolarity::Reservation
1453            } else {
1454                ty::ImplPolarity::Positive
1455            }
1456        }
1457    }
1458}
1459
1460/// Returns the early-bound lifetimes declared in this generics
1461/// listing. For anything other than fns/methods, this is just all
1462/// the lifetimes that are declared. For fns or methods, we have to
1463/// screen out those that do not appear in any where-clauses etc using
1464/// `resolve_lifetime::early_bound_lifetimes`.
1465fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1466    tcx: TyCtxt<'tcx>,
1467    generics: &'a hir::Generics<'a>,
1468) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1469    generics.params.iter().filter(move |param| match param.kind {
1470        GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1471        _ => false,
1472    })
1473}
1474
1475fn compute_sig_of_foreign_fn_decl<'tcx>(
1476    tcx: TyCtxt<'tcx>,
1477    def_id: LocalDefId,
1478    decl: &'tcx hir::FnDecl<'tcx>,
1479    abi: ExternAbi,
1480    safety: hir::Safety,
1481) -> ty::PolyFnSig<'tcx> {
1482    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1483    let fty =
1484        ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1485
1486    // Feature gate SIMD types in FFI, since I am not sure that the
1487    // ABIs are handled at all correctly. -huonw
1488    if !tcx.features().simd_ffi() {
1489        let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1490            if ty.is_simd() {
1491                let snip = tcx
1492                    .sess
1493                    .source_map()
1494                    .span_to_snippet(hir_ty.span)
1495                    .map_or_else(|_| String::new(), |s| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", s))
    })format!(" `{s}`"));
1496                tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1497            }
1498        };
1499        for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1500            check(input, *ty)
1501        }
1502        if let hir::FnRetTy::Return(ty) = decl.output {
1503            check(ty, fty.output().skip_binder())
1504        }
1505    }
1506
1507    fty
1508}
1509
1510fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1511    match tcx.hir_node_by_def_id(def_id) {
1512        Node::Expr(&hir::Expr {
1513            kind:
1514                hir::ExprKind::Closure(&rustc_hir::Closure {
1515                    kind: hir::ClosureKind::Coroutine(kind),
1516                    ..
1517                }),
1518            ..
1519        }) => Some(kind),
1520        _ => None,
1521    }
1522}
1523
1524fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1525    let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1526        tcx.hir_node_by_def_id(def_id).expect_closure()
1527    else {
1528        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1529    };
1530
1531    let &hir::Expr {
1532        kind:
1533            hir::ExprKind::Closure(&rustc_hir::Closure {
1534                def_id,
1535                kind: hir::ClosureKind::Coroutine(_),
1536                ..
1537            }),
1538        ..
1539    } = tcx.hir_body(body).value
1540    else {
1541        ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1542    };
1543
1544    def_id.to_def_id()
1545}
1546
1547fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1548    match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1549        hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1550            hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1551        }
1552        hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1553            hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1554        }
1555        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1556            hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1557        }
1558    }
1559}
1560
1561fn rendered_precise_capturing_args<'tcx>(
1562    tcx: TyCtxt<'tcx>,
1563    def_id: LocalDefId,
1564) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1565    if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1566        tcx.opt_rpitit_info(def_id.to_def_id())
1567    {
1568        return tcx.rendered_precise_capturing_args(opaque_def_id);
1569    }
1570
1571    tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1572        hir::GenericBound::Use(args, ..) => {
1573            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1574                PreciseCapturingArgKind::Lifetime(_) => {
1575                    PreciseCapturingArgKind::Lifetime(arg.name())
1576                }
1577                PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1578            })))
1579        }
1580        _ => None,
1581    })
1582}
1583
1584fn const_param_default<'tcx>(
1585    tcx: TyCtxt<'tcx>,
1586    local_def_id: LocalDefId,
1587) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1588    let hir::Node::GenericParam(hir::GenericParam {
1589        kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
1590        ..
1591    }) = tcx.hir_node_by_def_id(local_def_id)
1592    else {
1593        ::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!(
1594            tcx.def_span(local_def_id),
1595            "`const_param_default` expected a generic parameter with a constant"
1596        )
1597    };
1598
1599    let icx = ItemCtxt::new(tcx, local_def_id);
1600
1601    let def_id = local_def_id.to_def_id();
1602    let identity_args = ty::GenericArgs::identity_for_item(tcx, tcx.parent(def_id));
1603
1604    let ct = icx.lowerer().lower_const_arg(
1605        default_ct,
1606        tcx.type_of(def_id).instantiate(tcx, identity_args).skip_norm_wip(),
1607    );
1608    ty::EarlyBinder::bind(ct)
1609}
1610
1611fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1612    let hir_id = tcx.local_def_id_to_hir_id(def);
1613    let const_arg_id = tcx.parent_hir_id(hir_id);
1614    match tcx.hir_node(const_arg_id) {
1615        hir::Node::ConstArg(_) => {
1616            let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id));
1617            if tcx.features().generic_const_exprs() {
1618                ty::AnonConstKind::GCE
1619            } else if tcx.features().generic_const_args() {
1620                // Only anon consts that are the RHS of a const item can be GCA.
1621                // Note: We can't just check tcx.parent because it needs to be EXACTLY
1622                // the RHS, not just part of the RHS.
1623                if !is_anon_const_rhs_of_const_item(tcx, def) {
1624                    return ty::AnonConstKind::MCG;
1625                }
1626
1627                let body = tcx.hir_body_owned_by(def);
1628                let mut visitor = GCAParamVisitor(tcx);
1629                match visitor.visit_body(body) {
1630                    ControlFlow::Break(UsesParam) => ty::AnonConstKind::GCA,
1631                    ControlFlow::Continue(()) => ty::AnonConstKind::MCG,
1632                }
1633            } else if tcx.features().min_generic_const_args() {
1634                ty::AnonConstKind::MCG
1635            } else if let hir::Node::Expr(hir::Expr {
1636                kind: hir::ExprKind::Repeat(_, repeat_count),
1637                ..
1638            }) = parent_hir_node
1639                && repeat_count.hir_id == const_arg_id
1640            {
1641                ty::AnonConstKind::RepeatExprCount
1642            } else {
1643                ty::AnonConstKind::MCG
1644            }
1645        }
1646        _ => ty::AnonConstKind::NonTypeSystem,
1647    }
1648}
1649
1650fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
1651    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1652    let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false };
1653    let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. })
1654    | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. })
1655    | Node::TraitItem(hir::TraitItem {
1656        kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _),
1657        ..
1658    })) = grandparent_node
1659    else {
1660        return false;
1661    };
1662    let hir::ConstItemRhs::TypeConst(hir::ConstArg {
1663        kind: hir::ConstArgKind::Anon(rhs_anon), ..
1664    }) = ct_rhs
1665    else {
1666        return false;
1667    };
1668    def_id == rhs_anon.def_id
1669}
1670
1671struct GCAParamVisitor<'tcx>(TyCtxt<'tcx>);
1672
1673struct UsesParam;
1674
1675impl<'tcx> Visitor<'tcx> for GCAParamVisitor<'tcx> {
1676    type NestedFilter = nested_filter::OnlyBodies;
1677    type Result = ControlFlow<UsesParam>;
1678
1679    fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
1680        self.0
1681    }
1682
1683    fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow<UsesParam> {
1684        if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) =
1685            path.res
1686        {
1687            return ControlFlow::Break(UsesParam);
1688        }
1689
1690        intravisit::walk_path(self, path)
1691    }
1692}
1693
1694x;#[instrument(level = "debug", skip(tcx), ret)]
1695fn const_of_item<'tcx>(
1696    tcx: TyCtxt<'tcx>,
1697    def_id: LocalDefId,
1698) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1699    let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
1700        hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
1701        hir::Node::TraitItem(hir::TraitItem {
1702            kind: hir::TraitItemKind::Const(_, ct, _), ..
1703        }) => ct.expect("no default value for trait assoc const"),
1704        hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
1705        _ => {
1706            span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1707        }
1708    };
1709    let ct_arg = match ct_rhs {
1710        hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1711        hir::ConstItemRhs::Body(_) => {
1712            let e = tcx.dcx().span_delayed_bug(
1713                tcx.def_span(def_id),
1714                "cannot call const_of_item on a non-type_const",
1715            );
1716            return ty::EarlyBinder::bind(Const::new_error(tcx, e));
1717        }
1718    };
1719    let icx = ItemCtxt::new(tcx, def_id);
1720    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1721    let ct = icx.lowerer().lower_const_arg(
1722        ct_arg,
1723        tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args).skip_norm_wip(),
1724    );
1725    if let Err(e) = icx.check_tainted_by_errors()
1726        && !ct.references_error()
1727    {
1728        ty::EarlyBinder::bind(Const::new_error(tcx, e))
1729    } else {
1730        ty::EarlyBinder::bind(ct)
1731    }
1732}