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