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 (is_alias, is_auto, safety, items) = match item.kind {
848 hir::ItemKind::Trait(is_auto, safety, .., items) => {
849 (false, is_auto == hir::IsAuto::Yes, safety, items)
850 }
851 hir::ItemKind::TraitAlias(..) => (true, false, hir::Safety::Safe, &[][..]),
852 _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
853 };
854
855 let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
857 hir::Constness::Const
858 } else {
859 hir::Constness::NotConst
860 };
861
862 let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
863 if paren_sugar && !tcx.features().unboxed_closures() {
864 tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
865 }
866
867 let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
869
870 let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
871 let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
872
873 let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
874 tcx.get_all_attrs(def_id),
875 AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
876 )
877 .unwrap_or([false; 2]);
878
879 let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
880 ty::trait_def::TraitSpecializationKind::Marker
881 } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
882 ty::trait_def::TraitSpecializationKind::AlwaysApplicable
883 } else {
884 ty::trait_def::TraitSpecializationKind::None
885 };
886 let must_implement_one_of = tcx
887 .get_attr(def_id, sym::rustc_must_implement_one_of)
888 .and_then(|attr| match attr.meta_item_list() {
891 Some(items) if items.len() < 2 => {
892 tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
893
894 None
895 }
896 Some(items) => items
897 .into_iter()
898 .map(|item| item.ident().ok_or(item.span()))
899 .collect::<Result<Box<[_]>, _>>()
900 .map_err(|span| {
901 tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
902 })
903 .ok()
904 .zip(Some(attr.span())),
905 None => None,
907 })
908 .and_then(|(list, attr_span)| {
911 let errors = list.iter().filter_map(|ident| {
912 let item = items.iter().find(|item| item.ident == *ident);
913
914 match item {
915 Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => {
916 if !tcx.defaultness(item.id.owner_id).has_value() {
917 tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
918 span: item.span,
919 note_span: attr_span,
920 });
921
922 return Some(());
923 }
924
925 return None;
926 }
927 Some(item) => {
928 tcx.dcx().emit_err(errors::MustImplementNotFunction {
929 span: item.span,
930 span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
931 note: errors::MustImplementNotFunctionNote {},
932 });
933 }
934 None => {
935 tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
936 }
937 }
938
939 Some(())
940 });
941
942 (errors.count() == 0).then_some(list)
943 })
944 .and_then(|list| {
946 let mut set: UnordMap<Symbol, Span> = Default::default();
947 let mut no_dups = true;
948
949 for ident in &*list {
950 if let Some(dup) = set.insert(ident.name, ident.span) {
951 tcx.dcx()
952 .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
953
954 no_dups = false;
955 }
956 }
957
958 no_dups.then_some(list)
959 });
960
961 let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
962 let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
963
964 ty::TraitDef {
965 def_id: def_id.to_def_id(),
966 safety,
967 constness,
968 paren_sugar,
969 has_auto_impl: is_auto,
970 is_marker,
971 is_coinductive: rustc_coinductive || is_auto,
972 is_fundamental,
973 skip_array_during_method_dispatch,
974 skip_boxed_slice_during_method_dispatch,
975 specialization_kind,
976 must_implement_one_of,
977 implement_via_object,
978 deny_explicit_impl,
979 }
980}
981
982#[instrument(level = "debug", skip(tcx), ret)]
983fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
984 use rustc_hir::Node::*;
985 use rustc_hir::*;
986
987 let hir_id = tcx.local_def_id_to_hir_id(def_id);
988
989 let icx = ItemCtxt::new(tcx, def_id);
990
991 let output = match tcx.hir_node(hir_id) {
992 TraitItem(hir::TraitItem {
993 kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
994 generics,
995 ..
996 })
997 | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
998 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
999 }
1000
1001 ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
1002 if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1004 && i.of_trait.is_some()
1005 {
1006 icx.lowerer().lower_fn_ty(
1007 hir_id,
1008 sig.header.safety(),
1009 sig.header.abi,
1010 sig.decl,
1011 Some(generics),
1012 None,
1013 )
1014 } else {
1015 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1016 }
1017 }
1018
1019 TraitItem(hir::TraitItem {
1020 kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1021 generics,
1022 ..
1023 }) => icx.lowerer().lower_fn_ty(
1024 hir_id,
1025 header.safety(),
1026 header.abi,
1027 decl,
1028 Some(generics),
1029 None,
1030 ),
1031
1032 ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1033 let abi = tcx.hir_get_foreign_abi(hir_id);
1034 compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1035 }
1036
1037 Ctor(data) => {
1038 assert_matches!(data.ctor(), Some(_));
1039 let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1040 let ty = tcx.type_of(adt_def_id).instantiate_identity();
1041 let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1042 let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1044 (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1045 _ => hir::Safety::Unsafe,
1046 };
1047 ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1048 }
1049
1050 Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1051 bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1062 }
1063
1064 x => {
1065 bug!("unexpected sort of node in fn_sig(): {:?}", x);
1066 }
1067 };
1068 ty::EarlyBinder::bind(output)
1069}
1070
1071fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1072 icx: &ItemCtxt<'tcx>,
1073 sig: &'tcx hir::FnSig<'tcx>,
1074 generics: &'tcx hir::Generics<'tcx>,
1075 def_id: LocalDefId,
1076) -> ty::PolyFnSig<'tcx> {
1077 if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1078 return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1079 }
1080
1081 icx.lowerer().lower_fn_ty(
1082 icx.tcx().local_def_id_to_hir_id(def_id),
1083 sig.header.safety(),
1084 sig.header.abi,
1085 sig.decl,
1086 Some(generics),
1087 None,
1088 )
1089}
1090
1091fn recover_infer_ret_ty<'tcx>(
1092 icx: &ItemCtxt<'tcx>,
1093 infer_ret_ty: &'tcx hir::Ty<'tcx>,
1094 generics: &'tcx hir::Generics<'tcx>,
1095 def_id: LocalDefId,
1096) -> ty::PolyFnSig<'tcx> {
1097 let tcx = icx.tcx;
1098 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1099
1100 let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1101
1102 let has_region_params = generics.params.iter().any(|param| match param.kind {
1107 GenericParamKind::Lifetime { .. } => true,
1108 _ => false,
1109 });
1110 let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1111 ty::ReErased => {
1112 if has_region_params {
1113 ty::Region::new_error_with_message(
1114 tcx,
1115 DUMMY_SP,
1116 "erased region is not allowed here in return type",
1117 )
1118 } else {
1119 tcx.lifetimes.re_static
1120 }
1121 }
1122 _ => r,
1123 });
1124
1125 let mut visitor = HirPlaceholderCollector::default();
1126 visitor.visit_ty_unambig(infer_ret_ty);
1127
1128 let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1129 let ret_ty = fn_sig.output();
1130
1131 let mut recovered_ret_ty = None;
1135 if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1136 diag.span_suggestion(
1137 infer_ret_ty.span,
1138 "replace with the correct return type",
1139 suggestable_ret_ty,
1140 Applicability::MachineApplicable,
1141 );
1142 recovered_ret_ty = Some(suggestable_ret_ty);
1143 } else if let Some(sugg) = suggest_impl_trait(
1144 &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1145 tcx.param_env(def_id),
1146 ret_ty,
1147 ) {
1148 diag.span_suggestion(
1149 infer_ret_ty.span,
1150 "replace with an appropriate return type",
1151 sugg,
1152 Applicability::MachineApplicable,
1153 );
1154 } else if ret_ty.is_closure() {
1155 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1156 }
1157
1158 if ret_ty.is_closure() {
1160 diag.note(
1161 "for more information on `Fn` traits and closure types, see \
1162 https://doc.rust-lang.org/book/ch13-01-closures.html",
1163 );
1164 }
1165 let guar = diag.emit();
1166 ty::Binder::dummy(tcx.mk_fn_sig(
1167 fn_sig.inputs().iter().copied(),
1168 recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1169 fn_sig.c_variadic,
1170 fn_sig.safety,
1171 fn_sig.abi,
1172 ))
1173}
1174
1175pub fn suggest_impl_trait<'tcx>(
1176 infcx: &InferCtxt<'tcx>,
1177 param_env: ty::ParamEnv<'tcx>,
1178 ret_ty: Ty<'tcx>,
1179) -> Option<String> {
1180 let format_as_assoc: fn(_, _, _, _, _) -> _ =
1181 |tcx: TyCtxt<'tcx>,
1182 _: ty::GenericArgsRef<'tcx>,
1183 trait_def_id: DefId,
1184 assoc_item_def_id: DefId,
1185 item_ty: Ty<'tcx>| {
1186 let trait_name = tcx.item_name(trait_def_id);
1187 let assoc_name = tcx.item_name(assoc_item_def_id);
1188 Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1189 };
1190 let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1191 |tcx: TyCtxt<'tcx>,
1192 args: ty::GenericArgsRef<'tcx>,
1193 trait_def_id: DefId,
1194 _: DefId,
1195 item_ty: Ty<'tcx>| {
1196 let trait_name = tcx.item_name(trait_def_id);
1197 let args_tuple = args.type_at(1);
1198 let ty::Tuple(types) = *args_tuple.kind() else {
1199 return None;
1200 };
1201 let types = types.make_suggestable(tcx, false, None)?;
1202 let maybe_ret =
1203 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1204 Some(format!(
1205 "impl {trait_name}({}){maybe_ret}",
1206 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1207 ))
1208 };
1209
1210 for (trait_def_id, assoc_item_def_id, formatter) in [
1211 (
1212 infcx.tcx.get_diagnostic_item(sym::Iterator),
1213 infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1214 format_as_assoc,
1215 ),
1216 (
1217 infcx.tcx.lang_items().future_trait(),
1218 infcx.tcx.lang_items().future_output(),
1219 format_as_assoc,
1220 ),
1221 (
1222 infcx.tcx.lang_items().fn_trait(),
1223 infcx.tcx.lang_items().fn_once_output(),
1224 format_as_parenthesized,
1225 ),
1226 (
1227 infcx.tcx.lang_items().fn_mut_trait(),
1228 infcx.tcx.lang_items().fn_once_output(),
1229 format_as_parenthesized,
1230 ),
1231 (
1232 infcx.tcx.lang_items().fn_once_trait(),
1233 infcx.tcx.lang_items().fn_once_output(),
1234 format_as_parenthesized,
1235 ),
1236 ] {
1237 let Some(trait_def_id) = trait_def_id else {
1238 continue;
1239 };
1240 let Some(assoc_item_def_id) = assoc_item_def_id else {
1241 continue;
1242 };
1243 if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1244 continue;
1245 }
1246 let sugg = infcx.probe(|_| {
1247 let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1248 if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1249 });
1250 if !infcx
1251 .type_implements_trait(trait_def_id, args, param_env)
1252 .must_apply_modulo_regions()
1253 {
1254 return None;
1255 }
1256 let ocx = ObligationCtxt::new(&infcx);
1257 let item_ty = ocx.normalize(
1258 &ObligationCause::dummy(),
1259 param_env,
1260 Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1261 );
1262 if ocx.select_where_possible().is_empty()
1264 && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1265 && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1266 && let Some(sugg) = formatter(
1267 infcx.tcx,
1268 infcx.resolve_vars_if_possible(args),
1269 trait_def_id,
1270 assoc_item_def_id,
1271 item_ty,
1272 )
1273 {
1274 return Some(sugg);
1275 }
1276
1277 None
1278 });
1279
1280 if sugg.is_some() {
1281 return sugg;
1282 }
1283 }
1284 None
1285}
1286
1287fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
1288 let icx = ItemCtxt::new(tcx, def_id);
1289 let item = tcx.hir_expect_item(def_id);
1290 let impl_ = item.expect_impl();
1291 impl_.of_trait.as_ref().map(|ast_trait_ref| {
1292 let selfty = tcx.type_of(def_id).instantiate_identity();
1293
1294 check_impl_constness(tcx, impl_.constness, ast_trait_ref);
1295
1296 let trait_ref = icx.lowerer().lower_impl_trait_ref(ast_trait_ref, selfty);
1297
1298 ty::ImplTraitHeader {
1299 trait_ref: ty::EarlyBinder::bind(trait_ref),
1300 safety: impl_.safety,
1301 polarity: polarity_of_impl(tcx, def_id, impl_, item.span),
1302 constness: impl_.constness,
1303 }
1304 })
1305}
1306
1307fn check_impl_constness(
1308 tcx: TyCtxt<'_>,
1309 constness: hir::Constness,
1310 hir_trait_ref: &hir::TraitRef<'_>,
1311) {
1312 if let hir::Constness::NotConst = constness {
1313 return;
1314 }
1315
1316 let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1317 if tcx.is_const_trait(trait_def_id) {
1318 return;
1319 }
1320
1321 let trait_name = tcx.item_name(trait_def_id).to_string();
1322 let (local_trait_span, suggestion_pre) =
1323 match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1324 (true, true) => (
1325 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1326 if tcx.features().const_trait_impl() {
1327 ""
1328 } else {
1329 "enable `#![feature(const_trait_impl)]` in your crate and "
1330 },
1331 ),
1332 (false, _) | (_, false) => (None, ""),
1333 };
1334 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1335 trait_ref_span: hir_trait_ref.path.span,
1336 trait_name,
1337 local_trait_span,
1338 suggestion_pre,
1339 marking: (),
1340 adding: (),
1341 });
1342}
1343
1344fn polarity_of_impl(
1345 tcx: TyCtxt<'_>,
1346 def_id: LocalDefId,
1347 impl_: &hir::Impl<'_>,
1348 span: Span,
1349) -> ty::ImplPolarity {
1350 let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1351 match &impl_ {
1352 hir::Impl { polarity: hir::ImplPolarity::Negative(span), of_trait, .. } => {
1353 if is_rustc_reservation {
1354 let span = span.to(of_trait.as_ref().map_or(*span, |t| t.path.span));
1355 tcx.dcx().span_err(span, "reservation impls can't be negative");
1356 }
1357 ty::ImplPolarity::Negative
1358 }
1359 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: None, .. } => {
1360 if is_rustc_reservation {
1361 tcx.dcx().span_err(span, "reservation impls can't be inherent");
1362 }
1363 ty::ImplPolarity::Positive
1364 }
1365 hir::Impl { polarity: hir::ImplPolarity::Positive, of_trait: Some(_), .. } => {
1366 if is_rustc_reservation {
1367 ty::ImplPolarity::Reservation
1368 } else {
1369 ty::ImplPolarity::Positive
1370 }
1371 }
1372 }
1373}
1374
1375fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1381 tcx: TyCtxt<'tcx>,
1382 generics: &'a hir::Generics<'a>,
1383) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1384 generics.params.iter().filter(move |param| match param.kind {
1385 GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1386 _ => false,
1387 })
1388}
1389
1390fn compute_sig_of_foreign_fn_decl<'tcx>(
1391 tcx: TyCtxt<'tcx>,
1392 def_id: LocalDefId,
1393 decl: &'tcx hir::FnDecl<'tcx>,
1394 abi: ExternAbi,
1395 safety: hir::Safety,
1396) -> ty::PolyFnSig<'tcx> {
1397 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1398 let fty =
1399 ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1400
1401 if !tcx.features().simd_ffi() {
1404 let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1405 if ty.is_simd() {
1406 let snip = tcx
1407 .sess
1408 .source_map()
1409 .span_to_snippet(hir_ty.span)
1410 .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
1411 tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1412 }
1413 };
1414 for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1415 check(input, *ty)
1416 }
1417 if let hir::FnRetTy::Return(ty) = decl.output {
1418 check(ty, fty.output().skip_binder())
1419 }
1420 }
1421
1422 fty
1423}
1424
1425fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1426 match tcx.hir_node_by_def_id(def_id) {
1427 Node::Expr(&hir::Expr {
1428 kind:
1429 hir::ExprKind::Closure(&rustc_hir::Closure {
1430 kind: hir::ClosureKind::Coroutine(kind),
1431 ..
1432 }),
1433 ..
1434 }) => Some(kind),
1435 _ => None,
1436 }
1437}
1438
1439fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1440 let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1441 tcx.hir_node_by_def_id(def_id).expect_closure()
1442 else {
1443 bug!()
1444 };
1445
1446 let &hir::Expr {
1447 kind:
1448 hir::ExprKind::Closure(&rustc_hir::Closure {
1449 def_id,
1450 kind: hir::ClosureKind::Coroutine(_),
1451 ..
1452 }),
1453 ..
1454 } = tcx.hir_body(body).value
1455 else {
1456 bug!()
1457 };
1458
1459 def_id.to_def_id()
1460}
1461
1462fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1463 match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1464 hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1465 hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1466 }
1467 hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1468 hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1469 }
1470 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1471 hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1472 }
1473 }
1474}
1475
1476fn rendered_precise_capturing_args<'tcx>(
1477 tcx: TyCtxt<'tcx>,
1478 def_id: LocalDefId,
1479) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1480 if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1481 tcx.opt_rpitit_info(def_id.to_def_id())
1482 {
1483 return tcx.rendered_precise_capturing_args(opaque_def_id);
1484 }
1485
1486 tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1487 hir::GenericBound::Use(args, ..) => {
1488 Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1489 PreciseCapturingArgKind::Lifetime(_) => {
1490 PreciseCapturingArgKind::Lifetime(arg.name())
1491 }
1492 PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1493 })))
1494 }
1495 _ => None,
1496 })
1497}
1498
1499fn const_param_default<'tcx>(
1500 tcx: TyCtxt<'tcx>,
1501 def_id: LocalDefId,
1502) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1503 let default_ct = match tcx.hir_node_by_def_id(def_id) {
1504 hir::Node::GenericParam(hir::GenericParam {
1505 kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1506 ..
1507 }) => ct,
1508 _ => span_bug!(
1509 tcx.def_span(def_id),
1510 "`const_param_default` expected a generic parameter with a constant"
1511 ),
1512 };
1513 let icx = ItemCtxt::new(tcx, def_id);
1514 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1515 let ct = icx
1516 .lowerer()
1517 .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1518 ty::EarlyBinder::bind(ct)
1519}
1520
1521fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1522 let hir_id = tcx.local_def_id_to_hir_id(def);
1523 let const_arg_id = tcx.parent_hir_id(hir_id);
1524 match tcx.hir_node(const_arg_id) {
1525 hir::Node::ConstArg(_) => {
1526 if tcx.features().generic_const_exprs() {
1527 ty::AnonConstKind::GCE
1528 } else if tcx.features().min_generic_const_args() {
1529 ty::AnonConstKind::MCG
1530 } else if let hir::Node::Expr(hir::Expr {
1531 kind: hir::ExprKind::Repeat(_, repeat_count),
1532 ..
1533 }) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
1534 && repeat_count.hir_id == const_arg_id
1535 {
1536 ty::AnonConstKind::RepeatExprCount
1537 } else {
1538 ty::AnonConstKind::MCG
1539 }
1540 }
1541 _ => ty::AnonConstKind::NonTypeSystem,
1542 }
1543}