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
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                    if 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
542                self.lowerer().lower_ty(a)
543            })
544            .collect();
545
546        let output_ty = match decl.output {
547            hir::FnRetTy::Return(output) => {
548                if let hir::TyKind::Infer(()) = output.kind
549                    && let Some(suggested_ty) =
550                        self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
551                {
552                    infer_replacements.push((output.span, suggested_ty.to_string()));
553                    Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
554                } else {
555                    self.lower_ty(output)
556                }
557            }
558            hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
559        };
560
561        if !infer_replacements.is_empty() {
562            self.report_placeholder_type_error(vec![], infer_replacements);
563        }
564        (input_tys, output_ty)
565    }
566
567    fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
568        hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
569    }
570}
571
572/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
573fn get_new_lifetime_name<'tcx>(
574    tcx: TyCtxt<'tcx>,
575    poly_trait_ref: ty::PolyTraitRef<'tcx>,
576    generics: &hir::Generics<'tcx>,
577) -> String {
578    let existing_lifetimes = tcx
579        .collect_referenced_late_bound_regions(poly_trait_ref)
580        .into_iter()
581        .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
582        .chain(generics.params.iter().filter_map(|param| {
583            if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
584                Some(param.name.ident().as_str().to_string())
585            } else {
586                None
587            }
588        }))
589        .collect::<FxHashSet<String>>();
590
591    let a_to_z_repeat_n = |n| {
592        (b'a'..=b'z').map(move |c| {
593            let mut s = '\''.to_string();
594            s.extend(std::iter::repeat(char::from(c)).take(n));
595            s
596        })
597    };
598
599    // If all single char lifetime names are present, we wrap around and double the chars.
600    (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
601}
602
603pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
604    tcx.ensure_ok().generics_of(def_id);
605    tcx.ensure_ok().type_of(def_id);
606    tcx.ensure_ok().predicates_of(def_id);
607}
608
609pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
610    let def = tcx.adt_def(def_id);
611    let repr_type = def.repr().discr_type();
612    let initial = repr_type.initial_discriminant(tcx);
613    let mut prev_discr = None::<Discr<'_>>;
614
615    // fill the discriminant values and field types
616    for variant in def.variants() {
617        let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
618        prev_discr = Some(
619            if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
620                def.eval_explicit_discr(tcx, const_def_id).ok()
621            } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
622                Some(discr)
623            } else {
624                let span = tcx.def_span(variant.def_id);
625                tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
626                    span,
627                    discr: prev_discr.unwrap().to_string(),
628                    item_name: tcx.item_ident(variant.def_id),
629                    wrapped_discr: wrapped_discr.to_string(),
630                });
631                None
632            }
633            .unwrap_or(wrapped_discr),
634        );
635
636        for f in &variant.fields {
637            tcx.ensure_ok().generics_of(f.did);
638            tcx.ensure_ok().type_of(f.did);
639            tcx.ensure_ok().predicates_of(f.did);
640        }
641
642        // Lower the ctor, if any. This also registers the variant as an item.
643        if let Some(ctor_def_id) = variant.ctor_def_id() {
644            lower_variant_ctor(tcx, ctor_def_id.expect_local());
645        }
646    }
647}
648
649#[derive(Clone, Copy)]
650struct NestedSpan {
651    span: Span,
652    nested_field_span: Span,
653}
654
655impl NestedSpan {
656    fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
657        errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
658    }
659}
660
661#[derive(Clone, Copy)]
662enum FieldDeclSpan {
663    NotNested(Span),
664    Nested(NestedSpan),
665}
666
667impl From<Span> for FieldDeclSpan {
668    fn from(span: Span) -> Self {
669        Self::NotNested(span)
670    }
671}
672
673impl From<NestedSpan> for FieldDeclSpan {
674    fn from(span: NestedSpan) -> Self {
675        Self::Nested(span)
676    }
677}
678
679struct FieldUniquenessCheckContext<'tcx> {
680    tcx: TyCtxt<'tcx>,
681    seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
682}
683
684impl<'tcx> FieldUniquenessCheckContext<'tcx> {
685    fn new(tcx: TyCtxt<'tcx>) -> Self {
686        Self { tcx, seen_fields: FxIndexMap::default() }
687    }
688
689    /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
690    fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
691        use FieldDeclSpan::*;
692        let field_name = field_name.normalize_to_macros_2_0();
693        match (field_decl, self.seen_fields.get(&field_name).copied()) {
694            (NotNested(span), Some(NotNested(prev_span))) => {
695                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
696                    field_name,
697                    span,
698                    prev_span,
699                });
700            }
701            (NotNested(span), Some(Nested(prev))) => {
702                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
703                    field_name,
704                    span,
705                    prev_span: prev.span,
706                    prev_nested_field_span: prev.nested_field_span,
707                    prev_help: prev.to_field_already_declared_nested_help(),
708                });
709            }
710            (
711                Nested(current @ NestedSpan { span, nested_field_span, .. }),
712                Some(NotNested(prev_span)),
713            ) => {
714                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
715                    field_name,
716                    span,
717                    nested_field_span,
718                    help: current.to_field_already_declared_nested_help(),
719                    prev_span,
720                });
721            }
722            (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
723                self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
724                    field_name,
725                    span,
726                    nested_field_span,
727                    help: current.to_field_already_declared_nested_help(),
728                    prev_span: prev.span,
729                    prev_nested_field_span: prev.nested_field_span,
730                    prev_help: prev.to_field_already_declared_nested_help(),
731                });
732            }
733            (field_decl, None) => {
734                self.seen_fields.insert(field_name, field_decl);
735            }
736        }
737    }
738}
739
740fn lower_variant<'tcx>(
741    tcx: TyCtxt<'tcx>,
742    variant_did: Option<LocalDefId>,
743    ident: Ident,
744    discr: ty::VariantDiscr,
745    def: &hir::VariantData<'tcx>,
746    adt_kind: ty::AdtKind,
747    parent_did: LocalDefId,
748) -> ty::VariantDef {
749    let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
750    let fields = def
751        .fields()
752        .iter()
753        .inspect(|field| {
754            field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
755        })
756        .map(|f| ty::FieldDef {
757            did: f.def_id.to_def_id(),
758            name: f.ident.name,
759            vis: tcx.visibility(f.def_id),
760            safety: f.safety,
761            value: f.default.map(|v| v.def_id.to_def_id()),
762        })
763        .collect();
764    let recovered = match def {
765        hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
766        _ => None,
767    };
768    ty::VariantDef::new(
769        ident.name,
770        variant_did.map(LocalDefId::to_def_id),
771        def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
772        discr,
773        fields,
774        parent_did.to_def_id(),
775        recovered,
776        adt_kind == AdtKind::Struct
777            && find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
778            || variant_did.is_some_and(|variant_did| {
779                find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
780            }),
781    )
782}
783
784fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
785    use rustc_hir::*;
786
787    let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
788        bug!("expected ADT to be an item");
789    };
790
791    let repr = tcx.repr_options_of_def(def_id);
792    let (kind, variants) = match &item.kind {
793        ItemKind::Enum(_, _, def) => {
794            let mut distance_from_explicit = 0;
795            let variants = def
796                .variants
797                .iter()
798                .map(|v| {
799                    let discr = if let Some(e) = &v.disr_expr {
800                        distance_from_explicit = 0;
801                        ty::VariantDiscr::Explicit(e.def_id.to_def_id())
802                    } else {
803                        ty::VariantDiscr::Relative(distance_from_explicit)
804                    };
805                    distance_from_explicit += 1;
806
807                    lower_variant(
808                        tcx,
809                        Some(v.def_id),
810                        v.ident,
811                        discr,
812                        &v.data,
813                        AdtKind::Enum,
814                        def_id,
815                    )
816                })
817                .collect();
818
819            (AdtKind::Enum, variants)
820        }
821        ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
822            let adt_kind = match item.kind {
823                ItemKind::Struct(..) => AdtKind::Struct,
824                _ => AdtKind::Union,
825            };
826            let variants = std::iter::once(lower_variant(
827                tcx,
828                None,
829                *ident,
830                ty::VariantDiscr::Relative(0),
831                def,
832                adt_kind,
833                def_id,
834            ))
835            .collect();
836
837            (adt_kind, variants)
838        }
839        _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
840    };
841    tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
842}
843
844fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
845    let item = tcx.hir_expect_item(def_id);
846
847    let (is_alias, is_auto, safety, items) = match item.kind {
848        hir::ItemKind::Trait(is_auto, safety, .., items) => {
849            (false, is_auto == hir::IsAuto::Yes, safety, items)
850        }
851        hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
852        _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
853    };
854
855    // Only regular traits can be const.
856    let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
857        hir::Constness::Const
858    } else {
859        hir::Constness::NotConst
860    };
861
862    let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
863    if paren_sugar && !tcx.features().unboxed_closures() {
864        tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
865    }
866
867    // Only regular traits can be marker.
868    let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
869
870    let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
871    let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
872
873    let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
874        tcx.get_all_attrs(def_id),
875        AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
876    )
877    .unwrap_or([false; 2]);
878
879    let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
880        ty::trait_def::TraitSpecializationKind::Marker
881    } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
882        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
883    } else {
884        ty::trait_def::TraitSpecializationKind::None
885    };
886    let must_implement_one_of = tcx
887        .get_attr(def_id, sym::rustc_must_implement_one_of)
888        // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
889        // and that they are all identifiers
890        .and_then(|attr| match attr.meta_item_list() {
891            Some(items) if items.len() < 2 => {
892                tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
893
894                None
895            }
896            Some(items) => items
897                .into_iter()
898                .map(|item| item.ident().ok_or(item.span()))
899                .collect::<Result<Box<[_]>, _>>()
900                .map_err(|span| {
901                    tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
902                })
903                .ok()
904                .zip(Some(attr.span())),
905            // Error is reported by `rustc_attr!`
906            None => None,
907        })
908        // Check that all arguments of `#[rustc_must_implement_one_of]` reference
909        // functions in the trait with default implementations
910        .and_then(|(list, attr_span)| {
911            let errors = list.iter().filter_map(|ident| {
912                let item = items.iter().find(|item| item.ident == *ident);
913
914                match item {
915                    Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
916                        if !tcx.defaultness(item.id.owner_id).has_value() {
917                            tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
918                                span: item.span,
919                                note_span: attr_span,
920                            });
921
922                            return Some(());
923                        }
924
925                        return None;
926                    }
927                    Some(item) => {
928                        tcx.dcx().emit_err(errors::MustImplementNotFunction {
929                            span: item.span,
930                            span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
931                            note: errors::MustImplementNotFunctionNote {},
932                        });
933                    }
934                    None => {
935                        tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
936                    }
937                }
938
939                Some(())
940            });
941
942            (errors.count() == 0).then_some(list)
943        })
944        // Check for duplicates
945        .and_then(|list| {
946            let mut set: UnordMap<Symbol, Span> = Default::default();
947            let mut no_dups = true;
948
949            for ident in &*list {
950                if let Some(dup) = set.insert(ident.name, ident.span) {
951                    tcx.dcx()
952                        .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
953
954                    no_dups = false;
955                }
956            }
957
958            no_dups.then_some(list)
959        });
960
961    let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
962    let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
963
964    ty::TraitDef {
965        def_id: def_id.to_def_id(),
966        safety,
967        constness,
968        paren_sugar,
969        has_auto_impl: is_auto,
970        is_marker,
971        is_coinductive: rustc_coinductive || is_auto,
972        is_fundamental,
973        skip_array_during_method_dispatch,
974        skip_boxed_slice_during_method_dispatch,
975        specialization_kind,
976        must_implement_one_of,
977        implement_via_object,
978        deny_explicit_impl,
979    }
980}
981
982#[instrument(level = "debug", skip(tcx), ret)]
983fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
984    use rustc_hir::Node::*;
985    use rustc_hir::*;
986
987    let hir_id = tcx.local_def_id_to_hir_id(def_id);
988
989    let icx = ItemCtxt::new(tcx, def_id);
990
991    let output = match tcx.hir_node(hir_id) {
992        TraitItem(hir::TraitItem {
993            kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
994            generics,
995            ..
996        })
997        | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
998            lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
999        }
1000
1001        ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
1002            // Do not try to infer the return type for a impl method coming from a trait
1003            if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1004                && i.of_trait.is_some()
1005            {
1006                icx.lowerer().lower_fn_ty(
1007                    hir_id,
1008                    sig.header.safety(),
1009                    sig.header.abi,
1010                    sig.decl,
1011                    Some(generics),
1012                    None,
1013                )
1014            } else {
1015                lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1016            }
1017        }
1018
1019        TraitItem(hir::TraitItem {
1020            kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1021            generics,
1022            ..
1023        }) => icx.lowerer().lower_fn_ty(
1024            hir_id,
1025            header.safety(),
1026            header.abi,
1027            decl,
1028            Some(generics),
1029            None,
1030        ),
1031
1032        ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1033            let abi = tcx.hir_get_foreign_abi(hir_id);
1034            compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1035        }
1036
1037        Ctor(data) => {
1038            assert_matches!(data.ctor(), Some(_));
1039            let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1040            let ty = tcx.type_of(adt_def_id).instantiate_identity();
1041            let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1042            // constructors for structs with `layout_scalar_valid_range` are unsafe to call
1043            let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1044                (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1045                _ => hir::Safety::Unsafe,
1046            };
1047            ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1048        }
1049
1050        Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1051            // Closure signatures are not like other function
1052            // signatures and cannot be accessed through `fn_sig`. For
1053            // example, a closure signature excludes the `self`
1054            // argument. In any case they are embedded within the
1055            // closure type as part of the `ClosureArgs`.
1056            //
1057            // To get the signature of a closure, you should use the
1058            // `sig` method on the `ClosureArgs`:
1059            //
1060            //    args.as_closure().sig(def_id, tcx)
1061            bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1062        }
1063
1064        x => {
1065            bug!("unexpected sort of node in fn_sig(): {:?}", x);
1066        }
1067    };
1068    ty::EarlyBinder::bind(output)
1069}
1070
1071fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1072    icx: &ItemCtxt<'tcx>,
1073    sig: &'tcx hir::FnSig<'tcx>,
1074    generics: &'tcx hir::Generics<'tcx>,
1075    def_id: LocalDefId,
1076) -> ty::PolyFnSig<'tcx> {
1077    if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1078        return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1079    }
1080
1081    icx.lowerer().lower_fn_ty(
1082        icx.tcx().local_def_id_to_hir_id(def_id),
1083        sig.header.safety(),
1084        sig.header.abi,
1085        sig.decl,
1086        Some(generics),
1087        None,
1088    )
1089}
1090
1091fn recover_infer_ret_ty<'tcx>(
1092    icx: &ItemCtxt<'tcx>,
1093    infer_ret_ty: &'tcx hir::Ty<'tcx>,
1094    generics: &'tcx hir::Generics<'tcx>,
1095    def_id: LocalDefId,
1096) -> ty::PolyFnSig<'tcx> {
1097    let tcx = icx.tcx;
1098    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1099
1100    let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1101
1102    // Typeck doesn't expect erased regions to be returned from `type_of`.
1103    // This is a heuristic approach. If the scope has region parameters,
1104    // we should change fn_sig's lifetime from `ReErased` to `ReError`,
1105    // otherwise to `ReStatic`.
1106    let has_region_params = generics.params.iter().any(|param| match param.kind {
1107        GenericParamKind::Lifetime { .. } => true,
1108        _ => false,
1109    });
1110    let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1111        ty::ReErased => {
1112            if has_region_params {
1113                ty::Region::new_error_with_message(
1114                    tcx,
1115                    DUMMY_SP,
1116                    "erased region is not allowed here in return type",
1117                )
1118            } else {
1119                tcx.lifetimes.re_static
1120            }
1121        }
1122        _ => r,
1123    });
1124
1125    let mut visitor = HirPlaceholderCollector::default();
1126    visitor.visit_ty_unambig(infer_ret_ty);
1127
1128    let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1129    let ret_ty = fn_sig.output();
1130
1131    // Don't leak types into signatures unless they're nameable!
1132    // For example, if a function returns itself, we don't want that
1133    // recursive function definition to leak out into the fn sig.
1134    let mut recovered_ret_ty = None;
1135    if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1136        diag.span_suggestion(
1137            infer_ret_ty.span,
1138            "replace with the correct return type",
1139            suggestable_ret_ty,
1140            Applicability::MachineApplicable,
1141        );
1142        recovered_ret_ty = Some(suggestable_ret_ty);
1143    } else if let Some(sugg) = suggest_impl_trait(
1144        &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1145        tcx.param_env(def_id),
1146        ret_ty,
1147    ) {
1148        diag.span_suggestion(
1149            infer_ret_ty.span,
1150            "replace with an appropriate return type",
1151            sugg,
1152            Applicability::MachineApplicable,
1153        );
1154    } else if ret_ty.is_closure() {
1155        diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1156    }
1157
1158    // Also note how `Fn` traits work just in case!
1159    if ret_ty.is_closure() {
1160        diag.note(
1161            "for more information on `Fn` traits and closure types, see \
1162                     https://doc.rust-lang.org/book/ch13-01-closures.html",
1163        );
1164    }
1165    let guar = diag.emit();
1166    ty::Binder::dummy(tcx.mk_fn_sig(
1167        fn_sig.inputs().iter().copied(),
1168        recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1169        fn_sig.c_variadic,
1170        fn_sig.safety,
1171        fn_sig.abi,
1172    ))
1173}
1174
1175pub fn suggest_impl_trait<'tcx>(
1176    infcx: &InferCtxt<'tcx>,
1177    param_env: ty::ParamEnv<'tcx>,
1178    ret_ty: Ty<'tcx>,
1179) -> Option<String> {
1180    let format_as_assoc: fn(_, _, _, _, _) -> _ =
1181        |tcx: TyCtxt<'tcx>,
1182         _: ty::GenericArgsRef<'tcx>,
1183         trait_def_id: DefId,
1184         assoc_item_def_id: DefId,
1185         item_ty: Ty<'tcx>| {
1186            let trait_name = tcx.item_name(trait_def_id);
1187            let assoc_name = tcx.item_name(assoc_item_def_id);
1188            Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1189        };
1190    let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1191        |tcx: TyCtxt<'tcx>,
1192         args: ty::GenericArgsRef<'tcx>,
1193         trait_def_id: DefId,
1194         _: DefId,
1195         item_ty: Ty<'tcx>| {
1196            let trait_name = tcx.item_name(trait_def_id);
1197            let args_tuple = args.type_at(1);
1198            let ty::Tuple(types) = *args_tuple.kind() else {
1199                return None;
1200            };
1201            let types = types.make_suggestable(tcx, false, None)?;
1202            let maybe_ret =
1203                if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1204            Some(format!(
1205                "impl {trait_name}({}){maybe_ret}",
1206                types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1207            ))
1208        };
1209
1210    for (trait_def_id, assoc_item_def_id, formatter) in [
1211        (
1212            infcx.tcx.get_diagnostic_item(sym::Iterator),
1213            infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1214            format_as_assoc,
1215        ),
1216        (
1217            infcx.tcx.lang_items().future_trait(),
1218            infcx.tcx.lang_items().future_output(),
1219            format_as_assoc,
1220        ),
1221        (
1222            infcx.tcx.lang_items().fn_trait(),
1223            infcx.tcx.lang_items().fn_once_output(),
1224            format_as_parenthesized,
1225        ),
1226        (
1227            infcx.tcx.lang_items().fn_mut_trait(),
1228            infcx.tcx.lang_items().fn_once_output(),
1229            format_as_parenthesized,
1230        ),
1231        (
1232            infcx.tcx.lang_items().fn_once_trait(),
1233            infcx.tcx.lang_items().fn_once_output(),
1234            format_as_parenthesized,
1235        ),
1236    ] {
1237        let Some(trait_def_id) = trait_def_id else {
1238            continue;
1239        };
1240        let Some(assoc_item_def_id) = assoc_item_def_id else {
1241            continue;
1242        };
1243        if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1244            continue;
1245        }
1246        let sugg = infcx.probe(|_| {
1247            let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1248                if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1249            });
1250            if !infcx
1251                .type_implements_trait(trait_def_id, args, param_env)
1252                .must_apply_modulo_regions()
1253            {
1254                return None;
1255            }
1256            let ocx = ObligationCtxt::new(&infcx);
1257            let item_ty = ocx.normalize(
1258                &ObligationCause::dummy(),
1259                param_env,
1260                Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1261            );
1262            // FIXME(compiler-errors): We may benefit from resolving regions here.
1263            if ocx.select_where_possible().is_empty()
1264                && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1265                && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1266                && let Some(sugg) = formatter(
1267                    infcx.tcx,
1268                    infcx.resolve_vars_if_possible(args),
1269                    trait_def_id,
1270                    assoc_item_def_id,
1271                    item_ty,
1272                )
1273            {
1274                return Some(sugg);
1275            }
1276
1277            None
1278        });
1279
1280        if sugg.is_some() {
1281            return sugg;
1282        }
1283    }
1284    None
1285}
1286
1287fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
1288    let icx = ItemCtxt::new(tcx, def_id);
1289    let item = tcx.hir_expect_item(def_id);
1290    let impl_ = item.expect_impl();
1291    impl_.of_trait.as_ref().map(|ast_trait_ref| {
1292        let selfty = tcx.type_of(def_id).instantiate_identity();
1293
1294        check_impl_constness(tcx, impl_.constness, ast_trait_ref);
1295
1296        let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
1297
1298        ty::ImplTraitHeader {
1299            trait_ref: ty::EarlyBinder::bind(trait_ref),
1300            safety: impl_.safety,
1301            polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
1302            constness: impl_.constness,
1303        }
1304    })
1305}
1306
1307fn check_impl_constness(
1308    tcx: TyCtxt<'_>,
1309    constness: hir::Constness,
1310    hir_trait_ref: &hir::TraitRef<'_>,
1311) {
1312    if let hir::Constness::NotConst = constness {
1313        return;
1314    }
1315
1316    let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1317    if tcx.is_const_trait(trait_def_id) {
1318        return;
1319    }
1320
1321    let trait_name = tcx.item_name(trait_def_id).to_string();
1322    let (local_trait_span, suggestion_pre) =
1323        match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1324            (true, true) => (
1325                Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1326                if tcx.features().const_trait_impl() {
1327                    ""
1328                } else {
1329                    "enable `#![feature(const_trait_impl)]` in your crate and "
1330                },
1331            ),
1332            (false, _) | (_, false) => (None, ""),
1333        };
1334    tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1335        trait_ref_span: hir_trait_ref.path.span,
1336        trait_name,
1337        local_trait_span,
1338        suggestion_pre,
1339        marking: (),
1340        adding: (),
1341    });
1342}
1343
1344fn polarity_of_impl(
1345    tcx: TyCtxt<'_>,
1346    def_id: LocalDefId,
1347    impl_: &hir::Impl<'_>,
1348    span: Span,
1349) -> ty::ImplPolarity {
1350    let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1351    match &impl_ {
1352        hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
1353            if is_rustc_reservation {
1354                let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
1355                tcx.dcx().span_err(span, "reservation impls can't be negative");
1356            }
1357            ty::ImplPolarity::Negative
1358        }
1359        hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
1360            if is_rustc_reservation {
1361                tcx.dcx().span_err(span, "reservation impls can't be inherent");
1362            }
1363            ty::ImplPolarity::Positive
1364        }
1365        hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
1366            if is_rustc_reservation {
1367                ty::ImplPolarity::Reservation
1368            } else {
1369                ty::ImplPolarity::Positive
1370            }
1371        }
1372    }
1373}
1374
1375/// Returns the early-bound lifetimes declared in this generics
1376/// listing. For anything other than fns/methods, this is just all
1377/// the lifetimes that are declared. For fns or methods, we have to
1378/// screen out those that do not appear in any where-clauses etc using
1379/// `resolve_lifetime::early_bound_lifetimes`.
1380fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1381    tcx: TyCtxt<'tcx>,
1382    generics: &'a hir::Generics<'a>,
1383) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1384    generics.params.iter().filter(move |param| match param.kind {
1385        GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1386        _ => false,
1387    })
1388}
1389
1390fn compute_sig_of_foreign_fn_decl<'tcx>(
1391    tcx: TyCtxt<'tcx>,
1392    def_id: LocalDefId,
1393    decl: &'tcx hir::FnDecl<'tcx>,
1394    abi: ExternAbi,
1395    safety: hir::Safety,
1396) -> ty::PolyFnSig<'tcx> {
1397    let hir_id = tcx.local_def_id_to_hir_id(def_id);
1398    let fty =
1399        ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1400
1401    // Feature gate SIMD types in FFI, since I am not sure that the
1402    // ABIs are handled at all correctly. -huonw
1403    if !tcx.features().simd_ffi() {
1404        let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1405            if ty.is_simd() {
1406                let snip = tcx
1407                    .sess
1408                    .source_map()
1409                    .span_to_snippet(hir_ty.span)
1410                    .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
1411                tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1412            }
1413        };
1414        for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1415            check(input, *ty)
1416        }
1417        if let hir::FnRetTy::Return(ty) = decl.output {
1418            check(ty, fty.output().skip_binder())
1419        }
1420    }
1421
1422    fty
1423}
1424
1425fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1426    match tcx.hir_node_by_def_id(def_id) {
1427        Node::Expr(&hir::Expr {
1428            kind:
1429                hir::ExprKind::Closure(&rustc_hir::Closure {
1430                    kind: hir::ClosureKind::Coroutine(kind),
1431                    ..
1432                }),
1433            ..
1434        }) => Some(kind),
1435        _ => None,
1436    }
1437}
1438
1439fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1440    let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1441        tcx.hir_node_by_def_id(def_id).expect_closure()
1442    else {
1443        bug!()
1444    };
1445
1446    let &hir::Expr {
1447        kind:
1448            hir::ExprKind::Closure(&rustc_hir::Closure {
1449                def_id,
1450                kind: hir::ClosureKind::Coroutine(_),
1451                ..
1452            }),
1453        ..
1454    } = tcx.hir_body(body).value
1455    else {
1456        bug!()
1457    };
1458
1459    def_id.to_def_id()
1460}
1461
1462fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1463    match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1464        hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1465            hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1466        }
1467        hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1468            hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1469        }
1470        hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1471            hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1472        }
1473    }
1474}
1475
1476fn rendered_precise_capturing_args<'tcx>(
1477    tcx: TyCtxt<'tcx>,
1478    def_id: LocalDefId,
1479) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1480    if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1481        tcx.opt_rpitit_info(def_id.to_def_id())
1482    {
1483        return tcx.rendered_precise_capturing_args(opaque_def_id);
1484    }
1485
1486    tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1487        hir::GenericBound::Use(args, ..) => {
1488            Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1489                PreciseCapturingArgKind::Lifetime(_) => {
1490                    PreciseCapturingArgKind::Lifetime(arg.name())
1491                }
1492                PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1493            })))
1494        }
1495        _ => None,
1496    })
1497}
1498
1499fn const_param_default<'tcx>(
1500    tcx: TyCtxt<'tcx>,
1501    def_id: LocalDefId,
1502) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1503    let default_ct = match tcx.hir_node_by_def_id(def_id) {
1504        hir::Node::GenericParam(hir::GenericParam {
1505            kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1506            ..
1507        }) => ct,
1508        _ => span_bug!(
1509            tcx.def_span(def_id),
1510            "`const_param_default` expected a generic parameter with a constant"
1511        ),
1512    };
1513    let icx = ItemCtxt::new(tcx, def_id);
1514    let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1515    let ct = icx
1516        .lowerer()
1517        .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1518    ty::EarlyBinder::bind(ct)
1519}
1520
1521fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1522    let hir_id = tcx.local_def_id_to_hir_id(def);
1523    let const_arg_id = tcx.parent_hir_id(hir_id);
1524    match tcx.hir_node(const_arg_id) {
1525        hir::Node::ConstArg(_) => {
1526            if tcx.features().generic_const_exprs() {
1527                ty::AnonConstKind::GCE
1528            } else if tcx.features().min_generic_const_args() {
1529                ty::AnonConstKind::MCG
1530            } else if let hir::Node::Expr(hir::Expr {
1531                kind: hir::ExprKind::Repeat(_, repeat_count),
1532                ..
1533            }) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
1534                && repeat_count.hir_id == const_arg_id
1535            {
1536                ty::AnonConstKind::RepeatExprCount
1537            } else {
1538                ty::AnonConstKind::MCG
1539            }
1540        }
1541        _ => ty::AnonConstKind::NonTypeSystem,
1542    }
1543}