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