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