1use std::assert_matches::assert_matches;
18use std::cell::Cell;
19use std::iter;
20use std::ops::Bound;
21
22use rustc_abi::ExternAbi;
23use rustc_ast::Recovered;
24use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
25use rustc_data_structures::unord::UnordMap;
26use rustc_errors::{
27 Applicability, Diag, DiagCtxtHandle, E0228, ErrorGuaranteed, StashKey, struct_span_code_err,
28};
29use rustc_hir::attrs::AttributeKind;
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, find_attr};
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 && 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 self.lowerer().lower_ty(a)
542 })
543 .collect();
544
545 let output_ty = match decl.output {
546 hir::FnRetTy::Return(output) => {
547 if let hir::TyKind::Infer(()) = output.kind
548 && let Some(suggested_ty) =
549 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
550 {
551 infer_replacements.push((output.span, suggested_ty.to_string()));
552 Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
553 } else {
554 self.lower_ty(output)
555 }
556 }
557 hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
558 };
559
560 if !infer_replacements.is_empty() {
561 self.report_placeholder_type_error(vec![], infer_replacements);
562 }
563 (input_tys, output_ty)
564 }
565
566 fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
567 hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
568 }
569}
570
571fn get_new_lifetime_name<'tcx>(
573 tcx: TyCtxt<'tcx>,
574 poly_trait_ref: ty::PolyTraitRef<'tcx>,
575 generics: &hir::Generics<'tcx>,
576) -> String {
577 let existing_lifetimes = tcx
578 .collect_referenced_late_bound_regions(poly_trait_ref)
579 .into_iter()
580 .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
581 .chain(generics.params.iter().filter_map(|param| {
582 if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind {
583 Some(param.name.ident().as_str().to_string())
584 } else {
585 None
586 }
587 }))
588 .collect::<FxHashSet<String>>();
589
590 let a_to_z_repeat_n = |n| {
591 (b'a'..=b'z').map(move |c| {
592 let mut s = '\''.to_string();
593 s.extend(std::iter::repeat(char::from(c)).take(n));
594 s
595 })
596 };
597
598 (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
600}
601
602pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
603 tcx.ensure_ok().generics_of(def_id);
604 tcx.ensure_ok().type_of(def_id);
605 tcx.ensure_ok().predicates_of(def_id);
606}
607
608pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
609 let def = tcx.adt_def(def_id);
610 let repr_type = def.repr().discr_type();
611 let initial = repr_type.initial_discriminant(tcx);
612 let mut prev_discr = None::<Discr<'_>>;
613
614 for variant in def.variants() {
616 let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
617 prev_discr = Some(
618 if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
619 def.eval_explicit_discr(tcx, const_def_id).ok()
620 } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
621 Some(discr)
622 } else {
623 let span = tcx.def_span(variant.def_id);
624 tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
625 span,
626 discr: prev_discr.unwrap().to_string(),
627 item_name: tcx.item_ident(variant.def_id),
628 wrapped_discr: wrapped_discr.to_string(),
629 });
630 None
631 }
632 .unwrap_or(wrapped_discr),
633 );
634
635 for f in &variant.fields {
636 tcx.ensure_ok().generics_of(f.did);
637 tcx.ensure_ok().type_of(f.did);
638 tcx.ensure_ok().predicates_of(f.did);
639 }
640
641 if let Some(ctor_def_id) = variant.ctor_def_id() {
643 lower_variant_ctor(tcx, ctor_def_id.expect_local());
644 }
645 }
646}
647
648#[derive(Clone, Copy)]
649struct NestedSpan {
650 span: Span,
651 nested_field_span: Span,
652}
653
654impl NestedSpan {
655 fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
656 errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
657 }
658}
659
660#[derive(Clone, Copy)]
661enum FieldDeclSpan {
662 NotNested(Span),
663 Nested(NestedSpan),
664}
665
666impl From<Span> for FieldDeclSpan {
667 fn from(span: Span) -> Self {
668 Self::NotNested(span)
669 }
670}
671
672impl From<NestedSpan> for FieldDeclSpan {
673 fn from(span: NestedSpan) -> Self {
674 Self::Nested(span)
675 }
676}
677
678struct FieldUniquenessCheckContext<'tcx> {
679 tcx: TyCtxt<'tcx>,
680 seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
681}
682
683impl<'tcx> FieldUniquenessCheckContext<'tcx> {
684 fn new(tcx: TyCtxt<'tcx>) -> Self {
685 Self { tcx, seen_fields: FxIndexMap::default() }
686 }
687
688 fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
690 use FieldDeclSpan::*;
691 let field_name = field_name.normalize_to_macros_2_0();
692 match (field_decl, self.seen_fields.get(&field_name).copied()) {
693 (NotNested(span), Some(NotNested(prev_span))) => {
694 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
695 field_name,
696 span,
697 prev_span,
698 });
699 }
700 (NotNested(span), Some(Nested(prev))) => {
701 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
702 field_name,
703 span,
704 prev_span: prev.span,
705 prev_nested_field_span: prev.nested_field_span,
706 prev_help: prev.to_field_already_declared_nested_help(),
707 });
708 }
709 (
710 Nested(current @ NestedSpan { span, nested_field_span, .. }),
711 Some(NotNested(prev_span)),
712 ) => {
713 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
714 field_name,
715 span,
716 nested_field_span,
717 help: current.to_field_already_declared_nested_help(),
718 prev_span,
719 });
720 }
721 (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
722 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
723 field_name,
724 span,
725 nested_field_span,
726 help: current.to_field_already_declared_nested_help(),
727 prev_span: prev.span,
728 prev_nested_field_span: prev.nested_field_span,
729 prev_help: prev.to_field_already_declared_nested_help(),
730 });
731 }
732 (field_decl, None) => {
733 self.seen_fields.insert(field_name, field_decl);
734 }
735 }
736 }
737}
738
739fn lower_variant<'tcx>(
740 tcx: TyCtxt<'tcx>,
741 variant_did: Option<LocalDefId>,
742 ident: Ident,
743 discr: ty::VariantDiscr,
744 def: &hir::VariantData<'tcx>,
745 adt_kind: ty::AdtKind,
746 parent_did: LocalDefId,
747) -> ty::VariantDef {
748 let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
749 let fields = def
750 .fields()
751 .iter()
752 .inspect(|field| {
753 field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
754 })
755 .map(|f| ty::FieldDef {
756 did: f.def_id.to_def_id(),
757 name: f.ident.name,
758 vis: tcx.visibility(f.def_id),
759 safety: f.safety,
760 value: f.default.map(|v| v.def_id.to_def_id()),
761 })
762 .collect();
763 let recovered = match def {
764 hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
765 _ => None,
766 };
767 ty::VariantDef::new(
768 ident.name,
769 variant_did.map(LocalDefId::to_def_id),
770 def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
771 discr,
772 fields,
773 parent_did.to_def_id(),
774 recovered,
775 adt_kind == AdtKind::Struct
776 && find_attr!(tcx.get_all_attrs(parent_did), AttributeKind::NonExhaustive(..))
777 || variant_did.is_some_and(|variant_did| {
778 find_attr!(tcx.get_all_attrs(variant_did), AttributeKind::NonExhaustive(..))
779 }),
780 )
781}
782
783fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
784 use rustc_hir::*;
785
786 let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
787 bug!("expected ADT to be an item");
788 };
789
790 let repr = tcx.repr_options_of_def(def_id);
791 let (kind, variants) = match &item.kind {
792 ItemKind::Enum(_, _, def) => {
793 let mut distance_from_explicit = 0;
794 let variants = def
795 .variants
796 .iter()
797 .map(|v| {
798 let discr = if let Some(e) = &v.disr_expr {
799 distance_from_explicit = 0;
800 ty::VariantDiscr::Explicit(e.def_id.to_def_id())
801 } else {
802 ty::VariantDiscr::Relative(distance_from_explicit)
803 };
804 distance_from_explicit += 1;
805
806 lower_variant(
807 tcx,
808 Some(v.def_id),
809 v.ident,
810 discr,
811 &v.data,
812 AdtKind::Enum,
813 def_id,
814 )
815 })
816 .collect();
817
818 (AdtKind::Enum, variants)
819 }
820 ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
821 let adt_kind = match item.kind {
822 ItemKind::Struct(..) => AdtKind::Struct,
823 _ => AdtKind::Union,
824 };
825 let variants = std::iter::once(lower_variant(
826 tcx,
827 None,
828 *ident,
829 ty::VariantDiscr::Relative(0),
830 def,
831 adt_kind,
832 def_id,
833 ))
834 .collect();
835
836 (adt_kind, variants)
837 }
838 _ => bug!("{:?} is not an ADT", item.owner_id.def_id),
839 };
840 tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
841}
842
843fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
844 let item = tcx.hir_expect_item(def_id);
845
846 let (constness, is_alias, is_auto, safety) = match item.kind {
847 hir::ItemKind::Trait(constness, is_auto, safety, ..) => {
848 (constness, false, is_auto == hir::IsAuto::Yes, safety)
849 }
850 hir::ItemKind::TraitAlias(..) => (hir::Constness::NotConst, true, false, hir::Safety::Safe),
851 _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
852 };
853
854 let attrs = tcx.get_all_attrs(def_id);
855 let constness = if constness == hir::Constness::Const
858 || !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_))
859 {
860 hir::Constness::Const
861 } else {
862 hir::Constness::NotConst
863 };
864
865 let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_));
866 if paren_sugar && !tcx.features().unboxed_closures() {
867 tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
868 }
869
870 let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_));
872
873 let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_));
874 let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental);
875
876 let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
877 attrs,
878 AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
879 )
880 .unwrap_or([false; 2]);
881
882 let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) {
883 ty::trait_def::TraitSpecializationKind::Marker
884 } else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) {
885 ty::trait_def::TraitSpecializationKind::AlwaysApplicable
886 } else {
887 ty::trait_def::TraitSpecializationKind::None
888 };
889 let must_implement_one_of = attrs
890 .iter()
891 .find(|attr| attr.has_name(sym::rustc_must_implement_one_of))
892 .and_then(|attr| match attr.meta_item_list() {
895 Some(items) if items.len() < 2 => {
896 tcx.dcx().emit_err(errors::MustImplementOneOfAttribute { span: attr.span() });
897
898 None
899 }
900 Some(items) => items
901 .into_iter()
902 .map(|item| item.ident().ok_or(item.span()))
903 .collect::<Result<Box<[_]>, _>>()
904 .map_err(|span| {
905 tcx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span });
906 })
907 .ok()
908 .zip(Some(attr.span())),
909 None => None,
911 })
912 .and_then(|(list, attr_span)| {
915 let errors = list.iter().filter_map(|ident| {
916 let item = tcx
917 .associated_items(def_id)
918 .filter_by_name_unhygienic(ident.name)
919 .find(|item| item.ident(tcx) == *ident);
920
921 match item {
922 Some(item) if matches!(item.kind, ty::AssocKind::Fn { .. }) => {
923 if !item.defaultness(tcx).has_value() {
924 tcx.dcx().emit_err(errors::FunctionNotHaveDefaultImplementation {
925 span: tcx.def_span(item.def_id),
926 note_span: attr_span,
927 });
928
929 return Some(());
930 }
931
932 return None;
933 }
934 Some(item) => {
935 tcx.dcx().emit_err(errors::MustImplementNotFunction {
936 span: tcx.def_span(item.def_id),
937 span_note: errors::MustImplementNotFunctionSpanNote { span: attr_span },
938 note: errors::MustImplementNotFunctionNote {},
939 });
940 }
941 None => {
942 tcx.dcx().emit_err(errors::FunctionNotFoundInTrait { span: ident.span });
943 }
944 }
945
946 Some(())
947 });
948
949 (errors.count() == 0).then_some(list)
950 })
951 .and_then(|list| {
953 let mut set: UnordMap<Symbol, Span> = Default::default();
954 let mut no_dups = true;
955
956 for ident in &*list {
957 if let Some(dup) = set.insert(ident.name, ident.span) {
958 tcx.dcx()
959 .emit_err(errors::FunctionNamesDuplicated { spans: vec![dup, ident.span] });
960
961 no_dups = false;
962 }
963 }
964
965 no_dups.then_some(list)
966 });
967
968 let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
969 let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));
970
971 ty::TraitDef {
972 def_id: def_id.to_def_id(),
973 safety,
974 constness,
975 paren_sugar,
976 has_auto_impl: is_auto,
977 is_marker,
978 is_coinductive: rustc_coinductive || is_auto,
979 is_fundamental,
980 skip_array_during_method_dispatch,
981 skip_boxed_slice_during_method_dispatch,
982 specialization_kind,
983 must_implement_one_of,
984 implement_via_object,
985 deny_explicit_impl,
986 }
987}
988
989#[instrument(level = "debug", skip(tcx), ret)]
990fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
991 use rustc_hir::Node::*;
992 use rustc_hir::*;
993
994 let hir_id = tcx.local_def_id_to_hir_id(def_id);
995
996 let icx = ItemCtxt::new(tcx, def_id);
997
998 let output = match tcx.hir_node(hir_id) {
999 TraitItem(hir::TraitItem {
1000 kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
1001 generics,
1002 ..
1003 })
1004 | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
1005 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1006 }
1007
1008 ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
1009 if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1011 && i.of_trait.is_some()
1012 {
1013 icx.lowerer().lower_fn_ty(
1014 hir_id,
1015 sig.header.safety(),
1016 sig.header.abi,
1017 sig.decl,
1018 Some(generics),
1019 None,
1020 )
1021 } else {
1022 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1023 }
1024 }
1025
1026 TraitItem(hir::TraitItem {
1027 kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1028 generics,
1029 ..
1030 }) => icx.lowerer().lower_fn_ty(
1031 hir_id,
1032 header.safety(),
1033 header.abi,
1034 decl,
1035 Some(generics),
1036 None,
1037 ),
1038
1039 ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1040 let abi = tcx.hir_get_foreign_abi(hir_id);
1041 compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1042 }
1043
1044 Ctor(data) => {
1045 assert_matches!(data.ctor(), Some(_));
1046 let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1047 let ty = tcx.type_of(adt_def_id).instantiate_identity();
1048 let inputs = data.fields().iter().map(|f| tcx.type_of(f.def_id).instantiate_identity());
1049 let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1051 (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1052 _ => hir::Safety::Unsafe,
1053 };
1054 ty::Binder::dummy(tcx.mk_fn_sig(inputs, ty, false, safety, ExternAbi::Rust))
1055 }
1056
1057 Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1058 bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1069 }
1070
1071 x => {
1072 bug!("unexpected sort of node in fn_sig(): {:?}", x);
1073 }
1074 };
1075 ty::EarlyBinder::bind(output)
1076}
1077
1078fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1079 icx: &ItemCtxt<'tcx>,
1080 sig: &'tcx hir::FnSig<'tcx>,
1081 generics: &'tcx hir::Generics<'tcx>,
1082 def_id: LocalDefId,
1083) -> ty::PolyFnSig<'tcx> {
1084 if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1085 return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1086 }
1087
1088 icx.lowerer().lower_fn_ty(
1089 icx.tcx().local_def_id_to_hir_id(def_id),
1090 sig.header.safety(),
1091 sig.header.abi,
1092 sig.decl,
1093 Some(generics),
1094 None,
1095 )
1096}
1097
1098fn recover_infer_ret_ty<'tcx>(
1099 icx: &ItemCtxt<'tcx>,
1100 infer_ret_ty: &'tcx hir::Ty<'tcx>,
1101 generics: &'tcx hir::Generics<'tcx>,
1102 def_id: LocalDefId,
1103) -> ty::PolyFnSig<'tcx> {
1104 let tcx = icx.tcx;
1105 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1106
1107 let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1108
1109 let has_region_params = generics.params.iter().any(|param| match param.kind {
1114 GenericParamKind::Lifetime { .. } => true,
1115 _ => false,
1116 });
1117 let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1118 ty::ReErased => {
1119 if has_region_params {
1120 ty::Region::new_error_with_message(
1121 tcx,
1122 DUMMY_SP,
1123 "erased region is not allowed here in return type",
1124 )
1125 } else {
1126 tcx.lifetimes.re_static
1127 }
1128 }
1129 _ => r,
1130 });
1131
1132 let mut visitor = HirPlaceholderCollector::default();
1133 visitor.visit_ty_unambig(infer_ret_ty);
1134
1135 let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1136 let ret_ty = fn_sig.output();
1137
1138 let mut recovered_ret_ty = None;
1142 if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1143 diag.span_suggestion(
1144 infer_ret_ty.span,
1145 "replace with the correct return type",
1146 suggestable_ret_ty,
1147 Applicability::MachineApplicable,
1148 );
1149 recovered_ret_ty = Some(suggestable_ret_ty);
1150 } else if let Some(sugg) = suggest_impl_trait(
1151 &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1152 tcx.param_env(def_id),
1153 ret_ty,
1154 ) {
1155 diag.span_suggestion(
1156 infer_ret_ty.span,
1157 "replace with an appropriate return type",
1158 sugg,
1159 Applicability::MachineApplicable,
1160 );
1161 } else if ret_ty.is_closure() {
1162 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1163 }
1164
1165 if ret_ty.is_closure() {
1167 diag.note(
1168 "for more information on `Fn` traits and closure types, see \
1169 https://doc.rust-lang.org/book/ch13-01-closures.html",
1170 );
1171 }
1172 let guar = diag.emit();
1173 ty::Binder::dummy(tcx.mk_fn_sig(
1174 fn_sig.inputs().iter().copied(),
1175 recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1176 fn_sig.c_variadic,
1177 fn_sig.safety,
1178 fn_sig.abi,
1179 ))
1180}
1181
1182pub fn suggest_impl_trait<'tcx>(
1183 infcx: &InferCtxt<'tcx>,
1184 param_env: ty::ParamEnv<'tcx>,
1185 ret_ty: Ty<'tcx>,
1186) -> Option<String> {
1187 let format_as_assoc: fn(_, _, _, _, _) -> _ =
1188 |tcx: TyCtxt<'tcx>,
1189 _: ty::GenericArgsRef<'tcx>,
1190 trait_def_id: DefId,
1191 assoc_item_def_id: DefId,
1192 item_ty: Ty<'tcx>| {
1193 let trait_name = tcx.item_name(trait_def_id);
1194 let assoc_name = tcx.item_name(assoc_item_def_id);
1195 Some(format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1196 };
1197 let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1198 |tcx: TyCtxt<'tcx>,
1199 args: ty::GenericArgsRef<'tcx>,
1200 trait_def_id: DefId,
1201 _: DefId,
1202 item_ty: Ty<'tcx>| {
1203 let trait_name = tcx.item_name(trait_def_id);
1204 let args_tuple = args.type_at(1);
1205 let ty::Tuple(types) = *args_tuple.kind() else {
1206 return None;
1207 };
1208 let types = types.make_suggestable(tcx, false, None)?;
1209 let maybe_ret =
1210 if item_ty.is_unit() { String::new() } else { format!(" -> {item_ty}") };
1211 Some(format!(
1212 "impl {trait_name}({}){maybe_ret}",
1213 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1214 ))
1215 };
1216
1217 for (trait_def_id, assoc_item_def_id, formatter) in [
1218 (
1219 infcx.tcx.get_diagnostic_item(sym::Iterator),
1220 infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1221 format_as_assoc,
1222 ),
1223 (
1224 infcx.tcx.lang_items().future_trait(),
1225 infcx.tcx.lang_items().future_output(),
1226 format_as_assoc,
1227 ),
1228 (
1229 infcx.tcx.lang_items().fn_trait(),
1230 infcx.tcx.lang_items().fn_once_output(),
1231 format_as_parenthesized,
1232 ),
1233 (
1234 infcx.tcx.lang_items().fn_mut_trait(),
1235 infcx.tcx.lang_items().fn_once_output(),
1236 format_as_parenthesized,
1237 ),
1238 (
1239 infcx.tcx.lang_items().fn_once_trait(),
1240 infcx.tcx.lang_items().fn_once_output(),
1241 format_as_parenthesized,
1242 ),
1243 ] {
1244 let Some(trait_def_id) = trait_def_id else {
1245 continue;
1246 };
1247 let Some(assoc_item_def_id) = assoc_item_def_id else {
1248 continue;
1249 };
1250 if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1251 continue;
1252 }
1253 let sugg = infcx.probe(|_| {
1254 let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1255 if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1256 });
1257 if !infcx
1258 .type_implements_trait(trait_def_id, args, param_env)
1259 .must_apply_modulo_regions()
1260 {
1261 return None;
1262 }
1263 let ocx = ObligationCtxt::new(&infcx);
1264 let item_ty = ocx.normalize(
1265 &ObligationCause::dummy(),
1266 param_env,
1267 Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args),
1268 );
1269 if ocx.select_where_possible().is_empty()
1271 && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1272 && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1273 && let Some(sugg) = formatter(
1274 infcx.tcx,
1275 infcx.resolve_vars_if_possible(args),
1276 trait_def_id,
1277 assoc_item_def_id,
1278 item_ty,
1279 )
1280 {
1281 return Some(sugg);
1282 }
1283
1284 None
1285 });
1286
1287 if sugg.is_some() {
1288 return sugg;
1289 }
1290 }
1291 None
1292}
1293
1294fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::ImplTraitHeader<'_>> {
1295 let icx = ItemCtxt::new(tcx, def_id);
1296 let item = tcx.hir_expect_item(def_id);
1297 let impl_ = item.expect_impl();
1298 let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl);
1299 if is_rustc_reservation && impl_.of_trait.is_none() {
1300 tcx.dcx().span_err(item.span, "reservation impls can't be inherent");
1301 }
1302 impl_.of_trait.map(|of_trait| {
1303 let selfty = tcx.type_of(def_id).instantiate_identity();
1304
1305 check_impl_constness(tcx, of_trait.constness, &of_trait.trait_ref);
1306
1307 let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
1308
1309 ty::ImplTraitHeader {
1310 trait_ref: ty::EarlyBinder::bind(trait_ref),
1311 safety: of_trait.safety,
1312 polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
1313 constness: of_trait.constness,
1314 }
1315 })
1316}
1317
1318fn check_impl_constness(
1319 tcx: TyCtxt<'_>,
1320 constness: hir::Constness,
1321 hir_trait_ref: &hir::TraitRef<'_>,
1322) {
1323 if let hir::Constness::NotConst = constness {
1324 return;
1325 }
1326
1327 let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1328 if tcx.is_const_trait(trait_def_id) {
1329 return;
1330 }
1331
1332 let trait_name = tcx.item_name(trait_def_id).to_string();
1333 let (local_trait_span, suggestion_pre) =
1334 match (trait_def_id.is_local(), tcx.sess.is_nightly_build()) {
1335 (true, true) => (
1336 Some(tcx.def_span(trait_def_id).shrink_to_lo()),
1337 if tcx.features().const_trait_impl() {
1338 ""
1339 } else {
1340 "enable `#![feature(const_trait_impl)]` in your crate and "
1341 },
1342 ),
1343 (false, _) | (_, false) => (None, ""),
1344 };
1345 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1346 trait_ref_span: hir_trait_ref.path.span,
1347 trait_name,
1348 local_trait_span,
1349 suggestion_pre,
1350 marking: (),
1351 adding: (),
1352 });
1353}
1354
1355fn polarity_of_impl(
1356 tcx: TyCtxt<'_>,
1357 of_trait: &hir::TraitImplHeader<'_>,
1358 is_rustc_reservation: bool,
1359) -> ty::ImplPolarity {
1360 match of_trait.polarity {
1361 hir::ImplPolarity::Negative(span) => {
1362 if is_rustc_reservation {
1363 let span = span.to(of_trait.trait_ref.path.span);
1364 tcx.dcx().span_err(span, "reservation impls can't be negative");
1365 }
1366 ty::ImplPolarity::Negative
1367 }
1368 hir::ImplPolarity::Positive => {
1369 if is_rustc_reservation {
1370 ty::ImplPolarity::Reservation
1371 } else {
1372 ty::ImplPolarity::Positive
1373 }
1374 }
1375 }
1376}
1377
1378fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1384 tcx: TyCtxt<'tcx>,
1385 generics: &'a hir::Generics<'a>,
1386) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1387 generics.params.iter().filter(move |param| match param.kind {
1388 GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1389 _ => false,
1390 })
1391}
1392
1393fn compute_sig_of_foreign_fn_decl<'tcx>(
1394 tcx: TyCtxt<'tcx>,
1395 def_id: LocalDefId,
1396 decl: &'tcx hir::FnDecl<'tcx>,
1397 abi: ExternAbi,
1398 safety: hir::Safety,
1399) -> ty::PolyFnSig<'tcx> {
1400 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1401 let fty =
1402 ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1403
1404 if !tcx.features().simd_ffi() {
1407 let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1408 if ty.is_simd() {
1409 let snip = tcx
1410 .sess
1411 .source_map()
1412 .span_to_snippet(hir_ty.span)
1413 .map_or_else(|_| String::new(), |s| format!(" `{s}`"));
1414 tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1415 }
1416 };
1417 for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1418 check(input, *ty)
1419 }
1420 if let hir::FnRetTy::Return(ty) = decl.output {
1421 check(ty, fty.output().skip_binder())
1422 }
1423 }
1424
1425 fty
1426}
1427
1428fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1429 match tcx.hir_node_by_def_id(def_id) {
1430 Node::Expr(&hir::Expr {
1431 kind:
1432 hir::ExprKind::Closure(&rustc_hir::Closure {
1433 kind: hir::ClosureKind::Coroutine(kind),
1434 ..
1435 }),
1436 ..
1437 }) => Some(kind),
1438 _ => None,
1439 }
1440}
1441
1442fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1443 let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1444 tcx.hir_node_by_def_id(def_id).expect_closure()
1445 else {
1446 bug!()
1447 };
1448
1449 let &hir::Expr {
1450 kind:
1451 hir::ExprKind::Closure(&rustc_hir::Closure {
1452 def_id,
1453 kind: hir::ClosureKind::Coroutine(_),
1454 ..
1455 }),
1456 ..
1457 } = tcx.hir_body(body).value
1458 else {
1459 bug!()
1460 };
1461
1462 def_id.to_def_id()
1463}
1464
1465fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1466 match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1467 hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1468 hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1469 }
1470 hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1471 hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1472 }
1473 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1474 hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1475 }
1476 }
1477}
1478
1479fn rendered_precise_capturing_args<'tcx>(
1480 tcx: TyCtxt<'tcx>,
1481 def_id: LocalDefId,
1482) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1483 if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1484 tcx.opt_rpitit_info(def_id.to_def_id())
1485 {
1486 return tcx.rendered_precise_capturing_args(opaque_def_id);
1487 }
1488
1489 tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1490 hir::GenericBound::Use(args, ..) => {
1491 Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1492 PreciseCapturingArgKind::Lifetime(_) => {
1493 PreciseCapturingArgKind::Lifetime(arg.name())
1494 }
1495 PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1496 })))
1497 }
1498 _ => None,
1499 })
1500}
1501
1502fn const_param_default<'tcx>(
1503 tcx: TyCtxt<'tcx>,
1504 def_id: LocalDefId,
1505) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1506 let default_ct = match tcx.hir_node_by_def_id(def_id) {
1507 hir::Node::GenericParam(hir::GenericParam {
1508 kind: hir::GenericParamKind::Const { default: Some(ct), .. },
1509 ..
1510 }) => ct,
1511 _ => span_bug!(
1512 tcx.def_span(def_id),
1513 "`const_param_default` expected a generic parameter with a constant"
1514 ),
1515 };
1516 let icx = ItemCtxt::new(tcx, def_id);
1517 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1518 let ct = icx
1519 .lowerer()
1520 .lower_const_arg(default_ct, FeedConstTy::Param(def_id.to_def_id(), identity_args));
1521 ty::EarlyBinder::bind(ct)
1522}
1523
1524fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1525 let hir_id = tcx.local_def_id_to_hir_id(def);
1526 let const_arg_id = tcx.parent_hir_id(hir_id);
1527 match tcx.hir_node(const_arg_id) {
1528 hir::Node::ConstArg(_) => {
1529 if tcx.features().generic_const_exprs() {
1530 ty::AnonConstKind::GCE
1531 } else if tcx.features().min_generic_const_args() {
1532 ty::AnonConstKind::MCG
1533 } else if let hir::Node::Expr(hir::Expr {
1534 kind: hir::ExprKind::Repeat(_, repeat_count),
1535 ..
1536 }) = tcx.hir_node(tcx.parent_hir_id(const_arg_id))
1537 && repeat_count.hir_id == const_arg_id
1538 {
1539 ty::AnonConstKind::RepeatExprCount
1540 } else {
1541 ty::AnonConstKind::MCG
1542 }
1543 }
1544 _ => ty::AnonConstKind::NonTypeSystem,
1545 }
1546}