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