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