1use std::assert_matches::assert_matches;
18use std::cell::Cell;
19use std::iter;
20use std::ops::Bound;
21
22use rustc_abi::ExternAbi;
23use rustc_ast::Recovered;
24use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
25use rustc_data_structures::unord::UnordMap;
26use rustc_errors::{
27 Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
28};
29use rustc_hir::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, PreciseCapturingArgKind};
33use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
34use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
35use rustc_middle::hir::nested_filter;
36use rustc_middle::query::Providers;
37use rustc_middle::ty::util::{Discr, IntTypeExt};
38use rustc_middle::ty::{self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypingMode, fold_regions};
39use rustc_middle::{bug, span_bug};
40use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
41use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
42use rustc_trait_selection::infer::InferCtxtExt;
43use rustc_trait_selection::traits::{ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations};
44use tracing::{debug, instrument};
45
46use crate::errors;
47use crate::hir_ty_lowering::{FeedConstTy, HirTyLowerer, RegionInferReason};
48
49pub(crate) mod dump;
50mod generics_of;
51mod item_bounds;
52mod predicates_of;
53mod resolve_bound_vars;
54mod type_of;
55
56pub(crate) fn provide(providers: &mut Providers) {
59 resolve_bound_vars::provide(providers);
60 *providers = Providers {
61 type_of: type_of::type_of,
62 type_of_opaque: type_of::type_of_opaque,
63 type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
64 type_alias_is_lazy: type_of::type_alias_is_lazy,
65 item_bounds: item_bounds::item_bounds,
66 explicit_item_bounds: item_bounds::explicit_item_bounds,
67 item_self_bounds: item_bounds::item_self_bounds,
68 explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
69 item_non_self_bounds: item_bounds::item_non_self_bounds,
70 impl_super_outlives: item_bounds::impl_super_outlives,
71 generics_of: generics_of::generics_of,
72 predicates_of: predicates_of::predicates_of,
73 explicit_predicates_of: predicates_of::explicit_predicates_of,
74 explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
75 explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
76 explicit_supertraits_containing_assoc_item:
77 predicates_of::explicit_supertraits_containing_assoc_item,
78 trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
79 const_conditions: predicates_of::const_conditions,
80 explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
81 type_param_predicates: predicates_of::type_param_predicates,
82 trait_def,
83 adt_def,
84 fn_sig,
85 impl_trait_header,
86 coroutine_kind,
87 coroutine_for_closure,
88 opaque_ty_origin,
89 rendered_precise_capturing_args,
90 const_param_default,
91 anon_const_kind,
92 ..*providers
93 };
94}
95
96pub(crate) struct ItemCtxt<'tcx> {
126 tcx: TyCtxt<'tcx>,
127 item_def_id: LocalDefId,
128 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
129}
130
131#[derive(Default)]
134pub(crate) struct HirPlaceholderCollector {
135 pub spans: Vec<Span>,
136 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
155pub(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 sugg.push((span, (*type_name).to_string()));
200 } else if let Some(span) = generics.span_for_param_suggestion() {
201 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 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 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 !(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 _ => 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 maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
281 self.tcx
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 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 }
321 intravisit::walk_expr(self, expr);
322 }
323
324 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
352fn 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 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_ident: 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_ident))
445 }
446
447 fn lower_assoc_item_path(
448 &self,
449 span: Span,
450 item_def_id: DefId,
451 item_segment: &rustc_hir::PathSegment<'tcx>,
452 poly_trait_ref: ty::PolyTraitRef<'tcx>,
453 ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
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 Ok((item_def_id, item_args))
462 } else {
463 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_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
472 match &item.kind {
473 hir::ItemKind::Enum(_, generics, _)
474 | hir::ItemKind::Struct(_, generics, _)
475 | hir::ItemKind::Union(_, generics, _) => {
476 let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
477 let (lt_sp, sugg) = match generics.params {
478 [] => (generics.span, format!("<{lt_name}>")),
479 [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
480 };
481 mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
482 fspan: lt_sp,
483 first: sugg,
484 sspan: span.with_hi(item_segment.ident.span.lo()),
485 second: format!(
486 "{}::",
487 self.tcx.instantiate_bound_regions_uncached(
489 poly_trait_ref,
490 |_| {
491 ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
492 index: 0,
493 name: Symbol::intern(<_name),
494 })
495 }
496 ),
497 ),
498 });
499 }
500 _ => {}
501 }
502 }
503 hir::Node::Item(hir::Item {
504 kind:
505 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
506 ..
507 }) => {}
508 hir::Node::Item(_)
509 | hir::Node::ForeignItem(_)
510 | hir::Node::TraitItem(_)
511 | hir::Node::ImplItem(_) => {
512 inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
513 bound = format!(
514 "{}::",
515 self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
517 );
518 }
519 _ => {}
520 }
521
522 Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
523 span,
524 inferred_sugg,
525 bound,
526 mpart_sugg,
527 what: self.tcx.def_descr(item_def_id),
528 }))
529 }
530 }
531
532 fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
533 ty.ty_adt_def()
535 }
536
537 fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
538 }
540
541 fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
542 None
543 }
544
545 fn lower_fn_sig(
546 &self,
547 decl: &hir::FnDecl<'tcx>,
548 generics: Option<&hir::Generics<'_>>,
549 hir_id: rustc_hir::HirId,
550 hir_ty: Option<&hir::Ty<'_>>,
551 ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
552 let tcx = self.tcx();
553 let mut visitor = HirPlaceholderCollector::default();
555 let mut infer_replacements = vec![];
556
557 if let Some(generics) = generics {
558 walk_generics(&mut visitor, generics);
559 }
560
561 let input_tys = decl
562 .inputs
563 .iter()
564 .enumerate()
565 .map(|(i, a)| {
566 if let hir::TyKind::Infer(()) = a.kind {
567 if let Some(suggested_ty) =
568 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
569 {
570 infer_replacements.push((a.span, suggested_ty.to_string()));
571 return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
572 }
573 }
574
575 visitor.visit_ty_unambig(a);
577 self.lowerer().lower_arg_ty(a, None)
578 })
579 .collect();
580
581 let output_ty = match decl.output {
582 hir::FnRetTy::Return(output) => {
583 if let hir::TyKind::Infer(()) = output.kind
584 && let Some(suggested_ty) =
585 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
586 {
587 infer_replacements.push((output.span, suggested_ty.to_string()));
588 Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
589 } else {
590 visitor.visit_ty_unambig(output);
591 self.lower_ty(output)
592 }
593 }
594 hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
595 };
596
597 if !(visitor.spans.is_empty() && infer_replacements.is_empty()) {
598 let mut diag = crate::collect::placeholder_type_error_diag(
602 self,
603 generics,
604 visitor.spans,
605 infer_replacements.iter().map(|(s, _)| *s).collect(),
606 !visitor.may_contain_const_infer,
607 hir_ty,
608 "function",
609 );
610
611 if !infer_replacements.is_empty() {
612 diag.multipart_suggestion(
613 format!(
614 "try replacing `_` with the type{} in the corresponding trait method \
615 signature",
616 rustc_errors::pluralize!(infer_replacements.len()),
617 ),
618 infer_replacements,
619 Applicability::MachineApplicable,
620 );
621 }
622
623 diag.emit();
624 }
625
626 (input_tys, output_ty)
627 }
628
629 fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
630 hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
631 }
632}
633
634fn get_new_lifetime_name<'tcx>(
636 tcx: TyCtxt<'tcx>,
637 poly_trait_ref: ty::PolyTraitRef<'tcx>,
638 generics: &hir::Generics<'tcx>,
639) -> String {
640 let existing_lifetimes = tcx
641 .collect_referenced_late_bound_regions(poly_trait_ref)
642 .into_iter()
643 .filter_map(|lt| {
644 if let ty::BoundRegionKind::Named(_, name) = lt {
645 Some(name.as_str().to_string())
646 } else {
647 None
648 }
649 })
650 .chain(generics.params.iter().filter_map(|param| {
651 if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind {
652 Some(param.name.ident().as_str().to_string())
653 } else {
654 None
655 }
656 }))
657 .collect::<FxHashSet<String>>();
658
659 let a_to_z_repeat_n = |n| {
660 (b'a'..=b'z').map(move |c| {
661 let mut s = '\''.to_string();
662 s.extend(std::iter::repeat(char::from(c)).take(n));
663 s
664 })
665 };
666
667 (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
669}
670
671#[instrument(level = "debug", skip_all)]
672fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) {
673 let it = tcx.hir_item(item_id);
674 debug!(item = ?it.kind.ident(), id = %it.hir_id());
675 let def_id = item_id.owner_id.def_id;
676 let icx = ItemCtxt::new(tcx, def_id);
677
678 match &it.kind {
679 hir::ItemKind::ExternCrate(..)
681 | hir::ItemKind::Use(..)
682 | hir::ItemKind::Macro(..)
683 | hir::ItemKind::Mod(..)
684 | hir::ItemKind::GlobalAsm { .. } => {}
685 hir::ItemKind::ForeignMod { items, .. } => {
686 for item in *items {
687 let item = tcx.hir_foreign_item(item.id);
688 tcx.ensure_ok().generics_of(item.owner_id);
689 tcx.ensure_ok().type_of(item.owner_id);
690 tcx.ensure_ok().predicates_of(item.owner_id);
691 if tcx.is_conditionally_const(def_id) {
692 tcx.ensure_ok().explicit_implied_const_bounds(def_id);
693 tcx.ensure_ok().const_conditions(def_id);
694 }
695 match item.kind {
696 hir::ForeignItemKind::Fn(..) => {
697 tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
698 tcx.ensure_ok().fn_sig(item.owner_id)
699 }
700 hir::ForeignItemKind::Static(..) => {
701 tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
702 let mut visitor = HirPlaceholderCollector::default();
703 visitor.visit_foreign_item(item);
704 placeholder_type_error(
705 icx.lowerer(),
706 None,
707 visitor.spans,
708 false,
709 None,
710 "static variable",
711 );
712 }
713 _ => (),
714 }
715 }
716 }
717 hir::ItemKind::Enum(..) => {
718 tcx.ensure_ok().generics_of(def_id);
719 tcx.ensure_ok().type_of(def_id);
720 tcx.ensure_ok().predicates_of(def_id);
721 lower_enum_variant_types(tcx, def_id.to_def_id());
722 }
723 hir::ItemKind::Impl { .. } => {
724 tcx.ensure_ok().generics_of(def_id);
725 tcx.ensure_ok().type_of(def_id);
726 tcx.ensure_ok().impl_trait_header(def_id);
727 tcx.ensure_ok().predicates_of(def_id);
728 tcx.ensure_ok().associated_items(def_id);
729 }
730 hir::ItemKind::Trait(..) => {
731 tcx.ensure_ok().generics_of(def_id);
732 tcx.ensure_ok().trait_def(def_id);
733 tcx.at(it.span).explicit_super_predicates_of(def_id);
734 tcx.ensure_ok().predicates_of(def_id);
735 tcx.ensure_ok().associated_items(def_id);
736 }
737 hir::ItemKind::TraitAlias(..) => {
738 tcx.ensure_ok().generics_of(def_id);
739 tcx.at(it.span).explicit_implied_predicates_of(def_id);
740 tcx.at(it.span).explicit_super_predicates_of(def_id);
741 tcx.ensure_ok().predicates_of(def_id);
742 }
743 hir::ItemKind::Struct(_, _, struct_def) | hir::ItemKind::Union(_, _, struct_def) => {
744 tcx.ensure_ok().generics_of(def_id);
745 tcx.ensure_ok().type_of(def_id);
746 tcx.ensure_ok().predicates_of(def_id);
747
748 for f in struct_def.fields() {
749 tcx.ensure_ok().generics_of(f.def_id);
750 tcx.ensure_ok().type_of(f.def_id);
751 tcx.ensure_ok().predicates_of(f.def_id);
752 }
753
754 if let Some(ctor_def_id) = struct_def.ctor_def_id() {
755 lower_variant_ctor(tcx, ctor_def_id);
756 }
757 }
758
759 hir::ItemKind::TyAlias(..) => {
760 tcx.ensure_ok().generics_of(def_id);
761 tcx.ensure_ok().type_of(def_id);
762 tcx.ensure_ok().predicates_of(def_id);
763 }
764
765 hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _) => {
766 tcx.ensure_ok().generics_of(def_id);
767 tcx.ensure_ok().type_of(def_id);
768 tcx.ensure_ok().predicates_of(def_id);
769 if !ty.is_suggestable_infer_ty() {
770 let mut visitor = HirPlaceholderCollector::default();
771 visitor.visit_item(it);
772 placeholder_type_error(
773 icx.lowerer(),
774 None,
775 visitor.spans,
776 false,
777 None,
778 it.kind.descr(),
779 );
780 }
781 }
782
783 hir::ItemKind::Fn { .. } => {
784 tcx.ensure_ok().generics_of(def_id);
785 tcx.ensure_ok().type_of(def_id);
786 tcx.ensure_ok().predicates_of(def_id);
787 tcx.ensure_ok().fn_sig(def_id);
788 tcx.ensure_ok().codegen_fn_attrs(def_id);
789 }
790 }
791}
792
793fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) {
794 let trait_item = tcx.hir_trait_item(trait_item_id);
795 let def_id = trait_item_id.owner_id;
796 tcx.ensure_ok().generics_of(def_id);
797 let icx = ItemCtxt::new(tcx, def_id.def_id);
798
799 match trait_item.kind {
800 hir::TraitItemKind::Fn(..) => {
801 tcx.ensure_ok().codegen_fn_attrs(def_id);
802 tcx.ensure_ok().type_of(def_id);
803 tcx.ensure_ok().fn_sig(def_id);
804 }
805
806 hir::TraitItemKind::Const(ty, body_id) => {
807 tcx.ensure_ok().type_of(def_id);
808 if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType)
809 && !(ty.is_suggestable_infer_ty() && body_id.is_some())
810 {
811 let mut visitor = HirPlaceholderCollector::default();
813 visitor.visit_trait_item(trait_item);
814 placeholder_type_error(
815 icx.lowerer(),
816 None,
817 visitor.spans,
818 false,
819 None,
820 "associated constant",
821 );
822 }
823 }
824
825 hir::TraitItemKind::Type(_, Some(_)) => {
826 tcx.ensure_ok().item_bounds(def_id);
827 tcx.ensure_ok().item_self_bounds(def_id);
828 tcx.ensure_ok().type_of(def_id);
829 let mut visitor = HirPlaceholderCollector::default();
831 visitor.visit_trait_item(trait_item);
832 placeholder_type_error(
833 icx.lowerer(),
834 None,
835 visitor.spans,
836 false,
837 None,
838 "associated type",
839 );
840 }
841
842 hir::TraitItemKind::Type(_, None) => {
843 tcx.ensure_ok().item_bounds(def_id);
844 tcx.ensure_ok().item_self_bounds(def_id);
845 let mut visitor = HirPlaceholderCollector::default();
848 visitor.visit_trait_item(trait_item);
849
850 placeholder_type_error(
851 icx.lowerer(),
852 None,
853 visitor.spans,
854 false,
855 None,
856 "associated type",
857 );
858 }
859 };
860
861 tcx.ensure_ok().predicates_of(def_id);
862}
863
864fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) {
865 let def_id = impl_item_id.owner_id;
866 tcx.ensure_ok().generics_of(def_id);
867 tcx.ensure_ok().type_of(def_id);
868 tcx.ensure_ok().predicates_of(def_id);
869 let impl_item = tcx.hir_impl_item(impl_item_id);
870 let icx = ItemCtxt::new(tcx, def_id.def_id);
871 match impl_item.kind {
872 hir::ImplItemKind::Fn(..) => {
873 tcx.ensure_ok().codegen_fn_attrs(def_id);
874 tcx.ensure_ok().fn_sig(def_id);
875 }
876 hir::ImplItemKind::Type(_) => {
877 let mut visitor = HirPlaceholderCollector::default();
879 visitor.visit_impl_item(impl_item);
880
881 placeholder_type_error(
882 icx.lowerer(),
883 None,
884 visitor.spans,
885 false,
886 None,
887 "associated type",
888 );
889 }
890 hir::ImplItemKind::Const(ty, _) => {
891 if !ty.is_suggestable_infer_ty() {
893 let mut visitor = HirPlaceholderCollector::default();
894 visitor.visit_impl_item(impl_item);
895 placeholder_type_error(
896 icx.lowerer(),
897 None,
898 visitor.spans,
899 false,
900 None,
901 "associated constant",
902 );
903 }
904 }
905 }
906}
907
908fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
909 tcx.ensure_ok().generics_of(def_id);
910 tcx.ensure_ok().type_of(def_id);
911 tcx.ensure_ok().predicates_of(def_id);
912}
913
914fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
915 let def = tcx.adt_def(def_id);
916 let repr_type = def.repr().discr_type();
917 let initial = repr_type.initial_discriminant(tcx);
918 let mut prev_discr = None::<Discr<'_>>;
919
920 for variant in def.variants() {
922 let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
923 prev_discr = Some(
924 if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
925 def.eval_explicit_discr(tcx, const_def_id).ok()
926 } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
927 Some(discr)
928 } else {
929 let span = tcx.def_span(variant.def_id);
930 tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
931 span,
932 discr: prev_discr.unwrap().to_string(),
933 item_name: tcx.item_ident(variant.def_id),
934 wrapped_discr: wrapped_discr.to_string(),
935 });
936 None
937 }
938 .unwrap_or(wrapped_discr),
939 );
940
941 for f in &variant.fields {
942 tcx.ensure_ok().generics_of(f.did);
943 tcx.ensure_ok().type_of(f.did);
944 tcx.ensure_ok().predicates_of(f.did);
945 }
946
947 if let Some(ctor_def_id) = variant.ctor_def_id() {
949 lower_variant_ctor(tcx, ctor_def_id.expect_local());
950 }
951 }
952}
953
954#[derive(Clone, Copy)]
955struct NestedSpan {
956 span: Span,
957 nested_field_span: Span,
958}
959
960impl NestedSpan {
961 fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
962 errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
963 }
964}
965
966#[derive(Clone, Copy)]
967enum FieldDeclSpan {
968 NotNested(Span),
969 Nested(NestedSpan),
970}
971
972impl From<Span> for FieldDeclSpan {
973 fn from(span: Span) -> Self {
974 Self::NotNested(span)
975 }
976}
977
978impl From<NestedSpan> for FieldDeclSpan {
979 fn from(span: NestedSpan) -> Self {
980 Self::Nested(span)
981 }
982}
983
984struct FieldUniquenessCheckContext<'tcx> {
985 tcx: TyCtxt<'tcx>,
986 seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
987}
988
989impl<'tcx> FieldUniquenessCheckContext<'tcx> {
990 fn new(tcx: TyCtxt<'tcx>) -> Self {
991 Self { tcx, seen_fields: FxIndexMap::default() }
992 }
993
994 fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
996 use FieldDeclSpan::*;
997 let field_name = field_name.normalize_to_macros_2_0();
998 match (field_decl, self.seen_fields.get(&field_name).copied()) {
999 (NotNested(span), Some(NotNested(prev_span))) => {
1000 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
1001 field_name,
1002 span,
1003 prev_span,
1004 });
1005 }
1006 (NotNested(span), Some(Nested(prev))) => {
1007 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
1008 field_name,
1009 span,
1010 prev_span: prev.span,
1011 prev_nested_field_span: prev.nested_field_span,
1012 prev_help: prev.to_field_already_declared_nested_help(),
1013 });
1014 }
1015 (
1016 Nested(current @ NestedSpan { span, nested_field_span, .. }),
1017 Some(NotNested(prev_span)),
1018 ) => {
1019 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
1020 field_name,
1021 span,
1022 nested_field_span,
1023 help: current.to_field_already_declared_nested_help(),
1024 prev_span,
1025 });
1026 }
1027 (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
1028 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
1029 field_name,
1030 span,
1031 nested_field_span,
1032 help: current.to_field_already_declared_nested_help(),
1033 prev_span: prev.span,
1034 prev_nested_field_span: prev.nested_field_span,
1035 prev_help: prev.to_field_already_declared_nested_help(),
1036 });
1037 }
1038 (field_decl, None) => {
1039 self.seen_fields.insert(field_name, field_decl);
1040 }
1041 }
1042 }
1043}
1044
1045fn lower_variant<'tcx>(
1046 tcx: TyCtxt<'tcx>,
1047 variant_did: Option<LocalDefId>,
1048 ident: Ident,
1049 discr: ty::VariantDiscr,
1050 def: &hir::VariantData<'tcx>,
1051 adt_kind: ty::AdtKind,
1052 parent_did: LocalDefId,
1053) -> ty::VariantDef {
1054 let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
1055 let fields = def
1056 .fields()
1057 .iter()
1058 .inspect(|field| {
1059 field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
1060 })
1061 .map(|f| ty::FieldDef {
1062 did: f.def_id.to_def_id(),
1063 name: f.ident.name,
1064 vis: tcx.visibility(f.def_id),
1065 safety: f.safety,
1066 value: f.default.map(|v| v.def_id.to_def_id()),
1067 })
1068 .collect();
1069 let recovered = match def {
1070 hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
1071 _ => None,
1072 };
1073 ty::VariantDef::new(
1074 ident.name,
1075 variant_did.map(LocalDefId::to_def_id),
1076 def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
1077 discr,
1078 fields,
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(ident, _, def) | ItemKind::Union(ident, _, 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 *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 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 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 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 .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 None => None,
1221 })
1222 .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 .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 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) => {
1352 assert_matches!(data.ctor(), Some(_));
1353 let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1354 let ty = tcx.type_of(adt_def_id).instantiate_identity();
1355 let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1356 let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1358 (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1359 _ => hir::Safety::Unsafe,
1360 };
1361 ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1362 }
1363
1364 Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1365 bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1376 }
1377
1378 x => {
1379 bug!("unexpected sort of node in fn_sig(): {:?}", x);
1380 }
1381 };
1382 ty::EarlyBinder::bind(output)
1383}
1384
1385fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1386 icx: &ItemCtxt<'tcx>,
1387 sig: &'tcx hir::FnSig<'tcx>,
1388 generics: &'tcx hir::Generics<'tcx>,
1389 def_id: LocalDefId,
1390) -> ty::PolyFnSig<'tcx> {
1391 if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1392 return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1393 }
1394
1395 icx.lowerer().lower_fn_ty(
1396 icx.tcx().local_def_id_to_hir_id(def_id),
1397 sig.header.safety(),
1398 sig.header.abi,
1399 sig.decl,
1400 Some(generics),
1401 None,
1402 )
1403}
1404
1405fn recover_infer_ret_ty<'tcx>(
1406 icx: &ItemCtxt<'tcx>,
1407 infer_ret_ty: &'tcx hir::Ty<'tcx>,
1408 generics: &'tcx hir::Generics<'tcx>,
1409 def_id: LocalDefId,
1410) -> ty::PolyFnSig<'tcx> {
1411 let tcx = icx.tcx;
1412 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1413
1414 let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1415
1416 let has_region_params = generics.params.iter().any(|param| match param.kind {
1421 GenericParamKind::Lifetime { .. } => true,
1422 _ => false,
1423 });
1424 let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1425 ty::ReErased => {
1426 if has_region_params {
1427 ty::Region::new_error_with_message(
1428 tcx,
1429 DUMMY_SP,
1430 "erased region is not allowed here in return type",
1431 )
1432 } else {
1433 tcx.lifetimes.re_static
1434 }
1435 }
1436 _ => r,
1437 });
1438
1439 let mut visitor = HirPlaceholderCollector::default();
1440 visitor.visit_ty_unambig(infer_ret_ty);
1441
1442 let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1443 let ret_ty = fn_sig.output();
1444
1445 let mut recovered_ret_ty = None;
1449 if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1450 diag.span_suggestion(
1451 infer_ret_ty.span,
1452 "replace with the correct return type",
1453 suggestable_ret_ty,
1454 Applicability::MachineApplicable,
1455 );
1456 recovered_ret_ty = Some(suggestable_ret_ty);
1457 } else if let Some(sugg) = suggest_impl_trait(
1458 &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1459 tcx.param_env(def_id),
1460 ret_ty,
1461 ) {
1462 diag.span_suggestion(
1463 infer_ret_ty.span,
1464 "replace with an appropriate return type",
1465 sugg,
1466 Applicability::MachineApplicable,
1467 );
1468 } else if ret_ty.is_closure() {
1469 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1470 }
1471
1472 if ret_ty.is_closure() {
1474 diag.note(
1475 "for more information on `Fn` traits and closure types, see \
1476 https://doc.rust-lang.org/book/ch13-01-closures.html",
1477 );
1478 }
1479 let guar = diag.emit();
1480 ty::Binder::dummy(tcx.mk_fn_sig(
1481 fn_sig.inputs().iter().copied(),
1482 recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1483 fn_sig.c_variadic,
1484 fn_sig.safety,
1485 fn_sig.abi,
1486 ))
1487}
1488
1489pub fn suggest_impl_trait<'tcx>(
1490 infcx: &InferCtxt<'tcx>,
1491 param_env: ty::ParamEnv<'tcx>,
1492 ret_ty: Ty<'tcx>,
1493) -> Option<String> {
1494 let format_as_assoc: fn(_, _, _, _, _) -> _ =
1495 |tcx: TyCtxt<'tcx>,
1496 _: ty::GenericArgsRef<'tcx>,
1497 trait_def_id: DefId,
1498 assoc_item_def_id: DefId,
1499 item_ty: Ty<'tcx>| {
1500 let trait_name = tcx.item_name(trait_def_id);
1501 let assoc_name = tcx.item_name(assoc_item_def_id);
1502 Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1503 };
1504 let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1505 |tcx: TyCtxt<'tcx>,
1506 args: ty::GenericArgsRef<'tcx>,
1507 trait_def_id: DefId,
1508 _: DefId,
1509 item_ty: Ty<'tcx>| {
1510 let trait_name = tcx.item_name(trait_def_id);
1511 let args_tuple = args.type_at(1);
1512 let ty::Tuple(types) = *args_tuple.kind() else {
1513 return None;
1514 };
1515 let types = types.make_suggestable(tcx, false, None)?;
1516 let maybe_ret =
1517 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1518 Some(format!(
1519 "impl {trait_name}({}){maybe_ret}",
1520 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1521 ))
1522 };
1523
1524 for (trait_def_id, assoc_item_def_id, formatter) in [
1525 (
1526 infcx.tcx.get_diagnostic_item(sym::Iterator),
1527 infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1528 format_as_assoc,
1529 ),
1530 (
1531 infcx.tcx.lang_items().future_trait(),
1532 infcx.tcx.lang_items().future_output(),
1533 format_as_assoc,
1534 ),
1535 (
1536 infcx.tcx.lang_items().fn_trait(),
1537 infcx.tcx.lang_items().fn_once_output(),
1538 format_as_parenthesized,
1539 ),
1540 (
1541 infcx.tcx.lang_items().fn_mut_trait(),
1542 infcx.tcx.lang_items().fn_once_output(),
1543 format_as_parenthesized,
1544 ),
1545 (
1546 infcx.tcx.lang_items().fn_once_trait(),
1547 infcx.tcx.lang_items().fn_once_output(),
1548 format_as_parenthesized,
1549 ),
1550 ] {
1551 let Some(trait_def_id) = trait_def_id else {
1552 continue;
1553 };
1554 let Some(assoc_item_def_id) = assoc_item_def_id else {
1555 continue;
1556 };
1557 if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1558 continue;
1559 }
1560 let sugg = infcx.probe(|_| {
1561 let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1562 if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1563 });
1564 if !infcx
1565 .type_implements_trait(trait_def_id, args, param_env)
1566 .must_apply_modulo_regions()
1567 {
1568 return None;
1569 }
1570 let ocx = ObligationCtxt::new(&infcx);
1571 let item_ty = ocx.normalize(
1572 &ObligationCause::dummy(),
1573 param_env,
1574 Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1575 );
1576 if ocx.select_where_possible().is_empty()
1578 && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1579 && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1580 && let Some(sugg) = formatter(
1581 infcx.tcx,
1582 infcx.resolve_vars_if_possible(args),
1583 trait_def_id,
1584 assoc_item_def_id,
1585 item_ty,
1586 )
1587 {
1588 return Some(sugg);
1589 }
1590
1591 None
1592 });
1593
1594 if sugg.is_some() {
1595 return sugg;
1596 }
1597 }
1598 None
1599}
1600
1601fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
1602 let icx = ItemCtxt::new(tcx, def_id);
1603 let item = tcx.hir_expect_item(def_id);
1604 let impl_ = item.expect_impl();
1605 impl_.of_trait.as_ref().map(|ast_trait_ref| {
1606 let selfty = tcx.type_of(def_id).instantiate_identity();
1607
1608 check_impl_constness(tcx, impl_.constness, ast_trait_ref);
1609
1610 let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
1611
1612 ty::ImplTraitHeader {
1613 trait_ref: ty::EarlyBinder::bind(trait_ref),
1614 safety: impl_.safety,
1615 polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
1616 constness: impl_.constness,
1617 }
1618 })
1619}
1620
1621fn check_impl_constness(
1622 tcx: TyCtxt<'_>,
1623 constness: hir::Constness,
1624 hir_trait_ref: &hir::TraitRef<'_>,
1625) {
1626 if let hir::Constness::NotConst = constness {
1627 return;
1628 }
1629
1630 let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1631 if tcx.is_const_trait(trait_def_id) {
1632 return;
1633 }
1634
1635 let trait_name = tcx.item_name(trait_def_id).to_string();
1636 let (local_trait_span, suggestion_pre) =
1637 match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1638 (true, true) => (
1639 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1640 if tcx.features().const_trait_impl() {
1641 ""
1642 } else {
1643 "enable `#![feature(const_trait_impl)]` in your crate and "
1644 },
1645 ),
1646 (false, _) | (_, false) => (None, ""),
1647 };
1648 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1649 trait_ref_span: hir_trait_ref.path.span,
1650 trait_name,
1651 local_trait_span,
1652 suggestion_pre,
1653 marking: (),
1654 adding: (),
1655 });
1656}
1657
1658fn polarity_of_impl(
1659 tcx: TyCtxt<'_>,
1660 def_id: LocalDefId,
1661 impl_: &hir::Impl<'_>,
1662 span: Span,
1663) -> ty::ImplPolarity {
1664 let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1665 match &impl_ {
1666 hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
1667 if is_rustc_reservation {
1668 let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
1669 tcx.dcx().span_err(span, "reservation impls can't be negative");
1670 }
1671 ty::ImplPolarity::Negative
1672 }
1673 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
1674 if is_rustc_reservation {
1675 tcx.dcx().span_err(span, "reservation impls can't be inherent");
1676 }
1677 ty::ImplPolarity::Positive
1678 }
1679 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
1680 if is_rustc_reservation {
1681 ty::ImplPolarity::Reservation
1682 } else {
1683 ty::ImplPolarity::Positive
1684 }
1685 }
1686 }
1687}
1688
1689fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1695 tcx: TyCtxt<'tcx>,
1696 generics: &'a hir::Generics<'a>,
1697) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1698 generics.params.iter().filter(move |param| match param.kind {
1699 GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1700 _ => false,
1701 })
1702}
1703
1704fn compute_sig_of_foreign_fn_decl<'tcx>(
1705 tcx: TyCtxt<'tcx>,
1706 def_id: LocalDefId,
1707 decl: &'tcx hir::FnDecl<'tcx>,
1708 abi: ExternAbi,
1709 safety: hir::Safety,
1710) -> ty::PolyFnSig<'tcx> {
1711 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1712 let fty =
1713 ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1714
1715 if !tcx.features().simd_ffi() {
1718 let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1719 if ty.is_simd() {
1720 let snip = tcx
1721 .sess
1722 .source_map()
1723 .span_to_snippet(hir_ty.span)
1724 .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
1725 tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1726 }
1727 };
1728 for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1729 check(input, *ty)
1730 }
1731 if let hir::FnRetTy::Return(ty) = decl.output {
1732 check(ty, fty.output().skip_binder())
1733 }
1734 }
1735
1736 fty
1737}
1738
1739fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1740 match tcx.hir_node_by_def_id(def_id) {
1741 Node::Expr(&hir::Expr {
1742 kind:
1743 hir::ExprKind::Closure(&rustc_hir::Closure {
1744 kind: hir::ClosureKind::Coroutine(kind),
1745 ..
1746 }),
1747 ..
1748 }) => Some(kind),
1749 _ => None,
1750 }
1751}
1752
1753fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1754 let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1755 tcx.hir_node_by_def_id(def_id).expect_closure()
1756 else {
1757 bug!()
1758 };
1759
1760 let &hir::Expr {
1761 kind:
1762 hir::ExprKind::Closure(&rustc_hir::Closure {
1763 def_id,
1764 kind: hir::ClosureKind::Coroutine(_),
1765 ..
1766 }),
1767 ..
1768 } = tcx.hir_body(body).value
1769 else {
1770 bug!()
1771 };
1772
1773 def_id.to_def_id()
1774}
1775
1776fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1777 match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1778 hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1779 hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1780 }
1781 hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1782 hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1783 }
1784 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1785 hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1786 }
1787 }
1788}
1789
1790fn rendered_precise_capturing_args<'tcx>(
1791 tcx: TyCtxt<'tcx>,
1792 def_id: LocalDefId,
1793) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1794 if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1795 tcx.opt_rpitit_info(def_id.to_def_id())
1796 {
1797 return tcx.rendered_precise_capturing_args(opaque_def_id);
1798 }
1799
1800 tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1801 hir::GenericBound::Use(args, ..) => {
1802 Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1803 PreciseCapturingArgKind::Lifetime(_) => {
1804 PreciseCapturingArgKind::Lifetime(arg.name())
1805 }
1806 PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1807 })))
1808 }
1809 _ => None,
1810 })
1811}
1812
1813fn const_param_default<'tcx>(
1814 tcx: TyCtxt<'tcx>,
1815 def_id: LocalDefId,
1816) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1817 let default_ct = match tcx.hir_node_by_def_id(def_id) {
1818 hir::Node::GenericParam(hir::GenericParam {
1819 kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1820 ..
1821 }) => ct,
1822 _ => span_bug!(
1823 tcx.def_span(def_id),
1824 "`const_param_default` expected a generic parameter with a constant"
1825 ),
1826 };
1827 let icx = ItemCtxt::new(tcx, def_id);
1828 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1829 let ct = icx
1830 .lowerer()
1831 .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1832 ty::EarlyBinder::bind(ct)
1833}
1834
1835fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1836 let hir_id = tcx.local_def_id_to_hir_id(def);
1837 let const_arg_id = tcx.parent_hir_id(hir_id);
1838 match tcx.hir_node(const_arg_id) {
1839 hir::Node::ConstArg(_) => {
1840 if tcx.features().generic_const_exprs() {
1841 ty::AnonConstKind::GCE
1842 } else if tcx.features().min_generic_const_args() {
1843 ty::AnonConstKind::MCG
1844 } else if let hir::Node::Expr(hir::Expr {
1845 kind: hir::ExprKind::Repeat(_, repeat_count),
1846 ..
1847 }) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
1848 && repeat_count.hir_id == const_arg_id
1849 {
1850 ty::AnonConstKind::RepeatExprCount
1851 } else {
1852 ty::AnonConstKind::MCG
1853 }
1854 }
1855 _ => ty::AnonConstKind::NonTypeSystem,
1856 }
1857}