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