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