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