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