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