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