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