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