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