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