1use std::cell::Cell;
18use std::ops::{Bound, ControlFlow};
19use std::{assert_matches, iter};
20
21use rustc_abi::{ExternAbi, Size};
22use rustc_ast::Recovered;
23use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
24use rustc_errors::{
25 Applicability, Diag, DiagCtxtHandle, Diagnostic, E0228, ErrorGuaranteed, Level, StashKey,
26};
27use rustc_hir::def::{DefKind, Res};
28use rustc_hir::def_id::{DefId, LocalDefId};
29use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt};
30use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr};
31use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
32use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause};
33use rustc_middle::hir::nested_filter;
34use rustc_middle::query::Providers;
35use rustc_middle::ty::util::{Discr, IntTypeExt};
36use rustc_middle::ty::{
37 self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized,
38 fold_regions,
39};
40use rustc_middle::{bug, span_bug};
41use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
42use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName;
43use rustc_trait_selection::infer::InferCtxtExt;
44use rustc_trait_selection::traits::{
45 FulfillmentError, ObligationCtxt, hir_ty_lowering_dyn_compatibility_violations,
46};
47use tracing::{debug, instrument};
48
49use crate::errors;
50use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason};
51
52pub(crate) mod dump;
53mod generics_of;
54mod item_bounds;
55mod predicates_of;
56mod resolve_bound_vars;
57mod type_of;
58
59pub(crate) fn provide(providers: &mut Providers) {
63 resolve_bound_vars::provide(providers);
64 *providers = Providers {
65 type_of: type_of::type_of,
66 type_of_opaque: type_of::type_of_opaque,
67 type_of_opaque_hir_typeck: type_of::type_of_opaque_hir_typeck,
68 type_alias_is_lazy: type_of::type_alias_is_lazy,
69 item_bounds: item_bounds::item_bounds,
70 explicit_item_bounds: item_bounds::explicit_item_bounds,
71 item_self_bounds: item_bounds::item_self_bounds,
72 explicit_item_self_bounds: item_bounds::explicit_item_self_bounds,
73 item_non_self_bounds: item_bounds::item_non_self_bounds,
74 impl_super_outlives: item_bounds::impl_super_outlives,
75 generics_of: generics_of::generics_of,
76 predicates_of: predicates_of::predicates_of,
77 explicit_predicates_of: predicates_of::explicit_predicates_of,
78 explicit_super_predicates_of: predicates_of::explicit_super_predicates_of,
79 explicit_implied_predicates_of: predicates_of::explicit_implied_predicates_of,
80 explicit_supertraits_containing_assoc_item:
81 predicates_of::explicit_supertraits_containing_assoc_item,
82 trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
83 const_conditions: predicates_of::const_conditions,
84 explicit_implied_const_bounds: predicates_of::explicit_implied_const_bounds,
85 type_param_predicates: predicates_of::type_param_predicates,
86 trait_def,
87 adt_def,
88 fn_sig,
89 impl_trait_header,
90 coroutine_kind,
91 coroutine_for_closure,
92 opaque_ty_origin,
93 rendered_precise_capturing_args,
94 const_param_default,
95 anon_const_kind,
96 const_of_item,
97 ..*providers
98 };
99}
100
101pub(crate) struct ItemCtxt<'tcx> {
131 tcx: TyCtxt<'tcx>,
132 item_def_id: LocalDefId,
133 tainted_by_errors: Cell<Option<ErrorGuaranteed>>,
134}
135
136#[derive(#[automatically_derived]
impl ::core::default::Default for HirPlaceholderCollector {
#[inline]
fn default() -> HirPlaceholderCollector {
HirPlaceholderCollector {
spans: ::core::default::Default::default(),
may_contain_const_infer: ::core::default::Default::default(),
}
}
}Default)]
139pub(crate) struct HirPlaceholderCollector {
140 pub spans: Vec<Span>,
141 pub may_contain_const_infer: bool,
144}
145
146impl<'v> Visitor<'v> for HirPlaceholderCollector {
147 fn visit_infer(&mut self, _inf_id: HirId, inf_span: Span, kind: InferKind<'v>) -> Self::Result {
148 self.spans.push(inf_span);
149
150 if let InferKind::Const(_) | InferKind::Ambig(_) = kind {
151 self.may_contain_const_infer = true;
152 }
153 }
154}
155
156fn placeholder_type_error_diag<'cx, 'tcx>(
157 cx: &'cx dyn HirTyLowerer<'tcx>,
158 generics: Option<&hir::Generics<'_>>,
159 placeholder_types: Vec<Span>,
160 additional_spans: Vec<Span>,
161 suggest: bool,
162 hir_ty: Option<&hir::Ty<'_>>,
163 kind: &'static str,
164) -> Diag<'cx> {
165 if placeholder_types.is_empty() {
166 return bad_placeholder(cx, additional_spans, kind);
167 }
168
169 let params = generics.map(|g| g.params).unwrap_or_default();
170 let type_name = params.next_type_param_name(None);
171 let mut sugg: Vec<_> =
172 placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect();
173
174 if let Some(generics) = generics {
175 if let Some(span) = params.iter().find_map(|arg| match arg.name {
176 hir::ParamName::Plain(Ident { name: kw::Underscore, span }) => Some(span),
177 _ => None,
178 }) {
179 sugg.push((span, (*type_name).to_string()));
182 } else if let Some(span) = generics.span_for_param_suggestion() {
183 sugg.push((span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(", {0}", type_name))
})format!(", {type_name}")));
185 } else {
186 sugg.push((generics.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", type_name))
})format!("<{type_name}>")));
187 }
188 }
189
190 let mut err =
191 bad_placeholder(cx, placeholder_types.into_iter().chain(additional_spans).collect(), kind);
192
193 if suggest {
195 let mut is_fn = false;
196 let mut is_const_or_static = false;
197
198 if let Some(hir_ty) = hir_ty
199 && let hir::TyKind::FnPtr(_) = hir_ty.kind
200 {
201 is_fn = true;
202
203 is_const_or_static = #[allow(non_exhaustive_omitted_patterns)] match cx.tcx().parent_hir_node(hir_ty.hir_id)
{
Node::Item(&hir::Item {
kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..), .. }) |
Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..),
.. }) |
Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), ..
}) => true,
_ => false,
}matches!(
205 cx.tcx().parent_hir_node(hir_ty.hir_id),
206 Node::Item(&hir::Item {
207 kind: hir::ItemKind::Const(..) | hir::ItemKind::Static(..),
208 ..
209 }) | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
210 | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
211 );
212 }
213
214 if !(is_fn && is_const_or_static) {
217 err.multipart_suggestion(
218 "use type parameters instead",
219 sugg,
220 Applicability::HasPlaceholders,
221 );
222 }
223 }
224
225 err
226}
227
228fn bad_placeholder<'cx, 'tcx>(
232 cx: &'cx dyn HirTyLowerer<'tcx>,
233 mut spans: Vec<Span>,
234 kind: &'static str,
235) -> Diag<'cx> {
236 let kind = if kind.ends_with('s') { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}es", kind))
})format!("{kind}es") } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}s", kind))
})format!("{kind}s") };
237
238 spans.sort();
239 cx.dcx().create_err(errors::PlaceholderNotAllowedItemSignatures { spans, kind })
240}
241
242impl<'tcx> ItemCtxt<'tcx> {
243 pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> {
244 ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) }
245 }
246
247 pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
248 self.lowerer().lower_ty(hir_ty)
249 }
250
251 pub(crate) fn hir_id(&self) -> hir::HirId {
252 self.tcx.local_def_id_to_hir_id(self.item_def_id)
253 }
254
255 pub(crate) fn node(&self) -> hir::Node<'tcx> {
256 self.tcx.hir_node(self.hir_id())
257 }
258
259 fn check_tainted_by_errors(&self) -> Result<(), ErrorGuaranteed> {
260 match self.tainted_by_errors.get() {
261 Some(err) => Err(err),
262 None => Ok(()),
263 }
264 }
265
266 fn report_placeholder_type_error(
267 &self,
268 placeholder_types: Vec<Span>,
269 infer_replacements: Vec<(Span, String)>,
270 ) -> ErrorGuaranteed {
271 let node = self.tcx.hir_node_by_def_id(self.item_def_id);
272 let generics = node.generics();
273 let kind_id = match node {
274 Node::GenericParam(_) | Node::WherePredicate(_) | Node::Field(_) => {
275 self.tcx.local_parent(self.item_def_id)
276 }
277 _ => self.item_def_id,
278 };
279 let kind = self.tcx.def_descr(kind_id.into());
280 let mut diag = placeholder_type_error_diag(
281 self,
282 generics,
283 placeholder_types,
284 infer_replacements.iter().map(|&(span, _)| span).collect(),
285 false,
286 None,
287 kind,
288 );
289 if !infer_replacements.is_empty() {
290 diag.multipart_suggestion(
291 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("try replacing `_` with the type{0} in the corresponding trait method signature",
if infer_replacements.len() == 1 { "" } else { "s" }))
})format!(
292 "try replacing `_` with the type{} in the corresponding trait method \
293 signature",
294 rustc_errors::pluralize!(infer_replacements.len()),
295 ),
296 infer_replacements,
297 Applicability::MachineApplicable,
298 );
299 }
300
301 diag.emit()
302 }
303}
304
305impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
306 fn tcx(&self) -> TyCtxt<'tcx> {
307 self.tcx
308 }
309
310 fn dcx(&self) -> DiagCtxtHandle<'_> {
311 self.tcx.dcx().taintable_handle(&self.tainted_by_errors)
312 }
313
314 fn item_def_id(&self) -> LocalDefId {
315 self.item_def_id
316 }
317
318 fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> {
319 if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason {
320 let guar = self
323 .dcx()
324 .struct_span_err(
325 span,
326 "cannot deduce the lifetime bound for this trait object type from context",
327 )
328 .with_code(E0228)
329 .with_span_suggestion_verbose(
330 sugg_sp,
331 "please supply an explicit bound",
332 " + /* 'a */",
333 Applicability::HasPlaceholders,
334 )
335 .emit();
336 ty::Region::new_error(self.tcx(), guar)
337 } else {
338 ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature")
340 }
341 }
342
343 fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> {
344 if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) {
345 self.report_placeholder_type_error(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[span]))vec![span], ::alloc::vec::Vec::new()vec![]);
346 }
347 Ty::new_error_with_message(self.tcx(), span, "bad placeholder type")
348 }
349
350 fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> {
351 self.report_placeholder_type_error(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[span]))vec![span], ::alloc::vec::Vec::new()vec![]);
352 ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant")
353 }
354
355 fn register_trait_ascription_bounds(
356 &self,
357 _: Vec<(ty::Clause<'tcx>, Span)>,
358 _: HirId,
359 span: Span,
360 ) {
361 self.dcx().span_delayed_bug(span, "trait ascription type not allowed here");
362 }
363
364 fn probe_ty_param_bounds(
365 &self,
366 span: Span,
367 def_id: LocalDefId,
368 assoc_ident: Ident,
369 ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
370 self.tcx.at(span).type_param_predicates((self.item_def_id, def_id, assoc_ident))
371 }
372
373 x;#[instrument(level = "debug", skip(self, _span), ret)]
374 fn select_inherent_assoc_candidates(
375 &self,
376 _span: Span,
377 self_ty: Ty<'tcx>,
378 candidates: Vec<InherentAssocCandidate>,
379 ) -> (Vec<InherentAssocCandidate>, Vec<FulfillmentError<'tcx>>) {
380 assert!(!self_ty.has_infer());
381
382 let self_ty = self.tcx.expand_free_alias_tys(self_ty);
387 debug!("select_inherent_assoc_candidates: self_ty={:?}", self_ty);
388
389 let candidates = candidates
390 .into_iter()
391 .filter(|&InherentAssocCandidate { impl_, .. }| {
392 let impl_ty = self.tcx().type_of(impl_).instantiate_identity().skip_norm_wip();
393
394 let impl_ty = self.tcx.expand_free_alias_tys(impl_ty);
396 debug!("select_inherent_assoc_candidates: impl_ty={:?}", impl_ty);
397
398 ty::DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify_with_depth(
415 self_ty,
416 impl_ty,
417 usize::MAX,
418 )
419 })
420 .collect();
421
422 (candidates, vec![])
423 }
424
425 fn lower_assoc_item_path(
426 &self,
427 span: Span,
428 item_def_id: DefId,
429 item_segment: &rustc_hir::PathSegment<'tcx>,
430 poly_trait_ref: ty::PolyTraitRef<'tcx>,
431 ) -> Result<(DefId, ty::GenericArgsRef<'tcx>), ErrorGuaranteed> {
432 if let Some(trait_ref) = poly_trait_ref.no_bound_vars() {
433 let item_args = self.lowerer().lower_generic_args_of_assoc_item(
434 span,
435 item_def_id,
436 item_segment,
437 trait_ref.args,
438 );
439 Ok((item_def_id, item_args))
440 } else {
441 let (mut mpart_sugg, mut inferred_sugg) = (None, None);
443 let mut bound = String::new();
444
445 match self.node() {
446 hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
447 let item = self
448 .tcx
449 .hir_expect_item(self.tcx.hir_get_parent_item(self.hir_id()).def_id);
450 match &item.kind {
451 hir::ItemKind::Enum(_, generics, _)
452 | hir::ItemKind::Struct(_, generics, _)
453 | hir::ItemKind::Union(_, generics, _) => {
454 let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics);
455 let (lt_sp, sugg) = match generics.params {
456 [] => (generics.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", lt_name))
})format!("<{lt_name}>")),
457 [bound, ..] => (bound.span.shrink_to_lo(), ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", lt_name))
})format!("{lt_name}, ")),
458 };
459 mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
460 fspan: lt_sp,
461 first: sugg,
462 sspan: span.with_hi(item_segment.ident.span.lo()),
463 second: ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
self.tcx.instantiate_bound_regions_uncached(poly_trait_ref,
|_|
{
ty::Region::new_early_param(self.tcx,
ty::EarlyParamRegion {
index: 0,
name: Symbol::intern(<_name),
})
})))
})format!(
464 "{}::",
465 self.tcx.instantiate_bound_regions_uncached(
467 poly_trait_ref,
468 |_| {
469 ty::Region::new_early_param(self.tcx, ty::EarlyParamRegion {
470 index: 0,
471 name: Symbol::intern(<_name),
472 })
473 }
474 ),
475 ),
476 });
477 }
478 _ => {}
479 }
480 }
481 hir::Node::Item(hir::Item {
482 kind:
483 hir::ItemKind::Struct(..) | hir::ItemKind::Enum(..) | hir::ItemKind::Union(..),
484 ..
485 }) => {}
486 hir::Node::Item(_)
487 | hir::Node::ForeignItem(_)
488 | hir::Node::TraitItem(_)
489 | hir::Node::ImplItem(_) => {
490 inferred_sugg = Some(span.with_hi(item_segment.ident.span.lo()));
491 bound = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::",
self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder()))
})format!(
492 "{}::",
493 self.tcx.anonymize_bound_vars(poly_trait_ref).skip_binder(),
495 );
496 }
497 _ => {}
498 }
499
500 Err(self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
501 span,
502 inferred_sugg,
503 bound,
504 mpart_sugg,
505 what: self.tcx.def_descr(item_def_id),
506 }))
507 }
508 }
509
510 fn probe_adt(&self, _span: Span, ty: Ty<'tcx>) -> Option<ty::AdtDef<'tcx>> {
511 ty.ty_adt_def()
513 }
514
515 fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) {
516 }
518
519 fn infcx(&self) -> Option<&InferCtxt<'tcx>> {
520 None
521 }
522
523 fn lower_fn_sig(
524 &self,
525 decl: &hir::FnDecl<'tcx>,
526 _generics: Option<&hir::Generics<'_>>,
527 hir_id: rustc_hir::HirId,
528 _hir_ty: Option<&hir::Ty<'_>>,
529 ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) {
530 let tcx = self.tcx();
531
532 let mut infer_replacements = ::alloc::vec::Vec::new()vec![];
533
534 let input_tys = decl
535 .inputs
536 .iter()
537 .enumerate()
538 .map(|(i, a)| {
539 if let hir::TyKind::Infer(()) = a.kind
540 && let Some(suggested_ty) =
541 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i))
542 {
543 infer_replacements.push((a.span, suggested_ty.to_string()));
544 return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string());
545 }
546
547 self.lowerer().lower_ty(a)
548 })
549 .collect();
550
551 let output_ty = match decl.output {
552 hir::FnRetTy::Return(output) => {
553 if let hir::TyKind::Infer(()) = output.kind
554 && let Some(suggested_ty) =
555 self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None)
556 {
557 infer_replacements.push((output.span, suggested_ty.to_string()));
558 Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string())
559 } else {
560 self.lower_ty(output)
561 }
562 }
563 hir::FnRetTy::DefaultReturn(..) => tcx.types.unit,
564 };
565
566 if !infer_replacements.is_empty() {
567 self.report_placeholder_type_error(::alloc::vec::Vec::new()vec![], infer_replacements);
568 }
569 (input_tys, output_ty)
570 }
571
572 fn dyn_compatibility_violations(&self, trait_def_id: DefId) -> Vec<DynCompatibilityViolation> {
573 hir_ty_lowering_dyn_compatibility_violations(self.tcx, trait_def_id)
574 }
575}
576
577fn get_new_lifetime_name<'tcx>(
579 tcx: TyCtxt<'tcx>,
580 poly_trait_ref: ty::PolyTraitRef<'tcx>,
581 generics: &hir::Generics<'tcx>,
582) -> String {
583 let existing_lifetimes = tcx
584 .collect_referenced_late_bound_regions(poly_trait_ref)
585 .into_iter()
586 .filter_map(|lt| lt.get_name(tcx).map(|name| name.as_str().to_string()))
587 .chain(generics.params.iter().filter_map(|param| {
588 if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind {
589 Some(param.name.ident().as_str().to_string())
590 } else {
591 None
592 }
593 }))
594 .collect::<FxHashSet<String>>();
595
596 let a_to_z_repeat_n = |n| {
597 (b'a'..=b'z').map(move |c| {
598 let mut s = '\''.to_string();
599 s.extend(std::iter::repeat_n(char::from(c), n));
600 s
601 })
602 };
603
604 (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
606}
607
608pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
609 tcx.ensure_ok().generics_of(def_id);
610 tcx.ensure_ok().type_of(def_id);
611 tcx.ensure_ok().predicates_of(def_id);
612}
613
614pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: LocalDefId) {
615 struct ReprCIssue {
616 msg: &'static str,
617 }
618
619 impl<'a> Diagnostic<'a, ()> for ReprCIssue {
620 fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
621 let Self { msg } = self;
622 Diag::new(dcx, level, msg)
623 .with_note("`repr(C)` enums with big discriminants are non-portable, and their size in Rust might not match their size in C")
624 .with_help("use `repr($int_ty)` instead to explicitly set the size of this enum")
625 }
626 }
627
628 let def = tcx.adt_def(def_id);
629 let repr_type = def.repr().discr_type();
630 let initial = repr_type.initial_discriminant(tcx);
631 let mut prev_discr = None::<Discr<'_>>;
632 if !(tcx.sess.target.c_int_width < 128) {
::core::panicking::panic("assertion failed: tcx.sess.target.c_int_width < 128")
};assert!(tcx.sess.target.c_int_width < 128);
634 let mut min_discr = i128::MAX;
635 let mut max_discr = i128::MIN;
636
637 for variant in def.variants() {
639 let wrapped_discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx));
640 let cur_discr = if let ty::VariantDiscr::Explicit(const_def_id) = variant.discr {
641 def.eval_explicit_discr(tcx, const_def_id).ok()
642 } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {
643 Some(discr)
644 } else {
645 let span = tcx.def_span(variant.def_id);
646 tcx.dcx().emit_err(errors::EnumDiscriminantOverflowed {
647 span,
648 discr: prev_discr.unwrap().to_string(),
649 item_name: tcx.item_ident(variant.def_id),
650 wrapped_discr: wrapped_discr.to_string(),
651 });
652 None
653 }
654 .unwrap_or(wrapped_discr);
655
656 if def.repr().c() {
657 let c_int = Size::from_bits(tcx.sess.target.c_int_width);
658 let c_uint_max = i128::try_from(c_int.unsigned_int_max()).unwrap();
659 let discr_size = cur_discr.ty.int_size_and_signed(tcx).0;
661 let discr_val = discr_size.sign_extend(cur_discr.val);
662 min_discr = min_discr.min(discr_val);
663 max_discr = max_discr.max(discr_val);
664
665 if !(min_discr >= c_int.signed_int_min() && max_discr <= c_int.signed_int_max())
667 && !(min_discr >= 0 && max_discr <= c_uint_max)
668 {
669 let span = tcx.def_span(variant.def_id);
670 let msg = if discr_val < c_int.signed_int_min() || discr_val > c_uint_max {
671 "`repr(C)` enum discriminant does not fit into C `int` nor into C `unsigned int`"
672 } else if discr_val < 0 {
673 "`repr(C)` enum discriminant does not fit into C `unsigned int`, and a previous discriminant does not fit into C `int`"
674 } else {
675 "`repr(C)` enum discriminant does not fit into C `int`, and a previous discriminant does not fit into C `unsigned int`"
676 };
677 tcx.emit_node_span_lint(
678 rustc_session::lint::builtin::REPR_C_ENUMS_LARGER_THAN_INT,
679 tcx.local_def_id_to_hir_id(def_id),
680 span,
681 ReprCIssue { msg },
682 );
683 }
684 }
685
686 prev_discr = Some(cur_discr);
687
688 for f in &variant.fields {
689 tcx.ensure_ok().generics_of(f.did);
690 tcx.ensure_ok().type_of(f.did);
691 tcx.ensure_ok().predicates_of(f.did);
692 }
693
694 if let Some(ctor_def_id) = variant.ctor_def_id() {
696 lower_variant_ctor(tcx, ctor_def_id.expect_local());
697 }
698 }
699}
700
701#[derive(#[automatically_derived]
impl ::core::clone::Clone for NestedSpan {
#[inline]
fn clone(&self) -> NestedSpan {
let _: ::core::clone::AssertParamIsClone<Span>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for NestedSpan { }Copy)]
702struct NestedSpan {
703 span: Span,
704 nested_field_span: Span,
705}
706
707impl NestedSpan {
708 fn to_field_already_declared_nested_help(&self) -> errors::FieldAlreadyDeclaredNestedHelp {
709 errors::FieldAlreadyDeclaredNestedHelp { span: self.span }
710 }
711}
712
713#[derive(#[automatically_derived]
impl ::core::clone::Clone for FieldDeclSpan {
#[inline]
fn clone(&self) -> FieldDeclSpan {
let _: ::core::clone::AssertParamIsClone<Span>;
let _: ::core::clone::AssertParamIsClone<NestedSpan>;
*self
}
}Clone, #[automatically_derived]
impl ::core::marker::Copy for FieldDeclSpan { }Copy)]
714enum FieldDeclSpan {
715 NotNested(Span),
716 Nested(NestedSpan),
717}
718
719impl From<Span> for FieldDeclSpan {
720 fn from(span: Span) -> Self {
721 Self::NotNested(span)
722 }
723}
724
725impl From<NestedSpan> for FieldDeclSpan {
726 fn from(span: NestedSpan) -> Self {
727 Self::Nested(span)
728 }
729}
730
731struct FieldUniquenessCheckContext<'tcx> {
732 tcx: TyCtxt<'tcx>,
733 seen_fields: FxIndexMap<Ident, FieldDeclSpan>,
734}
735
736impl<'tcx> FieldUniquenessCheckContext<'tcx> {
737 fn new(tcx: TyCtxt<'tcx>) -> Self {
738 Self { tcx, seen_fields: FxIndexMap::default() }
739 }
740
741 fn check_field_decl(&mut self, field_name: Ident, field_decl: FieldDeclSpan) {
743 use FieldDeclSpan::*;
744 let field_name = field_name.normalize_to_macros_2_0();
745 match (field_decl, self.seen_fields.get(&field_name).copied()) {
746 (NotNested(span), Some(NotNested(prev_span))) => {
747 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::NotNested {
748 field_name,
749 span,
750 prev_span,
751 });
752 }
753 (NotNested(span), Some(Nested(prev))) => {
754 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::PreviousNested {
755 field_name,
756 span,
757 prev_span: prev.span,
758 prev_nested_field_span: prev.nested_field_span,
759 prev_help: prev.to_field_already_declared_nested_help(),
760 });
761 }
762 (
763 Nested(current @ NestedSpan { span, nested_field_span, .. }),
764 Some(NotNested(prev_span)),
765 ) => {
766 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::CurrentNested {
767 field_name,
768 span,
769 nested_field_span,
770 help: current.to_field_already_declared_nested_help(),
771 prev_span,
772 });
773 }
774 (Nested(current @ NestedSpan { span, nested_field_span }), Some(Nested(prev))) => {
775 self.tcx.dcx().emit_err(errors::FieldAlreadyDeclared::BothNested {
776 field_name,
777 span,
778 nested_field_span,
779 help: current.to_field_already_declared_nested_help(),
780 prev_span: prev.span,
781 prev_nested_field_span: prev.nested_field_span,
782 prev_help: prev.to_field_already_declared_nested_help(),
783 });
784 }
785 (field_decl, None) => {
786 self.seen_fields.insert(field_name, field_decl);
787 }
788 }
789 }
790}
791
792fn lower_variant<'tcx>(
793 tcx: TyCtxt<'tcx>,
794 variant_did: Option<LocalDefId>,
795 ident: Ident,
796 discr: ty::VariantDiscr,
797 def: &hir::VariantData<'tcx>,
798 adt_kind: ty::AdtKind,
799 parent_did: LocalDefId,
800) -> ty::VariantDef {
801 let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext::new(tcx);
802 let fields = def
803 .fields()
804 .iter()
805 .inspect(|field| {
806 field_uniqueness_check_ctx.check_field_decl(field.ident, field.span.into());
807 })
808 .map(|f| ty::FieldDef {
809 did: f.def_id.to_def_id(),
810 name: f.ident.name,
811 vis: tcx.visibility(f.def_id),
812 safety: f.safety,
813 value: f.default.map(|v| v.def_id.to_def_id()),
814 })
815 .collect();
816 let recovered = match def {
817 hir::VariantData::Struct { recovered: Recovered::Yes(guar), .. } => Some(*guar),
818 _ => None,
819 };
820 ty::VariantDef::new(
821 ident.name,
822 variant_did.map(LocalDefId::to_def_id),
823 def.ctor().map(|(kind, _, def_id)| (kind, def_id.to_def_id())),
824 discr,
825 fields,
826 parent_did.to_def_id(),
827 recovered,
828 adt_kind == AdtKind::Struct && {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(parent_did, &tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NonExhaustive(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, parent_did, NonExhaustive(..))
829 || variant_did
830 .is_some_and(|variant_did| {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(variant_did, &tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NonExhaustive(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, variant_did, NonExhaustive(..))),
831 )
832}
833
834fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
835 use rustc_hir::*;
836
837 let Node::Item(item) = tcx.hir_node_by_def_id(def_id) else {
838 ::rustc_middle::util::bug::bug_fmt(format_args!("expected ADT to be an item"));bug!("expected ADT to be an item");
839 };
840
841 let repr = tcx.repr_options_of_def(def_id);
842 let (kind, variants) = match &item.kind {
843 ItemKind::Enum(_, _, def) => {
844 let mut distance_from_explicit = 0;
845 let variants = def
846 .variants
847 .iter()
848 .map(|v| {
849 let discr = if let Some(e) = &v.disr_expr {
850 distance_from_explicit = 0;
851 ty::VariantDiscr::Explicit(e.def_id.to_def_id())
852 } else {
853 ty::VariantDiscr::Relative(distance_from_explicit)
854 };
855 distance_from_explicit += 1;
856
857 lower_variant(
858 tcx,
859 Some(v.def_id),
860 v.ident,
861 discr,
862 &v.data,
863 AdtKind::Enum,
864 def_id,
865 )
866 })
867 .collect();
868
869 (AdtKind::Enum, variants)
870 }
871 ItemKind::Struct(ident, _, def) | ItemKind::Union(ident, _, def) => {
872 let adt_kind = match item.kind {
873 ItemKind::Struct(..) => AdtKind::Struct,
874 _ => AdtKind::Union,
875 };
876 let variants = std::iter::once(lower_variant(
877 tcx,
878 None,
879 *ident,
880 ty::VariantDiscr::Relative(0),
881 def,
882 adt_kind,
883 def_id,
884 ))
885 .collect();
886
887 (adt_kind, variants)
888 }
889 _ => ::rustc_middle::util::bug::bug_fmt(format_args!("{0:?} is not an ADT",
item.owner_id.def_id))bug!("{:?} is not an ADT", item.owner_id.def_id),
890 };
891 tcx.mk_adt_def(def_id.to_def_id(), kind, variants, repr)
892}
893
894fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
895 let item = tcx.hir_expect_item(def_id);
896
897 let (constness, is_alias, is_auto, safety, impl_restriction) = match item.kind {
898 hir::ItemKind::Trait(constness, is_auto, safety, impl_restriction, ..) => (
899 constness,
900 false,
901 is_auto == hir::IsAuto::Yes,
902 safety,
903 if let hir::RestrictionKind::Restricted(path) = impl_restriction.kind {
904 ty::trait_def::ImplRestrictionKind::Restricted(path.res, impl_restriction.span)
905 } else {
906 ty::trait_def::ImplRestrictionKind::Unrestricted
907 },
908 ),
909 hir::ItemKind::TraitAlias(constness, ..) => (
910 constness,
911 true,
912 false,
913 hir::Safety::Safe,
914 ty::trait_def::ImplRestrictionKind::Unrestricted,
915 ),
916 _ => ::rustc_middle::util::bug::span_bug_fmt(item.span,
format_args!("trait_def_of_item invoked on non-trait"))span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
917 };
918
919 #[allow(deprecated)]
921 let attrs = tcx.get_all_attrs(def_id);
922
923 let paren_sugar = {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcParenSugar(_)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcParenSugar(_));
924 if paren_sugar && !tcx.features().unboxed_closures() {
925 tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
926 }
927
928 let is_marker = !is_alias && {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(Marker(_)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, Marker(_));
930
931 let rustc_coinductive = {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcCoinductive(_)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcCoinductive(_));
932 let is_fundamental = {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(Fundamental) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, Fundamental);
933
934 let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = {
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcSkipDuringMethodDispatch {
array, boxed_slice, span: _ }) => {
break 'done Some([*array, *boxed_slice]);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}find_attr!(
935 attrs,
936 RustcSkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
937 )
938 .unwrap_or([false; 2]);
939
940 let specialization_kind = if {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcUnsafeSpecializationMarker(_))
=> {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcUnsafeSpecializationMarker(_)) {
941 ty::trait_def::TraitSpecializationKind::Marker
942 } else if {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcSpecializationTrait(_)) =>
{
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcSpecializationTrait(_)) {
943 ty::trait_def::TraitSpecializationKind::AlwaysApplicable
944 } else {
945 ty::trait_def::TraitSpecializationKind::None
946 };
947
948 let must_implement_one_of = {
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcMustImplementOneOf {
fn_names, .. }) => {
break 'done
Some(fn_names.iter().cloned().collect::<Box<[_]>>());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}find_attr!(
949 attrs,
950 RustcMustImplementOneOf { fn_names, .. } =>
951 fn_names
952 .iter()
953 .cloned()
954 .collect::<Box<[_]>>()
955 );
956
957 let deny_explicit_impl = {
{
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDenyExplicitImpl(_)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(attrs, RustcDenyExplicitImpl(_));
958 let force_dyn_incompatible = {
'done:
{
for i in attrs {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDynIncompatibleTrait(span))
=> {
break 'done Some(*span);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}find_attr!(attrs, RustcDynIncompatibleTrait(span) => *span);
959
960 ty::TraitDef {
961 def_id: def_id.to_def_id(),
962 safety,
963 constness,
964 impl_restriction,
965 paren_sugar,
966 has_auto_impl: is_auto,
967 is_marker,
968 is_coinductive: rustc_coinductive || is_auto,
969 is_fundamental,
970 skip_array_during_method_dispatch,
971 skip_boxed_slice_during_method_dispatch,
972 specialization_kind,
973 must_implement_one_of,
974 force_dyn_incompatible,
975 deny_explicit_impl,
976 }
977}
978
979x;#[instrument(level = "debug", skip(tcx), ret)]
980fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFnSig<'_>> {
981 use rustc_hir::Node::*;
982 use rustc_hir::*;
983
984 let hir_id = tcx.local_def_id_to_hir_id(def_id);
985
986 let icx = ItemCtxt::new(tcx, def_id);
987
988 let output = match tcx.hir_node(hir_id) {
989 TraitItem(hir::TraitItem {
990 kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)),
991 generics,
992 ..
993 })
994 | Item(hir::Item { kind: ItemKind::Fn { sig, generics, .. }, .. }) => {
995 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
996 }
997
998 ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), generics, .. }) => {
999 if let Item(hir::Item { kind: ItemKind::Impl(i), .. }) = tcx.parent_hir_node(hir_id)
1001 && i.of_trait.is_some()
1002 {
1003 icx.lowerer().lower_fn_ty(
1004 hir_id,
1005 sig.header.safety(),
1006 sig.header.abi,
1007 sig.decl,
1008 Some(generics),
1009 None,
1010 )
1011 } else {
1012 lower_fn_sig_recovering_infer_ret_ty(&icx, sig, generics, def_id)
1013 }
1014 }
1015
1016 TraitItem(hir::TraitItem {
1017 kind: TraitItemKind::Fn(FnSig { header, decl, span: _ }, _),
1018 generics,
1019 ..
1020 }) => icx.lowerer().lower_fn_ty(
1021 hir_id,
1022 header.safety(),
1023 header.abi,
1024 decl,
1025 Some(generics),
1026 None,
1027 ),
1028
1029 ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(sig, _, _), .. }) => {
1030 let abi = tcx.hir_get_foreign_abi(hir_id);
1031 compute_sig_of_foreign_fn_decl(tcx, def_id, sig.decl, abi, sig.header.safety())
1032 }
1033
1034 Ctor(data) => {
1035 assert_matches!(data.ctor(), Some(_));
1036 let adt_def_id = tcx.hir_get_parent_item(hir_id).def_id.to_def_id();
1037 let ty = tcx.type_of(adt_def_id).instantiate_identity().skip_norm_wip();
1038 let inputs = data
1039 .fields()
1040 .iter()
1041 .map(|f| tcx.type_of(f.def_id).instantiate_identity().skip_norm_wip());
1042 let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1044 (Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1045 _ => hir::Safety::Unsafe,
1046 };
1047 ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(inputs, ty, safety))
1048 }
1049
1050 Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {
1051 bug!("to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",);
1062 }
1063
1064 x => {
1065 bug!("unexpected sort of node in fn_sig(): {:?}", x);
1066 }
1067 };
1068 ty::EarlyBinder::bind(output)
1069}
1070
1071fn lower_fn_sig_recovering_infer_ret_ty<'tcx>(
1072 icx: &ItemCtxt<'tcx>,
1073 sig: &'tcx hir::FnSig<'tcx>,
1074 generics: &'tcx hir::Generics<'tcx>,
1075 def_id: LocalDefId,
1076) -> ty::PolyFnSig<'tcx> {
1077 if let Some(infer_ret_ty) = sig.decl.output.is_suggestable_infer_ty() {
1078 return recover_infer_ret_ty(icx, infer_ret_ty, generics, def_id);
1079 }
1080
1081 icx.lowerer().lower_fn_ty(
1082 icx.tcx().local_def_id_to_hir_id(def_id),
1083 sig.header.safety(),
1084 sig.header.abi,
1085 sig.decl,
1086 Some(generics),
1087 None,
1088 )
1089}
1090
1091fn late_param_regions_to_bound<'tcx, T>(
1093 tcx: TyCtxt<'tcx>,
1094 scope: DefId,
1095 bound_vars: &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
1096 value: T,
1097) -> ty::Binder<'tcx, T>
1098where
1099 T: ty::TypeFoldable<TyCtxt<'tcx>>,
1100{
1101 let value = fold_regions(tcx, value, |r, debruijn| match r.kind() {
1102 ty::ReLateParam(lp) => {
1103 match (&lp.scope, &scope) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(lp.scope, scope);
1105
1106 let br = match lp.kind {
1107 kind @ (ty::LateParamRegionKind::Anon(idx)
1109 | ty::LateParamRegionKind::NamedAnon(idx, _)) => {
1110 let idx = idx as usize;
1111 let var = ty::BoundVar::from_usize(idx);
1112
1113 let Some(ty::BoundVariableKind::Region(kind)) = bound_vars.get(idx).copied()
1114 else {
1115 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected late-bound region {0:?} for bound vars {1:?}",
kind, bound_vars));bug!("unexpected late-bound region {kind:?} for bound vars {bound_vars:?}");
1116 };
1117
1118 ty::BoundRegion { var, kind }
1119 }
1120
1121 ty::LateParamRegionKind::Named(def_id) => bound_vars
1123 .iter()
1124 .enumerate()
1125 .find_map(|(idx, bv)| match bv {
1126 ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::Named(did))
1127 if did == def_id =>
1128 {
1129 Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1130 }
1131 _ => None,
1132 })
1133 .unwrap(),
1134
1135 ty::LateParamRegionKind::ClosureEnv => bound_vars
1136 .iter()
1137 .enumerate()
1138 .find_map(|(idx, bv)| match bv {
1139 ty::BoundVariableKind::Region(kind @ ty::BoundRegionKind::ClosureEnv) => {
1140 Some(ty::BoundRegion { var: ty::BoundVar::from_usize(idx), kind })
1141 }
1142 _ => None,
1143 })
1144 .unwrap(),
1145 };
1146
1147 ty::Region::new_bound(tcx, debruijn, br)
1148 }
1149 _ => r,
1150 });
1151
1152 ty::Binder::bind_with_vars(value, bound_vars)
1153}
1154
1155fn recover_infer_ret_ty<'tcx>(
1156 icx: &ItemCtxt<'tcx>,
1157 infer_ret_ty: &'tcx hir::Ty<'tcx>,
1158 generics: &'tcx hir::Generics<'tcx>,
1159 def_id: LocalDefId,
1160) -> ty::PolyFnSig<'tcx> {
1161 let tcx = icx.tcx;
1162 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1163
1164 let fn_sig = tcx.typeck(def_id).liberated_fn_sigs()[hir_id];
1165
1166 let has_region_params = generics.params.iter().any(|param| match param.kind {
1171 GenericParamKind::Lifetime { .. } => true,
1172 _ => false,
1173 });
1174 let fn_sig = fold_regions(tcx, fn_sig, |r, _| match r.kind() {
1175 ty::ReErased => {
1176 if has_region_params {
1177 ty::Region::new_error_with_message(
1178 tcx,
1179 DUMMY_SP,
1180 "erased region is not allowed here in return type",
1181 )
1182 } else {
1183 tcx.lifetimes.re_static
1184 }
1185 }
1186 _ => r,
1187 });
1188
1189 let mut visitor = HirPlaceholderCollector::default();
1190 visitor.visit_ty_unambig(infer_ret_ty);
1191
1192 let mut diag = bad_placeholder(icx.lowerer(), visitor.spans, "return type");
1193 let ret_ty = fn_sig.output();
1194
1195 let mut recovered_ret_ty = None;
1199 if let Some(suggestable_ret_ty) = ret_ty.make_suggestable(tcx, false, None) {
1200 diag.span_suggestion_verbose(
1201 infer_ret_ty.span,
1202 "replace with the correct return type",
1203 suggestable_ret_ty,
1204 Applicability::MachineApplicable,
1205 );
1206 recovered_ret_ty = Some(suggestable_ret_ty);
1207 } else if let Some(sugg) = suggest_impl_trait(
1208 &tcx.infer_ctxt().build(TypingMode::non_body_analysis()),
1209 tcx.param_env(def_id),
1210 ret_ty,
1211 ) {
1212 diag.span_suggestion_verbose(
1213 infer_ret_ty.span,
1214 "replace with an appropriate return type",
1215 sugg,
1216 Applicability::MachineApplicable,
1217 );
1218 } else if ret_ty.is_closure() {
1219 diag.help("consider using an `Fn`, `FnMut`, or `FnOnce` trait bound");
1220 }
1221
1222 if ret_ty.is_closure() {
1224 diag.note(
1225 "for more information on `Fn` traits and closure types, see \
1226 https://doc.rust-lang.org/book/ch13-01-closures.html",
1227 );
1228 }
1229 let guar = diag.emit();
1230
1231 let bound_vars = tcx.late_bound_vars(hir_id);
1235 let scope = def_id.to_def_id();
1236
1237 let fn_sig = tcx.mk_fn_sig(
1238 fn_sig.inputs().iter().copied(),
1239 recovered_ret_ty.unwrap_or_else(|| Ty::new_error(tcx, guar)),
1240 fn_sig.fn_sig_kind,
1241 );
1242
1243 late_param_regions_to_bound(tcx, scope, bound_vars, fn_sig)
1244}
1245
1246pub fn suggest_impl_trait<'tcx>(
1247 infcx: &InferCtxt<'tcx>,
1248 param_env: ty::ParamEnv<'tcx>,
1249 ret_ty: Ty<'tcx>,
1250) -> Option<String> {
1251 let format_as_assoc: fn(_, _, _, _, _) -> _ =
1252 |tcx: TyCtxt<'tcx>,
1253 _: ty::GenericArgsRef<'tcx>,
1254 trait_def_id: DefId,
1255 assoc_item_def_id: DefId,
1256 item_ty: Ty<'tcx>| {
1257 let trait_name = tcx.item_name(trait_def_id);
1258 let assoc_name = tcx.item_name(assoc_item_def_id);
1259 Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl {0}<{1} = {2}>", trait_name,
assoc_name, item_ty))
})format!("impl {trait_name}<{assoc_name} = {item_ty}>"))
1260 };
1261 let format_as_parenthesized: fn(_, _, _, _, _) -> _ =
1262 |tcx: TyCtxt<'tcx>,
1263 args: ty::GenericArgsRef<'tcx>,
1264 trait_def_id: DefId,
1265 _: DefId,
1266 item_ty: Ty<'tcx>| {
1267 let trait_name = tcx.item_name(trait_def_id);
1268 let args_tuple = args.type_at(1);
1269 let ty::Tuple(types) = *args_tuple.kind() else {
1270 return None;
1271 };
1272 let types = types.make_suggestable(tcx, false, None)?;
1273 let maybe_ret =
1274 if item_ty.is_unit() { String::new() } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}", item_ty))
})format!(" -> {item_ty}") };
1275 Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("impl {1}({0}){2}",
types.iter().map(|ty|
ty.to_string()).collect::<Vec<_>>().join(", "), trait_name,
maybe_ret))
})format!(
1276 "impl {trait_name}({}){maybe_ret}",
1277 types.iter().map(|ty| ty.to_string()).collect::<Vec<_>>().join(", ")
1278 ))
1279 };
1280
1281 for (trait_def_id, assoc_item_def_id, formatter) in [
1282 (
1283 infcx.tcx.get_diagnostic_item(sym::Iterator),
1284 infcx.tcx.get_diagnostic_item(sym::IteratorItem),
1285 format_as_assoc,
1286 ),
1287 (
1288 infcx.tcx.lang_items().future_trait(),
1289 infcx.tcx.lang_items().future_output(),
1290 format_as_assoc,
1291 ),
1292 (
1293 infcx.tcx.lang_items().async_fn_trait(),
1294 infcx.tcx.lang_items().async_fn_once_output(),
1295 format_as_parenthesized,
1296 ),
1297 (
1298 infcx.tcx.lang_items().async_fn_mut_trait(),
1299 infcx.tcx.lang_items().async_fn_once_output(),
1300 format_as_parenthesized,
1301 ),
1302 (
1303 infcx.tcx.lang_items().async_fn_once_trait(),
1304 infcx.tcx.lang_items().async_fn_once_output(),
1305 format_as_parenthesized,
1306 ),
1307 (
1308 infcx.tcx.lang_items().fn_trait(),
1309 infcx.tcx.lang_items().fn_once_output(),
1310 format_as_parenthesized,
1311 ),
1312 (
1313 infcx.tcx.lang_items().fn_mut_trait(),
1314 infcx.tcx.lang_items().fn_once_output(),
1315 format_as_parenthesized,
1316 ),
1317 (
1318 infcx.tcx.lang_items().fn_once_trait(),
1319 infcx.tcx.lang_items().fn_once_output(),
1320 format_as_parenthesized,
1321 ),
1322 ] {
1323 let Some(trait_def_id) = trait_def_id else {
1324 continue;
1325 };
1326 let Some(assoc_item_def_id) = assoc_item_def_id else {
1327 continue;
1328 };
1329 if infcx.tcx.def_kind(assoc_item_def_id) != DefKind::AssocTy {
1330 continue;
1331 }
1332 let sugg = infcx.probe(|_| {
1333 let args = ty::GenericArgs::for_item(infcx.tcx, trait_def_id, |param, _| {
1334 if param.index == 0 { ret_ty.into() } else { infcx.var_for_def(DUMMY_SP, param) }
1335 });
1336 if !infcx
1337 .type_implements_trait(trait_def_id, args, param_env)
1338 .must_apply_modulo_regions()
1339 {
1340 return None;
1341 }
1342 let ocx = ObligationCtxt::new(&infcx);
1343 let item_ty = ocx.normalize(
1344 &ObligationCause::dummy(),
1345 param_env,
1346 Unnormalized::new(Ty::new_projection_from_args(infcx.tcx, assoc_item_def_id, args)),
1347 );
1348 if ocx.try_evaluate_obligations().is_empty()
1350 && let item_ty = infcx.resolve_vars_if_possible(item_ty)
1351 && let Some(item_ty) = item_ty.make_suggestable(infcx.tcx, false, None)
1352 && let Some(sugg) = formatter(
1353 infcx.tcx,
1354 infcx.resolve_vars_if_possible(args),
1355 trait_def_id,
1356 assoc_item_def_id,
1357 item_ty,
1358 )
1359 {
1360 return Some(sugg);
1361 }
1362
1363 None
1364 });
1365
1366 if sugg.is_some() {
1367 return sugg;
1368 }
1369 }
1370 None
1371}
1372
1373fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader<'_> {
1374 let icx = ItemCtxt::new(tcx, def_id);
1375 let item = tcx.hir_expect_item(def_id);
1376 let impl_ = item.expect_impl();
1377 let of_trait = impl_
1378 .of_trait
1379 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("expected impl trait, found inherent impl on {0:?}",
def_id));
}panic!("expected impl trait, found inherent impl on {def_id:?}"));
1380 let selfty = tcx.type_of(def_id).instantiate_identity().skip_norm_wip();
1381 let is_rustc_reservation = {
{
'done:
{
for i in ::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcReservationImpl(..)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, def_id, RustcReservationImpl(..));
1382
1383 check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref);
1384
1385 let trait_ref = icx.lowerer().lower_impl_trait_ref(&of_trait.trait_ref, selfty);
1386
1387 ty::ImplTraitHeader {
1388 trait_ref: ty::EarlyBinder::bind(trait_ref),
1389 safety: of_trait.safety,
1390 polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation),
1391 constness: impl_.constness,
1392 }
1393}
1394
1395fn check_impl_constness(
1396 tcx: TyCtxt<'_>,
1397 constness: hir::Constness,
1398 hir_trait_ref: &hir::TraitRef<'_>,
1399) {
1400 if let hir::Constness::NotConst = constness {
1401 return;
1402 }
1403
1404 let Some(trait_def_id) = hir_trait_ref.trait_def_id() else { return };
1405 if tcx.is_const_trait(trait_def_id) {
1406 return;
1407 }
1408
1409 let trait_name = tcx.item_name(trait_def_id).to_string();
1410 let (suggestion, suggestion_pre) = match (trait_def_id.as_local(), tcx.sess.is_nightly_build())
1411 {
1412 (Some(trait_def_id), true) => {
1413 let span = tcx.hir_expect_item(trait_def_id).vis_span;
1414 let span = tcx.sess.source_map().span_extend_while_whitespace(span);
1415
1416 (
1417 Some(span.shrink_to_hi()),
1418 if tcx.features().const_trait_impl() {
1419 ""
1420 } else {
1421 "enable `#![feature(const_trait_impl)]` in your crate and "
1422 },
1423 )
1424 }
1425 (None, _) | (_, false) => (None, ""),
1426 };
1427 tcx.dcx().emit_err(errors::ConstImplForNonConstTrait {
1428 trait_ref_span: hir_trait_ref.path.span,
1429 trait_name,
1430 suggestion,
1431 suggestion_pre,
1432 marking: (),
1433 adding: (),
1434 });
1435}
1436
1437fn polarity_of_impl(
1438 tcx: TyCtxt<'_>,
1439 of_trait: &hir::TraitImplHeader<'_>,
1440 is_rustc_reservation: bool,
1441) -> ty::ImplPolarity {
1442 match of_trait.polarity {
1443 hir::ImplPolarity::Negative(span) => {
1444 if is_rustc_reservation {
1445 let span = span.to(of_trait.trait_ref.path.span);
1446 tcx.dcx().span_err(span, "reservation impls can't be negative");
1447 }
1448 ty::ImplPolarity::Negative
1449 }
1450 hir::ImplPolarity::Positive => {
1451 if is_rustc_reservation {
1452 ty::ImplPolarity::Reservation
1453 } else {
1454 ty::ImplPolarity::Positive
1455 }
1456 }
1457 }
1458}
1459
1460fn early_bound_lifetimes_from_generics<'a, 'tcx>(
1466 tcx: TyCtxt<'tcx>,
1467 generics: &'a hir::Generics<'a>,
1468) -> impl Iterator<Item = &'a hir::GenericParam<'a>> {
1469 generics.params.iter().filter(move |param| match param.kind {
1470 GenericParamKind::Lifetime { .. } => !tcx.is_late_bound(param.hir_id),
1471 _ => false,
1472 })
1473}
1474
1475fn compute_sig_of_foreign_fn_decl<'tcx>(
1476 tcx: TyCtxt<'tcx>,
1477 def_id: LocalDefId,
1478 decl: &'tcx hir::FnDecl<'tcx>,
1479 abi: ExternAbi,
1480 safety: hir::Safety,
1481) -> ty::PolyFnSig<'tcx> {
1482 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1483 let fty =
1484 ItemCtxt::new(tcx, def_id).lowerer().lower_fn_ty(hir_id, safety, abi, decl, None, None);
1485
1486 if !tcx.features().simd_ffi() {
1489 let check = |hir_ty: &hir::Ty<'_>, ty: Ty<'_>| {
1490 if ty.is_simd() {
1491 let snip = tcx
1492 .sess
1493 .source_map()
1494 .span_to_snippet(hir_ty.span)
1495 .map_or_else(|_| String::new(), |s| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", s))
})format!(" `{s}`"));
1496 tcx.dcx().emit_err(errors::SIMDFFIHighlyExperimental { span: hir_ty.span, snip });
1497 }
1498 };
1499 for (input, ty) in iter::zip(decl.inputs, fty.inputs().skip_binder()) {
1500 check(input, *ty)
1501 }
1502 if let hir::FnRetTy::Return(ty) = decl.output {
1503 check(ty, fty.output().skip_binder())
1504 }
1505 }
1506
1507 fty
1508}
1509
1510fn coroutine_kind(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<hir::CoroutineKind> {
1511 match tcx.hir_node_by_def_id(def_id) {
1512 Node::Expr(&hir::Expr {
1513 kind:
1514 hir::ExprKind::Closure(&rustc_hir::Closure {
1515 kind: hir::ClosureKind::Coroutine(kind),
1516 ..
1517 }),
1518 ..
1519 }) => Some(kind),
1520 _ => None,
1521 }
1522}
1523
1524fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
1525 let &rustc_hir::Closure { kind: hir::ClosureKind::CoroutineClosure(_), body, .. } =
1526 tcx.hir_node_by_def_id(def_id).expect_closure()
1527 else {
1528 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1529 };
1530
1531 let &hir::Expr {
1532 kind:
1533 hir::ExprKind::Closure(&rustc_hir::Closure {
1534 def_id,
1535 kind: hir::ClosureKind::Coroutine(_),
1536 ..
1537 }),
1538 ..
1539 } = tcx.hir_body(body).value
1540 else {
1541 ::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))bug!()
1542 };
1543
1544 def_id.to_def_id()
1545}
1546
1547fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1548 match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1549 hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1550 hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1551 }
1552 hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1553 hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1554 }
1555 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1556 hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1557 }
1558 }
1559}
1560
1561fn rendered_precise_capturing_args<'tcx>(
1562 tcx: TyCtxt<'tcx>,
1563 def_id: LocalDefId,
1564) -> Option<&'tcx [PreciseCapturingArgKind<Symbol, Symbol>]> {
1565 if let Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
1566 tcx.opt_rpitit_info(def_id.to_def_id())
1567 {
1568 return tcx.rendered_precise_capturing_args(opaque_def_id);
1569 }
1570
1571 tcx.hir_node_by_def_id(def_id).expect_opaque_ty().bounds.iter().find_map(|bound| match bound {
1572 hir::GenericBound::Use(args, ..) => {
1573 Some(&*tcx.arena.alloc_from_iter(args.iter().map(|arg| match arg {
1574 PreciseCapturingArgKind::Lifetime(_) => {
1575 PreciseCapturingArgKind::Lifetime(arg.name())
1576 }
1577 PreciseCapturingArgKind::Param(_) => PreciseCapturingArgKind::Param(arg.name()),
1578 })))
1579 }
1580 _ => None,
1581 })
1582}
1583
1584fn const_param_default<'tcx>(
1585 tcx: TyCtxt<'tcx>,
1586 local_def_id: LocalDefId,
1587) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1588 let hir::Node::GenericParam(hir::GenericParam {
1589 kind: hir::GenericParamKind::Const { default: Some(default_ct), .. },
1590 ..
1591 }) = tcx.hir_node_by_def_id(local_def_id)
1592 else {
1593 ::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(local_def_id),
format_args!("`const_param_default` expected a generic parameter with a constant"))span_bug!(
1594 tcx.def_span(local_def_id),
1595 "`const_param_default` expected a generic parameter with a constant"
1596 )
1597 };
1598
1599 let icx = ItemCtxt::new(tcx, local_def_id);
1600
1601 let def_id = local_def_id.to_def_id();
1602 let identity_args = ty::GenericArgs::identity_for_item(tcx, tcx.parent(def_id));
1603
1604 let ct = icx.lowerer().lower_const_arg(
1605 default_ct,
1606 tcx.type_of(def_id).instantiate(tcx, identity_args).skip_norm_wip(),
1607 );
1608 ty::EarlyBinder::bind(ct)
1609}
1610
1611fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKind {
1612 let hir_id = tcx.local_def_id_to_hir_id(def);
1613 let const_arg_id = tcx.parent_hir_id(hir_id);
1614 match tcx.hir_node(const_arg_id) {
1615 hir::Node::ConstArg(_) => {
1616 let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id));
1617 if tcx.features().generic_const_exprs() {
1618 ty::AnonConstKind::GCE
1619 } else if tcx.features().generic_const_args() {
1620 if !is_anon_const_rhs_of_const_item(tcx, def) {
1624 return ty::AnonConstKind::MCG;
1625 }
1626
1627 let body = tcx.hir_body_owned_by(def);
1628 let mut visitor = GCAParamVisitor(tcx);
1629 match visitor.visit_body(body) {
1630 ControlFlow::Break(UsesParam) => ty::AnonConstKind::GCA,
1631 ControlFlow::Continue(()) => ty::AnonConstKind::MCG,
1632 }
1633 } else if tcx.features().min_generic_const_args() {
1634 ty::AnonConstKind::MCG
1635 } else if let hir::Node::Expr(hir::Expr {
1636 kind: hir::ExprKind::Repeat(_, repeat_count),
1637 ..
1638 }) = parent_hir_node
1639 && repeat_count.hir_id == const_arg_id
1640 {
1641 ty::AnonConstKind::RepeatExprCount
1642 } else {
1643 ty::AnonConstKind::MCG
1644 }
1645 }
1646 _ => ty::AnonConstKind::NonTypeSystem,
1647 }
1648}
1649
1650fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
1651 let hir_id = tcx.local_def_id_to_hir_id(def_id);
1652 let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false };
1653 let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. })
1654 | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. })
1655 | Node::TraitItem(hir::TraitItem {
1656 kind: hir::TraitItemKind::Const(_, Some(ct_rhs), _),
1657 ..
1658 })) = grandparent_node
1659 else {
1660 return false;
1661 };
1662 let hir::ConstItemRhs::TypeConst(hir::ConstArg {
1663 kind: hir::ConstArgKind::Anon(rhs_anon), ..
1664 }) = ct_rhs
1665 else {
1666 return false;
1667 };
1668 def_id == rhs_anon.def_id
1669}
1670
1671struct GCAParamVisitor<'tcx>(TyCtxt<'tcx>);
1672
1673struct UsesParam;
1674
1675impl<'tcx> Visitor<'tcx> for GCAParamVisitor<'tcx> {
1676 type NestedFilter = nested_filter::OnlyBodies;
1677 type Result = ControlFlow<UsesParam>;
1678
1679 fn maybe_tcx(&mut self) -> TyCtxt<'tcx> {
1680 self.0
1681 }
1682
1683 fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow<UsesParam> {
1684 if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) =
1685 path.res
1686 {
1687 return ControlFlow::Break(UsesParam);
1688 }
1689
1690 intravisit::walk_path(self, path)
1691 }
1692}
1693
1694x;#[instrument(level = "debug", skip(tcx), ret)]
1695fn const_of_item<'tcx>(
1696 tcx: TyCtxt<'tcx>,
1697 def_id: LocalDefId,
1698) -> ty::EarlyBinder<'tcx, Const<'tcx>> {
1699 let ct_rhs = match tcx.hir_node_by_def_id(def_id) {
1700 hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(.., ct), .. }) => *ct,
1701 hir::Node::TraitItem(hir::TraitItem {
1702 kind: hir::TraitItemKind::Const(_, ct, _), ..
1703 }) => ct.expect("no default value for trait assoc const"),
1704 hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(.., ct), .. }) => *ct,
1705 _ => {
1706 span_bug!(tcx.def_span(def_id), "`const_of_item` expected a const or assoc const item")
1707 }
1708 };
1709 let ct_arg = match ct_rhs {
1710 hir::ConstItemRhs::TypeConst(ct_arg) => ct_arg,
1711 hir::ConstItemRhs::Body(_) => {
1712 let e = tcx.dcx().span_delayed_bug(
1713 tcx.def_span(def_id),
1714 "cannot call const_of_item on a non-type_const",
1715 );
1716 return ty::EarlyBinder::bind(Const::new_error(tcx, e));
1717 }
1718 };
1719 let icx = ItemCtxt::new(tcx, def_id);
1720 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
1721 let ct = icx.lowerer().lower_const_arg(
1722 ct_arg,
1723 tcx.type_of(def_id.to_def_id()).instantiate(tcx, identity_args).skip_norm_wip(),
1724 );
1725 if let Err(e) = icx.check_tainted_by_errors()
1726 && !ct.references_error()
1727 {
1728 ty::EarlyBinder::bind(Const::new_error(tcx, e))
1729 } else {
1730 ty::EarlyBinder::bind(ct)
1731 }
1732}