• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 use crate::astconv::AstConv;
18 use crate::check::intrinsic::intrinsic_operation_unsafety;
19 use crate::errors;
20 use hir::def::DefKind;
21 use rustc_data_structures::captures::Captures;
22 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
23 use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
24 use rustc_hir as hir;
25 use rustc_hir::def_id::{DefId, LocalDefId};
26 use rustc_hir::intravisit::{self, Visitor};
27 use rustc_hir::{GenericParamKind, Node};
28 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
29 use rustc_infer::traits::ObligationCause;
30 use rustc_middle::hir::nested_filter;
31 use rustc_middle::query::Providers;
32 use rustc_middle::ty::util::{Discr, IntTypeExt};
33 use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, ToPredicate, Ty, TyCtxt};
34 use rustc_span::symbol::{kw, sym, Ident, Symbol};
35 use rustc_span::Span;
36 use rustc_target::spec::abi;
37 use rustc_trait_selection::infer::InferCtxtExt;
38 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
39 use rustc_trait_selection::traits::ObligationCtxt;
40 use std::iter;
41 
42 mod generics_of;
43 mod item_bounds;
44 mod predicates_of;
45 mod resolve_bound_vars;
46 mod type_of;
47 
48 ///////////////////////////////////////////////////////////////////////////
49 // Main entry point
50 
collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId)51 fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
52     tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
53 }
54 
provide(providers: &mut Providers)55 pub fn provide(providers: &mut Providers) {
56     resolve_bound_vars::provide(providers);
57     *providers = Providers {
58         type_of: type_of::type_of,
59         item_bounds: item_bounds::item_bounds,
60         explicit_item_bounds: item_bounds::explicit_item_bounds,
61         generics_of: generics_of::generics_of,
62         predicates_of: predicates_of::predicates_of,
63         predicates_defined_on,
64         explicit_predicates_of: predicates_of::explicit_predicates_of,
65         super_predicates_of: predicates_of::super_predicates_of,
66         implied_predicates_of: predicates_of::implied_predicates_of,
67         super_predicates_that_define_assoc_item:
68             predicates_of::super_predicates_that_define_assoc_item,
69         trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
70         type_param_predicates: predicates_of::type_param_predicates,
71         trait_def,
72         adt_def,
73         fn_sig,
74         impl_trait_ref,
75         impl_polarity,
76         generator_kind,
77         collect_mod_item_types,
78         is_type_alias_impl_trait,
79         ..*providers
80     };
81 }
82 
83 ///////////////////////////////////////////////////////////////////////////
84 
85 /// Context specific to some particular item. This is what implements
86 /// [`AstConv`].
87 ///
88 /// # `ItemCtxt` vs `FnCtxt`
89 ///
90 /// `ItemCtxt` is primarily used to type-check item signatures and lower them
91 /// from HIR to their [`ty::Ty`] representation, which is exposed using [`AstConv`].
92 /// It's also used for the bodies of items like structs where the body (the fields)
93 /// are just signatures.
94 ///
95 /// This is in contrast to `FnCtxt`, which is used to type-check bodies of
96 /// functions, closures, and `const`s -- anywhere that expressions and statements show up.
97 ///
98 /// An important thing to note is that `ItemCtxt` does no inference -- it has no [`InferCtxt`] --
99 /// while `FnCtxt` does do inference.
100 ///
101 /// [`InferCtxt`]: rustc_infer::infer::InferCtxt
102 ///
103 /// # Trait predicates
104 ///
105 /// `ItemCtxt` has information about the predicates that are defined
106 /// on the trait. Unfortunately, this predicate information is
107 /// available in various different forms at various points in the
108 /// process. So we can't just store a pointer to e.g., the AST or the
109 /// parsed ty form, we have to be more flexible. To this end, the
110 /// `ItemCtxt` is parameterized by a `DefId` that it uses to satisfy
111 /// `get_type_parameter_bounds` requests, drawing the information from
112 /// the AST (`hir::Generics`), recursively.
113 pub struct ItemCtxt<'tcx> {
114     tcx: TyCtxt<'tcx>,
115     item_def_id: LocalDefId,
116 }
117 
118 ///////////////////////////////////////////////////////////////////////////
119 
120 #[derive(Default)]
121 pub(crate) struct HirPlaceholderCollector(pub(crate) Vec<Span>);
122 
123 impl<'v> Visitor<'v> for HirPlaceholderCollector {
visit_ty(&mut self, t: &'v hir::Ty<'v>)124     fn visit_ty(&mut self, t: &'v hir::Ty<'v>) {
125         if let hir::TyKind::Infer = t.kind {
126             self.0.push(t.span);
127         }
128         intravisit::walk_ty(self, t)
129     }
visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>)130     fn visit_generic_arg(&mut self, generic_arg: &'v hir::GenericArg<'v>) {
131         match generic_arg {
132             hir::GenericArg::Infer(inf) => {
133                 self.0.push(inf.span);
134                 intravisit::walk_inf(self, inf);
135             }
136             hir::GenericArg::Type(t) => self.visit_ty(t),
137             _ => {}
138         }
139     }
visit_array_length(&mut self, length: &'v hir::ArrayLen)140     fn visit_array_length(&mut self, length: &'v hir::ArrayLen) {
141         if let &hir::ArrayLen::Infer(_, span) = length {
142             self.0.push(span);
143         }
144         intravisit::walk_array_len(self, length)
145     }
146 }
147 
148 struct CollectItemTypesVisitor<'tcx> {
149     tcx: TyCtxt<'tcx>,
150 }
151 
152 /// If there are any placeholder types (`_`), emit an error explaining that this is not allowed
153 /// and suggest adding type parameters in the appropriate place, taking into consideration any and
154 /// all already existing generic type parameters to avoid suggesting a name that is already in use.
placeholder_type_error<'tcx>( tcx: TyCtxt<'tcx>, generics: Option<&hir::Generics<'_>>, placeholder_types: Vec<Span>, suggest: bool, hir_ty: Option<&hir::Ty<'_>>, kind: &'static str, )155 pub(crate) fn placeholder_type_error<'tcx>(
156     tcx: TyCtxt<'tcx>,
157     generics: Option<&hir::Generics<'_>>,
158     placeholder_types: Vec<Span>,
159     suggest: bool,
160     hir_ty: Option<&hir::Ty<'_>>,
161     kind: &'static str,
162 ) {
163     if placeholder_types.is_empty() {
164         return;
165     }
166 
167     placeholder_type_error_diag(tcx, generics, placeholder_types, vec![], suggest, hir_ty, kind)
168         .emit();
169 }
170 
placeholder_type_error_diag<'tcx>( tcx: TyCtxt<'tcx>, generics: Option<&hir::Generics<'_>>, placeholder_types: Vec<Span>, additional_spans: Vec<Span>, suggest: bool, hir_ty: Option<&hir::Ty<'_>>, kind: &'static str, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>171 pub(crate) fn placeholder_type_error_diag<'tcx>(
172     tcx: TyCtxt<'tcx>,
173     generics: Option<&hir::Generics<'_>>,
174     placeholder_types: Vec<Span>,
175     additional_spans: Vec<Span>,
176     suggest: bool,
177     hir_ty: Option<&hir::Ty<'_>>,
178     kind: &'static str,
179 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
180     if placeholder_types.is_empty() {
181         return bad_placeholder(tcx, additional_spans, kind);
182     }
183 
184     let params = generics.map(|g| g.params).unwrap_or_default();
185     let type_name = params.next_type_param_name(None);
186     let mut sugg: Vec<_> =
187         placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
188 
189     if let Some(generics) = generics {
190         if let Some(arg) = params.iter().find(|arg| {
191             matches!(arg.name, hir::ParamName::Plain(Ident { name: kw::Underscore, .. }))
192         }) {
193             // Account for `_` already present in cases like `struct S<_>(_);` and suggest
194             // `struct S<T>(T);` instead of `struct S<_, T>(T);`.
195             sugg.push((arg.span, (*type_name).to_string()));
196         } else if let Some(span) = generics.span_for_param_suggestion() {
197             // Account for bounds, we want `fn foo<T: E, K>(_: K)` not `fn foo<T, K: E>(_: K)`.
198             sugg.push((span, format!(", {}", type_name)));
199         } else {
200             sugg.push((generics.span, format!("<{}>", type_name)));
201         }
202     }
203 
204     let mut err =
205         bad_placeholder(tcx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
206 
207     // Suggest, but only if it is not a function in const or static
208     if suggest {
209         let mut is_fn = false;
210         let mut is_const_or_static = false;
211 
212         if let Some(hir_ty) = hir_ty && let hir::TyKind::BareFn(_) = hir_ty.kind {
213             is_fn = true;
214 
215             // Check if parent is const or static
216             let parent_id = tcx.hir().parent_id(hir_ty.hir_id);
217             let parent_node = tcx.hir().get(parent_id);
218 
219             is_const_or_static = matches!(
220                 parent_node,
221                 Node::Item(&hir::Item {
222                     kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
223                     ..
224                 }) | Node::TraitItem(&hir::TraitItem {
225                     kind: hir::TraitItemKind::Const(..),
226                     ..
227                 }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
228             );
229         }
230 
231         // if function is wrapped around a const or static,
232         // then don't show the suggestion
233         if !(is_fn && is_const_or_static) {
234             err.multipart_suggestion(
235                 "use type parameters instead",
236                 sugg,
237                 Applicability::HasPlaceholders,
238             );
239         }
240     }
241 
242     err
243 }
244 
reject_placeholder_type_signatures_in_item<'tcx>( tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>, )245 fn reject_placeholder_type_signatures_in_item<'tcx>(
246     tcx: TyCtxt<'tcx>,
247     item: &'tcx hir::Item<'tcx>,
248 ) {
249     let (generics, suggest) = match &item.kind {
250         hir::ItemKind::Union(_, generics)
251         | hir::ItemKind::Enum(_, generics)
252         | hir::ItemKind::TraitAlias(generics, _)
253         | hir::ItemKind::Trait(_, _, generics, ..)
254         | hir::ItemKind::Impl(hir::Impl { generics, .. })
255         | hir::ItemKind::Struct(_, generics) => (generics, true),
256         hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. })
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     placeholder_type_error(tcx, Some(generics), visitor.0, suggest, None, item.kind.descr());
266 }
267 
268 impl<'tcx> Visitor<'tcx> for CollectItemTypesVisitor<'tcx> {
269     type NestedFilter = nested_filter::OnlyBodies;
270 
nested_visit_map(&mut self) -> Self::Map271     fn nested_visit_map(&mut self) -> Self::Map {
272         self.tcx.hir()
273     }
274 
visit_item(&mut self, item: &'tcx hir::Item<'tcx>)275     fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
276         convert_item(self.tcx, item.item_id());
277         reject_placeholder_type_signatures_in_item(self.tcx, item);
278         intravisit::walk_item(self, item);
279     }
280 
visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>)281     fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
282         for param in generics.params {
283             match param.kind {
284                 hir::GenericParamKind::Lifetime { .. } => {}
285                 hir::GenericParamKind::Type { default: Some(_), .. } => {
286                     self.tcx.ensure().type_of(param.def_id);
287                 }
288                 hir::GenericParamKind::Type { .. } => {}
289                 hir::GenericParamKind::Const { default, .. } => {
290                     self.tcx.ensure().type_of(param.def_id);
291                     if let Some(default) = default {
292                         // need to store default and type of default
293                         self.tcx.ensure().type_of(default.def_id);
294                         self.tcx.ensure().const_param_default(param.def_id);
295                     }
296                 }
297             }
298         }
299         intravisit::walk_generics(self, generics);
300     }
301 
visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>)302     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
303         if let hir::ExprKind::Closure(closure) = expr.kind {
304             self.tcx.ensure().generics_of(closure.def_id);
305             self.tcx.ensure().codegen_fn_attrs(closure.def_id);
306             // We do not call `type_of` for closures here as that
307             // depends on typecheck and would therefore hide
308             // any further errors in case one typeck fails.
309         }
310         intravisit::walk_expr(self, expr);
311     }
312 
visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>)313     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
314         convert_trait_item(self.tcx, trait_item.trait_item_id());
315         intravisit::walk_trait_item(self, trait_item);
316     }
317 
visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>)318     fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
319         convert_impl_item(self.tcx, impl_item.impl_item_id());
320         intravisit::walk_impl_item(self, impl_item);
321     }
322 }
323 
324 ///////////////////////////////////////////////////////////////////////////
325 // Utility types and common code for the above passes.
326 
bad_placeholder<'tcx>( tcx: TyCtxt<'tcx>, mut spans: Vec<Span>, kind: &'static str, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed>327 fn bad_placeholder<'tcx>(
328     tcx: TyCtxt<'tcx>,
329     mut spans: Vec<Span>,
330     kind: &'static str,
331 ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
332     let kind = if kind.ends_with('s') { format!("{}es", kind) } else { format!("{}s", kind) };
333 
334     spans.sort();
335     tcx.sess.create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
336 }
337 
338 impl<'tcx> ItemCtxt<'tcx> {
new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx>339     pub fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
340         ItemCtxt { tcx, item_def_id }
341     }
342 
to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx>343     pub fn to_ty(&self, ast_ty: &hir::Ty<'_>) -> Ty<'tcx> {
344         self.astconv().ast_ty_to_ty(ast_ty)
345     }
346 
hir_id(&self) -> hir::HirId347     pub fn hir_id(&self) -> hir::HirId {
348         self.tcx.hir().local_def_id_to_hir_id(self.item_def_id)
349     }
350 
node(&self) -> hir::Node<'tcx>351     pub fn node(&self) -> hir::Node<'tcx> {
352         self.tcx.hir().get(self.hir_id())
353     }
354 }
355 
356 impl<'tcx> AstConv<'tcx> for ItemCtxt<'tcx> {
tcx(&self) -> TyCtxt<'tcx>357     fn tcx(&self) -> TyCtxt<'tcx> {
358         self.tcx
359     }
360 
item_def_id(&self) -> DefId361     fn item_def_id(&self) -> DefId {
362         self.item_def_id.to_def_id()
363     }
364 
get_type_parameter_bounds( &self, span: Span, def_id: LocalDefId, assoc_name: Ident, ) -> ty::GenericPredicates<'tcx>365     fn get_type_parameter_bounds(
366         &self,
367         span: Span,
368         def_id: LocalDefId,
369         assoc_name: Ident,
370     ) -> ty::GenericPredicates<'tcx> {
371         self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_name))
372     }
373 
re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>>374     fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option<ty::Region<'tcx>> {
375         None
376     }
377 
allow_ty_infer(&self) -> bool378     fn allow_ty_infer(&self) -> bool {
379         false
380     }
381 
ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>382     fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
383         Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
384     }
385 
ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>386     fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
387         let ty = self.tcx.fold_regions(ty, |r, _| match *r {
388             // This is never reached in practice. If it ever is reached,
389             // `ReErased` should be changed to `ReStatic`, and any other region
390             // left alone.
391             r => bug!("unexpected region: {r:?}"),
392         });
393         ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant")
394     }
395 
projected_ty_from_poly_trait_ref( &self, span: Span, item_def_id: DefId, item_segment: &hir::PathSegment<'_>, poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>396     fn projected_ty_from_poly_trait_ref(
397         &self,
398         span: Span,
399         item_def_id: DefId,
400         item_segment: &hir::PathSegment<'_>,
401         poly_trait_ref: ty::PolyTraitRef<'tcx>,
402     ) -> Ty<'tcx> {
403         if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
404             let item_substs = self.astconv().create_substs_for_associated_item(
405                 span,
406                 item_def_id,
407                 item_segment,
408                 trait_ref.substs,
409             );
410             Ty::new_projection(self.tcx(), item_def_id, item_substs)
411         } else {
412             // There are no late-bound regions; we can just ignore the binder.
413             let (mut mpart_sugg, mut inferred_sugg) = (None, None);
414             let mut bound = String::new();
415 
416             match self.node() {
417                 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
418                     let item = self
419                         .tcx
420                         .hir()
421                         .expect_item(self.tcx.hir().get_parent_item(self.hir_id()).def_id);
422                     match &item.kind {
423                         hir::ItemKind::Enum(_, generics)
424                         | hir::ItemKind::Struct(_, generics)
425                         | hir::ItemKind::Union(_, generics) => {
426                             let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
427                             let (lt_sp, sugg) = match generics.params {
428                                 [] => (generics.span, format!("<{}>", lt_name)),
429                                 [bound, ..] => {
430                                     (bound.span.shrink_to_lo(), format!("{}, ", lt_name))
431                                 }
432                             };
433                             mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
434                                 fspan: lt_sp,
435                                 first: sugg,
436                                 sspan: span.with_hi(item_segment.ident.span.lo()),
437                                 second: format!(
438                                     "{}::",
439                                     // Replace the existing lifetimes with a new named lifetime.
440                                     self.tcx.replace_late_bound_regions_uncached(
441                                         poly_trait_ref,
442                                         |_| {
443                                             ty::Region::new_early_bound(self.tcx, ty::EarlyBoundRegion {
444                                                 def_id: item_def_id,
445                                                 index: 0,
446                                                 name: Symbol::intern(&lt_name),
447                                             })
448                                         }
449                                     ),
450                                 ),
451                             });
452                         }
453                         _ => {}
454                     }
455                 }
456                 hir::Node::Item(hir::Item {
457                     kind:
458                         hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
459                     ..
460                 }) => {}
461                 hir::Node::Item(_)
462                 | hir::Node::ForeignItem(_)
463                 | hir::Node::TraitItem(_)
464                 | hir::Node::ImplItem(_) => {
465                     inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
466                     bound = format!(
467                         "{}::",
468                         // Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
469                         self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
470                     );
471                 }
472                 _ => {}
473             }
474             Ty::new_error(
475                 self.tcx(),
476                 self.tcx().sess.emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
477                     span,
478                     inferred_sugg,
479                     bound,
480                     mpart_sugg,
481                 }),
482             )
483         }
484     }
485 
probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>>486     fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
487         // FIXME(#103640): Should we handle the case where `ty` is a projection?
488         ty.ty_adt_def()
489     }
490 
set_tainted_by_errors(&self, _: ErrorGuaranteed)491     fn set_tainted_by_errors(&self, _: ErrorGuaranteed) {
492         // There's no obvious place to track this, so just let it go.
493     }
494 
record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span)495     fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
496         // There's no place to record types from signatures?
497     }
498 
infcx(&self) -> Option<&InferCtxt<'tcx>>499     fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
500         None
501     }
502 }
503 
504 /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present.
get_new_lifetime_name<'tcx>( tcx: TyCtxt<'tcx>, poly_trait_ref: ty::PolyTraitRef<'tcx>, generics: &hir::Generics<'tcx>, ) -> String505 fn get_new_lifetime_name<'tcx>(
506     tcx: TyCtxt<'tcx>,
507     poly_trait_ref: ty::PolyTraitRef<'tcx>,
508     generics: &hir::Generics<'tcx>,
509 ) -> String {
510     let existing_lifetimes = tcx
511         .collect_referenced_late_bound_regions(&poly_trait_ref)
512         .into_iter()
513         .filter_map(|lt| {
514             if let ty::BoundRegionKind::BrNamed(_, name) = lt {
515                 Some(name.as_str().to_string())
516             } else {
517                 None
518             }
519         })
520         .chain(generics.params.iter().filter_map(|param| {
521             if let hir::GenericParamKind::Lifetime { .. } = &param.kind {
522                 Some(param.name.ident().as_str().to_string())
523             } else {
524                 None
525             }
526         }))
527         .collect::<FxHashSet<String>>();
528 
529     let a_to_z_repeat_n = |n| {
530         (b'a'..=b'z').map(move |c| {
531             let mut s = '\''.to_string();
532             s.extend(std::iter::repeat(char::from(c)).take(n));
533             s
534         })
535     };
536 
537     // If all single char lifetime names are present, we wrap around and double the chars.
538     (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
539 }
540 
convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId)541 fn convert_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
542     let it = tcx.hir().item(item_id);
543     debug!("convert: item {} with id {}", it.ident, it.hir_id());
544     let def_id = item_id.owner_id.def_id;
545 
546     match &it.kind {
547         // These don't define types.
548         hir::ItemKind::ExternCrate(_)
549         | hir::ItemKind::Use(..)
550         | hir::ItemKind::Macro(..)
551         | hir::ItemKind::Mod(_)
552         | hir::ItemKind::GlobalAsm(_) => {}
553         hir::ItemKind::ForeignMod { items, .. } => {
554             for item in *items {
555                 let item = tcx.hir().foreign_item(item.id);
556                 tcx.ensure().generics_of(item.owner_id);
557                 tcx.ensure().type_of(item.owner_id);
558                 tcx.ensure().predicates_of(item.owner_id);
559                 match item.kind {
560                     hir::ForeignItemKind::Fn(..) => {
561                         tcx.ensure().codegen_fn_attrs(item.owner_id);
562                         tcx.ensure().fn_sig(item.owner_id)
563                     }
564                     hir::ForeignItemKind::Static(..) => {
565                         tcx.ensure().codegen_fn_attrs(item.owner_id);
566                         let mut visitor = HirPlaceholderCollector::default();
567                         visitor.visit_foreign_item(item);
568                         placeholder_type_error(
569                             tcx,
570                             None,
571                             visitor.0,
572                             false,
573                             None,
574                             "static variable",
575                         );
576                     }
577                     _ => (),
578                 }
579             }
580         }
581         hir::ItemKind::Enum(..) => {
582             tcx.ensure().generics_of(def_id);
583             tcx.ensure().type_of(def_id);
584             tcx.ensure().predicates_of(def_id);
585             convert_enum_variant_types(tcx, def_id.to_def_id());
586         }
587         hir::ItemKind::Impl { .. } => {
588             tcx.ensure().generics_of(def_id);
589             tcx.ensure().type_of(def_id);
590             tcx.ensure().impl_trait_ref(def_id);
591             tcx.ensure().predicates_of(def_id);
592         }
593         hir::ItemKind::Trait(..) => {
594             tcx.ensure().generics_of(def_id);
595             tcx.ensure().trait_def(def_id);
596             tcx.at(it.span).super_predicates_of(def_id);
597             tcx.ensure().predicates_of(def_id);
598         }
599         hir::ItemKind::TraitAlias(..) => {
600             tcx.ensure().generics_of(def_id);
601             tcx.at(it.span).implied_predicates_of(def_id);
602             tcx.at(it.span).super_predicates_of(def_id);
603             tcx.ensure().predicates_of(def_id);
604         }
605         hir::ItemKind::Struct(struct_def, _) | hir::ItemKind::Union(struct_def, _) => {
606             tcx.ensure().generics_of(def_id);
607             tcx.ensure().type_of(def_id);
608             tcx.ensure().predicates_of(def_id);
609 
610             for f in struct_def.fields() {
611                 tcx.ensure().generics_of(f.def_id);
612                 tcx.ensure().type_of(f.def_id);
613                 tcx.ensure().predicates_of(f.def_id);
614             }
615 
616             if let Some(ctor_def_id) = struct_def.ctor_def_id() {
617                 convert_variant_ctor(tcx, ctor_def_id);
618             }
619         }
620 
621         // Don't call `type_of` on opaque types, since that depends on type
622         // checking function bodies. `check_item_type` ensures that it's called
623         // instead.
624         hir::ItemKind::OpaqueTy(..) => {
625             tcx.ensure().generics_of(def_id);
626             tcx.ensure().predicates_of(def_id);
627             tcx.ensure().explicit_item_bounds(def_id);
628             tcx.ensure().item_bounds(def_id);
629         }
630 
631         hir::ItemKind::TyAlias(..) => {
632             tcx.ensure().generics_of(def_id);
633             tcx.ensure().type_of(def_id);
634             tcx.ensure().predicates_of(def_id);
635         }
636 
637         hir::ItemKind::Static(ty, ..) | hir::ItemKind::Const(ty, ..) => {
638             tcx.ensure().generics_of(def_id);
639             tcx.ensure().type_of(def_id);
640             tcx.ensure().predicates_of(def_id);
641             if !is_suggestable_infer_ty(ty) {
642                 let mut visitor = HirPlaceholderCollector::default();
643                 visitor.visit_item(it);
644                 placeholder_type_error(tcx, None, visitor.0, false, None, it.kind.descr());
645             }
646         }
647 
648         hir::ItemKind::Fn(..) => {
649             tcx.ensure().generics_of(def_id);
650             tcx.ensure().type_of(def_id);
651             tcx.ensure().predicates_of(def_id);
652             tcx.ensure().fn_sig(def_id);
653             tcx.ensure().codegen_fn_attrs(def_id);
654         }
655     }
656 }
657 
convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId)658 fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
659     let trait_item = tcx.hir().trait_item(trait_item_id);
660     let def_id = trait_item_id.owner_id;
661     tcx.ensure().generics_of(def_id);
662 
663     match trait_item.kind {
664         hir::TraitItemKind::Fn(..) => {
665             tcx.ensure().codegen_fn_attrs(def_id);
666             tcx.ensure().type_of(def_id);
667             tcx.ensure().fn_sig(def_id);
668         }
669 
670         hir::TraitItemKind::Const(ty, body_id) => {
671             tcx.ensure().type_of(def_id);
672             if !tcx.sess.diagnostic().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
673                 && !(is_suggestable_infer_ty(ty) && body_id.is_some())
674             {
675                 // Account for `const C: _;`.
676                 let mut visitor = HirPlaceholderCollector::default();
677                 visitor.visit_trait_item(trait_item);
678                 placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
679             }
680         }
681 
682         hir::TraitItemKind::Type(_, Some(_)) => {
683             tcx.ensure().item_bounds(def_id);
684             tcx.ensure().type_of(def_id);
685             // Account for `type T = _;`.
686             let mut visitor = HirPlaceholderCollector::default();
687             visitor.visit_trait_item(trait_item);
688             placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
689         }
690 
691         hir::TraitItemKind::Type(_, None) => {
692             tcx.ensure().item_bounds(def_id);
693             // #74612: Visit and try to find bad placeholders
694             // even if there is no concrete type.
695             let mut visitor = HirPlaceholderCollector::default();
696             visitor.visit_trait_item(trait_item);
697 
698             placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
699         }
700     };
701 
702     tcx.ensure().predicates_of(def_id);
703 }
704 
convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId)705 fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
706     let def_id = impl_item_id.owner_id;
707     tcx.ensure().generics_of(def_id);
708     tcx.ensure().type_of(def_id);
709     tcx.ensure().predicates_of(def_id);
710     let impl_item = tcx.hir().impl_item(impl_item_id);
711     match impl_item.kind {
712         hir::ImplItemKind::Fn(..) => {
713             tcx.ensure().codegen_fn_attrs(def_id);
714             tcx.ensure().fn_sig(def_id);
715         }
716         hir::ImplItemKind::Type(_) => {
717             // Account for `type T = _;`
718             let mut visitor = HirPlaceholderCollector::default();
719             visitor.visit_impl_item(impl_item);
720 
721             placeholder_type_error(tcx, None, visitor.0, false, None, "associated type");
722         }
723         hir::ImplItemKind::Const(ty, _) => {
724             // Account for `const T: _ = ..;`
725             if !is_suggestable_infer_ty(ty) {
726                 let mut visitor = HirPlaceholderCollector::default();
727                 visitor.visit_impl_item(impl_item);
728                 placeholder_type_error(tcx, None, visitor.0, false, None, "associated constant");
729             }
730         }
731     }
732 }
733 
convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId)734 fn convert_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
735     tcx.ensure().generics_of(def_id);
736     tcx.ensure().type_of(def_id);
737     tcx.ensure().predicates_of(def_id);
738 }
739 
convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId)740 fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
741     let def = tcx.adt_def(def_id);
742     let repr_type = def.repr().discr_type();
743     let initial = repr_type.initial_discriminant(tcx);
744     let mut prev_discr = None::<Discr<'_>>;
745 
746     // fill the discriminant values and field types
747     for variant in def.variants() {
748         let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
749         prev_discr = Some(
750             if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
751                 def.eval_explicit_discr(tcx, const_def_id)
752             } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
753                 Some(discr)
754             } else {
755                 let span = tcx.def_span(variant.def_id);
756                 tcx.sess.emit_err(errors::EnumDiscriminantOverflowed {
757                     span,
758                     discr: prev_discr.unwrap().to_string(),
759                     item_name: tcx.item_name(variant.def_id),
760                     wrapped_discr: wrapped_discr.to_string(),
761                 });
762                 None
763             }
764             .unwrap_or(wrapped_discr),
765         );
766 
767         for f in &variant.fields {
768             tcx.ensure().generics_of(f.did);
769             tcx.ensure().type_of(f.did);
770             tcx.ensure().predicates_of(f.did);
771         }
772 
773         // Convert the ctor, if any. This also registers the variant as
774         // an item.
775         if let Some(ctor_def_id) = variant.ctor_def_id() {
776             convert_variant_ctor(tcx, ctor_def_id.expect_local());
777         }
778     }
779 }
780 
convert_variant( tcx: TyCtxt<'_>, variant_did: Option<LocalDefId>, ident: Ident, discr: ty::VariantDiscr, def: &hir::VariantData<'_>, adt_kind: ty::AdtKind, parent_did: LocalDefId, ) -> ty::VariantDef781 fn convert_variant(
782     tcx: TyCtxt<'_>,
783     variant_did: Option<LocalDefId>,
784     ident: Ident,
785     discr: ty::VariantDiscr,
786     def: &hir::VariantData<'_>,
787     adt_kind: ty::AdtKind,
788     parent_did: LocalDefId,
789 ) -> ty::VariantDef {
790     let mut seen_fields: FxHashMap<Ident, Span> = Default::default();
791     let fields = def
792         .fields()
793         .iter()
794         .map(|f| {
795             let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned();
796             if let Some(prev_span) = dup_span {
797                 tcx.sess.emit_err(errors::FieldAlreadyDeclared {
798                     field_name: f.ident,
799                     span: f.span,
800                     prev_span,
801                 });
802             } else {
803                 seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
804             }
805 
806             ty::FieldDef {
807                 did: f.def_id.to_def_id(),
808                 name: f.ident.name,
809                 vis: tcx.visibility(f.def_id),
810             }
811         })
812         .collect();
813     let recovered = match def {
814         hir::VariantData::Struct(_, r) => *r,
815         _ => false,
816     };
817     ty::VariantDef::new(
818         ident.name,
819         variant_did.map(LocalDefId::to_def_id),
820         def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
821         discr,
822         fields,
823         adt_kind,
824         parent_did.to_def_id(),
825         recovered,
826         adt_kind == AdtKind::Struct && tcx.has_attr(parent_did, sym::non_exhaustive)
827             || variant_did
828                 .is_some_and(|variant_did| tcx.has_attr(variant_did, sym::non_exhaustive)),
829     )
830 }
831 
adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_>832 fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
833     use rustc_hir::*;
834 
835     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
836     let Node::Item(item) = tcx.hir().get(hir_id) else {
837         bug!();
838     };
839 
840     let repr = tcx.repr_options_of_def(def_id.to_def_id());
841     let (kind, variants) = match &item.kind {
842         ItemKind::Enum(def, _) => {
843             let mut distance_from_explicit = 0;
844             let variants = def
845                 .variants
846                 .iter()
847                 .map(|v| {
848                     let discr = if let Some(e) = &v.disr_expr {
849                         distance_from_explicit = 0;
850                         ty::VariantDiscr::Explicit(e.def_id.to_def_id())
851                     } else {
852                         ty::VariantDiscr::Relative(distance_from_explicit)
853                     };
854                     distance_from_explicit += 1;
855 
856                     convert_variant(
857                         tcx,
858                         Some(v.def_id),
859                         v.ident,
860                         discr,
861                         &v.data,
862                         AdtKind::Enum,
863                         def_id,
864                     )
865                 })
866                 .collect();
867 
868             (AdtKind::Enum, variants)
869         }
870         ItemKind::Struct(def, _) | ItemKind::Union(def, _) => {
871             let adt_kind = match item.kind {
872                 ItemKind::Struct(..) => AdtKind::Struct,
873                 _ => AdtKind::Union,
874             };
875             let variants = std::iter::once(convert_variant(
876                 tcx,
877                 None,
878                 item.ident,
879                 ty::VariantDiscr::Relative(0),
880                 def,
881                 adt_kind,
882                 def_id,
883             ))
884             .collect();
885 
886             (adt_kind, variants)
887         }
888         _ => bug!(),
889     };
890     tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
891 }
892 
trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef893 fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
894     let item = tcx.hir().expect_item(def_id);
895 
896     let (is_auto, unsafety, items) = match item.kind {
897         hir::ItemKind::Trait(is_auto, unsafety, .., items) => {
898             (is_auto == hir::IsAuto::Yes, unsafety, items)
899         }
900         hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal, &[][..]),
901         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
902     };
903 
904     let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
905     if paren_sugar && !tcx.features().unboxed_closures {
906         tcx.sess.emit_err(errors::ParenSugarAttribute { span: item.span });
907     }
908 
909     let is_marker = tcx.has_attr(def_id, sym::marker);
910     let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
911     let skip_array_during_method_dispatch =
912         tcx.has_attr(def_id, sym::rustc_skip_array_during_method_dispatch);
913     let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
914         ty::trait_def::TraitSpecializationKind::Marker
915     } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
916         ty::trait_def::TraitSpecializationKind::AlwaysApplicable
917     } else {
918         ty::trait_def::TraitSpecializationKind::None
919     };
920     let must_implement_one_of = tcx
921         .get_attr(def_id, 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.sess.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.sess.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 = items.iter().find(|item| item.ident == *ident);
947 
948                 match item {
949                     Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
950                         if !tcx.defaultness(item.id.owner_id).has_value() {
951                             tcx.sess.emit_err(errors::FunctionNotHaveDefaultImplementation {
952                                 span: item.span,
953                                 note_span: attr_span,
954                             });
955 
956                             return Some(());
957                         }
958 
959                         return None;
960                     }
961                     Some(item) => {
962                         tcx.sess.emit_err(errors::MustImplementNotFunction {
963                             span: item.span,
964                             span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
965                             note: errors::MustImplementNotFunctionNote {},
966                         });
967                     }
968                     None => {
969                         tcx.sess.emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
970                     }
971                 }
972 
973                 Some(())
974             });
975 
976             (errors.count() == 0).then_some(list)
977         })
978         // Check for duplicates
979         .and_then(|list| {
980             let mut set: FxHashMap<Symbol, Span> = FxHashMap::default();
981             let mut no_dups = true;
982 
983             for ident in &*list {
984                 if let Some(dup) = set.insert(ident.name, ident.span) {
985                     tcx.sess
986                         .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
987 
988                     no_dups = false;
989                 }
990             }
991 
992             no_dups.then_some(list)
993         });
994 
995     let mut deny_explicit_impl = false;
996     let mut implement_via_object = true;
997     if let Some(attr) = tcx.get_attr(def_id, sym::rustc_deny_explicit_impl) {
998         deny_explicit_impl = true;
999         let mut seen_attr = false;
1000         for meta in attr.meta_item_list().iter().flatten() {
1001             if let Some(meta) = meta.meta_item()
1002                 && meta.name_or_empty() == sym::implement_via_object
1003                 && let Some(lit) = meta.name_value_literal()
1004             {
1005                 if seen_attr {
1006                     tcx.sess.span_err(
1007                         meta.span,
1008                         "duplicated `implement_via_object` meta item",
1009                     );
1010                 }
1011                 seen_attr = true;
1012 
1013                 match lit.symbol {
1014                     kw::True => {
1015                         implement_via_object = true;
1016                     }
1017                     kw::False => {
1018                         implement_via_object = false;
1019                     }
1020                     _ => {
1021                         tcx.sess.span_err(
1022                             meta.span,
1023                             format!("unknown literal passed to `implement_via_object` attribute: {}", lit.symbol),
1024                         );
1025                     }
1026                 }
1027             } else {
1028                 tcx.sess.span_err(
1029                     meta.span(),
1030                     format!("unknown meta item passed to `rustc_deny_explicit_impl` {:?}", meta),
1031                 );
1032             }
1033         }
1034         if !seen_attr {
1035             tcx.sess.span_err(attr.span, "missing `implement_via_object` meta item");
1036         }
1037     }
1038 
1039     ty::TraitDef {
1040         def_id: def_id.to_def_id(),
1041         unsafety,
1042         paren_sugar,
1043         has_auto_impl: is_auto,
1044         is_marker,
1045         is_coinductive: rustc_coinductive || is_auto,
1046         skip_array_during_method_dispatch,
1047         specialization_kind,
1048         must_implement_one_of,
1049         implement_via_object,
1050         deny_explicit_impl,
1051     }
1052 }
1053 
are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool1054 fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool {
1055     generic_args.iter().any(|arg| match arg {
1056         hir::GenericArg::Type(ty) => is_suggestable_infer_ty(ty),
1057         hir::GenericArg::Infer(_) => true,
1058         _ => false,
1059     })
1060 }
1061 
1062 /// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to
1063 /// use inference to provide suggestions for the appropriate type if possible.
is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool1064 fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool {
1065     debug!(?ty);
1066     use hir::TyKind::*;
1067     match &ty.kind {
1068         Infer => true,
1069         Slice(ty) => is_suggestable_infer_ty(ty),
1070         Array(ty, length) => {
1071             is_suggestable_infer_ty(ty) || matches!(length, hir::ArrayLen::Infer(_, _))
1072         }
1073         Tup(tys) => tys.iter().any(is_suggestable_infer_ty),
1074         Ptr(mut_ty) | Ref(_, mut_ty) => is_suggestable_infer_ty(mut_ty.ty),
1075         OpaqueDef(_, generic_args, _) => are_suggestable_generic_args(generic_args),
1076         Path(hir::QPath::TypeRelative(ty, segment)) => {
1077             is_suggestable_infer_ty(ty) || are_suggestable_generic_args(segment.args().args)
1078         }
1079         Path(hir::QPath::Resolved(ty_opt, hir::Path { segments, .. })) => {
1080             ty_opt.is_some_and(is_suggestable_infer_ty)
1081                 || segments.iter().any(|segment| are_suggestable_generic_args(segment.args().args))
1082         }
1083         _ => false,
1084     }
1085 }
1086 
get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>>1087 pub fn get_infer_ret_ty<'hir>(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> {
1088     if let hir::FnRetTy::Return(ty) = output {
1089         if is_suggestable_infer_ty(ty) {
1090             return Some(&*ty);
1091         }
1092     }
1093     None
1094 }
1095 
1096 #[instrument(level = "debug", skip(tcx))]
fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>>1097 fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<ty::PolyFnSig<'_>> {
1098     use rustc_hir::Node::*;
1099     use rustc_hir::*;
1100 
1101     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
1102 
1103     let icx = ItemCtxt::new(tcx, def_id);
1104 
1105     let output = match tcx.hir().get(hir_id) {
1106         TraitItem(hir::TraitItem {
1107             kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
1108             generics,
1109             ..
1110         })
1111         | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), .. }) => {
1112             infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
1113         }
1114 
1115         ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
1116             // Do not try to infer the return type for a impl method coming from a trait
1117             if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) =
1118                 tcx.hir().get_parent(hir_id)
1119                 && i.of_trait.is_some()
1120             {
1121                 icx.astconv().ty_of_fn(
1122                     hir_id,
1123                     sig.header.unsafety,
1124                     sig.header.abi,
1125                     sig.decl,
1126                     Some(generics),
1127                     None,
1128                 )
1129             } else {
1130                 infer_return_ty_for_fn_sig(tcx, sig, generics, def_id, &icx)
1131             }
1132         }
1133 
1134         TraitItem(hir::TraitItem {
1135             kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1136             generics,
1137             ..
1138         }) => {
1139             icx.astconv().ty_of_fn(hir_id, header.unsafety, header.abi, decl, Some(generics), None)
1140         }
1141 
1142         ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => {
1143             let abi = tcx.hir().get_foreign_abi(hir_id);
1144             compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi)
1145         }
1146 
1147         Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => {
1148             let ty = tcx.type_of(tcx.hir().get_parent_item(hir_id)).subst_identity();
1149             let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).subst_identity());
1150             ty::Binder::dummy(tcx.mk_fn_sig(
1151                 inputs,
1152                 ty,
1153                 false,
1154                 hir::Unsafety::Normal,
1155                 abi::Abi::Rust,
1156             ))
1157         }
1158 
1159         Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1160             // Closure signatures are not like other function
1161             // signatures and cannot be accessed through `fn_sig`. For
1162             // example, a closure signature excludes the `self`
1163             // argument. In any case they are embedded within the
1164             // closure type as part of the `ClosureSubsts`.
1165             //
1166             // To get the signature of a closure, you should use the
1167             // `sig` method on the `ClosureSubsts`:
1168             //
1169             //    substs.as_closure().sig(def_id, tcx)
1170             bug!(
1171                 "to get the signature of a closure, use `substs.as_closure().sig()` not `fn_sig()`",
1172             );
1173         }
1174 
1175         x => {
1176             bug!("unexpected sort of node in fn_sig(): {:?}", x);
1177         }
1178     };
1179     ty::EarlyBinder::bind(output)
1180 }
1181 
infer_return_ty_for_fn_sig<'tcx>( tcx: TyCtxt<'tcx>, sig: &hir::FnSig<'_>, generics: &hir::Generics<'_>, def_id: LocalDefId, icx: &ItemCtxt<'tcx>, ) -> ty::PolyFnSig<'tcx>1182 fn infer_return_ty_for_fn_sig<'tcx>(
1183     tcx: TyCtxt<'tcx>,
1184     sig: &hir::FnSig<'_>,
1185     generics: &hir::Generics<'_>,
1186     def_id: LocalDefId,
1187     icx: &ItemCtxt<'tcx>,
1188 ) -> ty::PolyFnSig<'tcx> {
1189     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
1190 
1191     match get_infer_ret_ty(&sig.decl.output) {
1192         Some(ty) => {
1193             let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1194             // Typeck doesn't expect erased regions to be returned from `type_of`.
1195             let fn_sig = tcx.fold_regions(fn_sig, |r, _| match *r {
1196                 ty::ReErased => tcx.lifetimes.re_static,
1197                 _ => r,
1198             });
1199 
1200             let mut visitor = HirPlaceholderCollector::default();
1201             visitor.visit_ty(ty);
1202 
1203             let mut diag = bad_placeholder(tcx, visitor.0, "return type");
1204             let ret_ty = fn_sig.output();
1205             // Don't leak types into signatures unless they're nameable!
1206             // For example, if a function returns itself, we don't want that
1207             // recursive function definition to leak out into the fn sig.
1208             let mut should_recover = false;
1209 
1210             if let Some(ret_ty) = ret_ty.make_suggestable(tcx, false) {
1211                 diag.span_suggestion(
1212                     ty.span,
1213                     "replace with the correct return type",
1214                     ret_ty,
1215                     Applicability::MachineApplicable,
1216                 );
1217                 should_recover = true;
1218             } else if let Some(sugg) = suggest_impl_trait(tcx, ret_ty, ty.span, def_id) {
1219                 diag.span_suggestion(
1220                     ty.span,
1221                     "replace with an appropriate return type",
1222                     sugg,
1223                     Applicability::MachineApplicable,
1224                 );
1225             } else if ret_ty.is_closure() {
1226                 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1227             }
1228             // Also note how `Fn` traits work just in case!
1229             if ret_ty.is_closure() {
1230                 diag.note(
1231                     "for more information on `Fn` traits and closure types, see \
1232                      https://doc.rust-lang.org/book/ch13-01-closures.html",
1233                 );
1234             }
1235 
1236             let guar = diag.emit();
1237 
1238             if should_recover {
1239                 ty::Binder::dummy(fn_sig)
1240             } else {
1241                 ty::Binder::dummy(tcx.mk_fn_sig(
1242                     fn_sig.inputs().iter().copied(),
1243                     Ty::new_error(tcx, guar),
1244                     fn_sig.c_variadic,
1245                     fn_sig.unsafety,
1246                     fn_sig.abi,
1247                 ))
1248             }
1249         }
1250         None => icx.astconv().ty_of_fn(
1251             hir_id,
1252             sig.header.unsafety,
1253             sig.header.abi,
1254             sig.decl,
1255             Some(generics),
1256             None,
1257         ),
1258     }
1259 }
1260 
suggest_impl_trait<'tcx>( tcx: TyCtxt<'tcx>, ret_ty: Ty<'tcx>, span: Span, def_id: LocalDefId, ) -> Option<String>1261 fn suggest_impl_trait<'tcx>(
1262     tcx: TyCtxt<'tcx>,
1263     ret_ty: Ty<'tcx>,
1264     span: Span,
1265     def_id: LocalDefId,
1266 ) -> Option<String> {
1267     let format_as_assoc: fn(_, _, _, _, _) -> _ =
1268         |tcx: TyCtxt<'tcx>,
1269          _: ty::SubstsRef<'tcx>,
1270          trait_def_id: DefId,
1271          assoc_item_def_id: DefId,
1272          item_ty: Ty<'tcx>| {
1273             let trait_name = tcx.item_name(trait_def_id);
1274             let assoc_name = tcx.item_name(assoc_item_def_id);
1275             Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1276         };
1277     let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1278         |tcx: TyCtxt<'tcx>,
1279          substs: ty::SubstsRef<'tcx>,
1280          trait_def_id: DefId,
1281          _: DefId,
1282          item_ty: Ty<'tcx>| {
1283             let trait_name = tcx.item_name(trait_def_id);
1284             let args_tuple = substs.type_at(1);
1285             let ty::Tuple(types) = *args_tuple.kind() else { return None; };
1286             let types = types.make_suggestable(tcx, false)?;
1287             let maybe_ret =
1288                 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1289             Some(format!(
1290                 "impl {trait_name}({}){maybe_ret}",
1291                 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1292             ))
1293         };
1294 
1295     for (trait_def_id, assoc_item_def_id, formatter) in [
1296         (
1297             tcx.get_diagnostic_item(sym::Iterator),
1298             tcx.get_diagnostic_item(sym::IteratorItem),
1299             format_as_assoc,
1300         ),
1301         (
1302             tcx.lang_items().future_trait(),
1303             tcx.get_diagnostic_item(sym::FutureOutput),
1304             format_as_assoc,
1305         ),
1306         (tcx.lang_items().fn_trait(), tcx.lang_items().fn_once_output(), format_as_parenthesized),
1307         (
1308             tcx.lang_items().fn_mut_trait(),
1309             tcx.lang_items().fn_once_output(),
1310             format_as_parenthesized,
1311         ),
1312         (
1313             tcx.lang_items().fn_once_trait(),
1314             tcx.lang_items().fn_once_output(),
1315             format_as_parenthesized,
1316         ),
1317     ] {
1318         let Some(trait_def_id) = trait_def_id else { continue; };
1319         let Some(assoc_item_def_id) = assoc_item_def_id else { continue; };
1320         if tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1321             continue;
1322         }
1323         let param_env = tcx.param_env(def_id);
1324         let infcx = tcx.infer_ctxt().build();
1325         let substs = ty::InternalSubsts::for_item(tcx, trait_def_id, |param, _| {
1326             if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(span, param) }
1327         });
1328         if !infcx.type_implements_trait(trait_def_id, substs, param_env).must_apply_modulo_regions()
1329         {
1330             continue;
1331         }
1332         let ocx = ObligationCtxt::new(&infcx);
1333         let item_ty = ocx.normalize(
1334             &ObligationCause::misc(span, def_id),
1335             param_env,
1336             Ty::new_projection(tcx, assoc_item_def_id, substs),
1337         );
1338         // FIXME(compiler-errors): We may benefit from resolving regions here.
1339         if ocx.select_where_possible().is_empty()
1340             && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1341             && let Some(item_ty) = item_ty.make_suggestable(tcx, false)
1342             && let Some(sugg) = formatter(tcx, infcx.resolve_vars_if_possible(substs), trait_def_id, assoc_item_def_id, item_ty)
1343         {
1344             return Some(sugg);
1345         }
1346     }
1347     None
1348 }
1349 
impl_trait_ref( tcx: TyCtxt<'_>, def_id: LocalDefId, ) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>>1350 fn impl_trait_ref(
1351     tcx: TyCtxt<'_>,
1352     def_id: LocalDefId,
1353 ) -> Option<ty::EarlyBinder<ty::TraitRef<'_>>> {
1354     let icx = ItemCtxt::new(tcx, def_id);
1355     let impl_ = tcx.hir().expect_item(def_id).expect_impl();
1356     impl_
1357         .of_trait
1358         .as_ref()
1359         .map(|ast_trait_ref| {
1360             let selfty = tcx.type_of(def_id).subst_identity();
1361             icx.astconv().instantiate_mono_trait_ref(
1362                 ast_trait_ref,
1363                 selfty,
1364                 check_impl_constness(tcx, impl_.constness, ast_trait_ref),
1365             )
1366         })
1367         .map(ty::EarlyBinder::bind)
1368 }
1369 
check_impl_constness( tcx: TyCtxt<'_>, constness: hir::Constness, ast_trait_ref: &hir::TraitRef<'_>, ) -> ty::BoundConstness1370 fn check_impl_constness(
1371     tcx: TyCtxt<'_>,
1372     constness: hir::Constness,
1373     ast_trait_ref: &hir::TraitRef<'_>,
1374 ) -> ty::BoundConstness {
1375     match constness {
1376         hir::Constness::Const => {
1377             if let Some(trait_def_id) = ast_trait_ref.trait_def_id() && !tcx.has_attr(trait_def_id, sym::const_trait) {
1378                 let trait_name = tcx.item_name(trait_def_id).to_string();
1379                 tcx.sess.emit_err(errors::ConstImplForNonConstTrait {
1380                     trait_ref_span: ast_trait_ref.path.span,
1381                     trait_name,
1382                     local_trait_span: trait_def_id.as_local().map(|_| tcx.def_span(trait_def_id).shrink_to_lo()),
1383                     marking: (),
1384                     adding: (),
1385                 });
1386                 ty::BoundConstness::NotConst
1387             } else {
1388                 ty::BoundConstness::ConstIfConst
1389             }
1390         },
1391         hir::Constness::NotConst => ty::BoundConstness::NotConst,
1392     }
1393 }
1394 
impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity1395 fn impl_polarity(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplPolarity {
1396     let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1397     let item = tcx.hir().expect_item(def_id);
1398     match &item.kind {
1399         hir::ItemKind::Impl(hir::Impl {
1400             polarity: hir::ImplPolarity::Negative(span),
1401             of_trait,
1402             ..
1403         }) => {
1404             if is_rustc_reservation {
1405                 let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
1406                 tcx.sess.span_err(span, "reservation impls can't be negative");
1407             }
1408             ty::ImplPolarity::Negative
1409         }
1410         hir::ItemKind::Impl(hir::Impl {
1411             polarity: hir::ImplPolarity::Positive,
1412             of_trait: None,
1413             ..
1414         }) => {
1415             if is_rustc_reservation {
1416                 tcx.sess.span_err(item.span, "reservation impls can't be inherent");
1417             }
1418             ty::ImplPolarity::Positive
1419         }
1420         hir::ItemKind::Impl(hir::Impl {
1421             polarity: hir::ImplPolarity::Positive,
1422             of_trait: Some(_),
1423             ..
1424         }) => {
1425             if is_rustc_reservation {
1426                 ty::ImplPolarity::Reservation
1427             } else {
1428                 ty::ImplPolarity::Positive
1429             }
1430         }
1431         item => bug!("impl_polarity: {:?} not an impl", item),
1432     }
1433 }
1434 
1435 /// Returns the early-bound lifetimes declared in this generics
1436 /// listing. For anything other than fns/methods, this is just all
1437 /// the lifetimes that are declared. For fns or methods, we have to
1438 /// screen out those that do not appear in any where-clauses etc using
1439 /// `resolve_lifetime::early_bound_lifetimes`.
early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( tcx: TyCtxt<'tcx>, generics: &'a hir::Generics<'a>, ) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx>1440 fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>(
1441     tcx: TyCtxt<'tcx>,
1442     generics: &'a hir::Generics<'a>,
1443 ) -> impl Iterator<Item = &'a hir::GenericParam<'a>> + Captures<'tcx> {
1444     generics.params.iter().filter(move |param| match param.kind {
1445         GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1446         _ => false,
1447     })
1448 }
1449 
1450 /// Returns a list of type predicates for the definition with ID `def_id`, including inferred
1451 /// lifetime constraints. This includes all predicates returned by `explicit_predicates_of`, plus
1452 /// inferred constraints concerning which regions outlive other regions.
1453 #[instrument(level = "debug", skip(tcx))]
predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_>1454 fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
1455     let mut result = tcx.explicit_predicates_of(def_id);
1456     debug!("predicates_defined_on: explicit_predicates_of({:?}) = {:?}", def_id, result,);
1457     let inferred_outlives = tcx.inferred_outlives_of(def_id);
1458     if !inferred_outlives.is_empty() {
1459         debug!(
1460             "predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
1461             def_id, inferred_outlives,
1462         );
1463         let inferred_outlives_iter =
1464             inferred_outlives.iter().map(|(clause, span)| ((*clause).to_predicate(tcx), *span));
1465         if result.predicates.is_empty() {
1466             result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
1467         } else {
1468             result.predicates = tcx.arena.alloc_from_iter(
1469                 result.predicates.into_iter().copied().chain(inferred_outlives_iter),
1470             );
1471         }
1472     }
1473 
1474     debug!("predicates_defined_on({:?}) = {:?}", def_id, result);
1475     result
1476 }
1477 
compute_sig_of_foreign_fn_decl<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, decl: &'tcx hir::FnDecl<'tcx>, abi: abi::Abi, ) -> ty::PolyFnSig<'tcx>1478 fn compute_sig_of_foreign_fn_decl<'tcx>(
1479     tcx: TyCtxt<'tcx>,
1480     def_id: LocalDefId,
1481     decl: &'tcx hir::FnDecl<'tcx>,
1482     abi: abi::Abi,
1483 ) -> ty::PolyFnSig<'tcx> {
1484     let unsafety = if abi == abi::Abi::RustIntrinsic {
1485         intrinsic_operation_unsafety(tcx, def_id.to_def_id())
1486     } else {
1487         hir::Unsafety::Unsafe
1488     };
1489     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
1490     let fty =
1491         ItemCtxt::new(tcx, def_id).astconv().ty_of_fn(hir_id, unsafety, abi, decl, None, None);
1492 
1493     // Feature gate SIMD types in FFI, since I am not sure that the
1494     // ABIs are handled at all correctly. -huonw
1495     if abi != abi::Abi::RustIntrinsic
1496         && abi != abi::Abi::PlatformIntrinsic
1497         && !tcx.features().simd_ffi
1498     {
1499         let check = |ast_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1500             if ty.is_simd() {
1501                 let snip = tcx
1502                     .sess
1503                     .source_map()
1504                     .span_to_snippet(ast_ty.span)
1505                     .map_or_else(|_| String::new(), |s| format!(" `{}`", s));
1506                 tcx.sess.emit_err(errors::SIMDFFIHighlyExperimental { span: ast_ty.span, snip });
1507             }
1508         };
1509         for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1510             check(input, *ty)
1511         }
1512         if let hir::FnRetTy::Return(ty) = decl.output {
1513             check(ty, fty.output().skip_binder())
1514         }
1515     }
1516 
1517     fty
1518 }
1519 
generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind>1520 fn generator_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::GeneratorKind> {
1521     match tcx.hir().get_by_def_id(def_id) {
1522         Node::Expr(&rustc_hir::Expr {
1523             kind: rustc_hir::ExprKind::Closure(&rustc_hir::Closure { body, .. }),
1524             ..
1525         }) => tcx.hir().body(body).generator_kind(),
1526         _ => None,
1527     }
1528 }
1529 
is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool1530 fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
1531     match tcx.hir().get_by_def_id(def_id) {
1532         Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(opaque), .. }) => {
1533             matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
1534         }
1535         _ => bug!("tried getting opaque_ty_origin for non-opaque: {:?}", def_id),
1536     }
1537 }
1538