1use std::cell::LazyCell;
2use std::ops::ControlFlow;
3
4use rustc_abi::FieldIdx;
5use rustc_data_structures::unord::{UnordMap, UnordSet};
6use rustc_errors::MultiSpan;
7use rustc_errors::codes::*;
8use rustc_hir::def::{CtorKind, DefKind};
9use rustc_hir::{LangItem, Node, intravisit};
10use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
11use rustc_infer::traits::{Obligation, ObligationCauseCode};
12use rustc_lint_defs::builtin::{
13 REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS,
14};
15use rustc_middle::hir::nested_filter;
16use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
17use rustc_middle::middle::stability::EvalResult;
18use rustc_middle::span_bug;
19use rustc_middle::ty::error::TypeErrorToStringExt;
20use rustc_middle::ty::fold::{BottomUpFolder, fold_regions};
21use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
22use rustc_middle::ty::util::{Discr, IntTypeExt};
23use rustc_middle::ty::{
24 AdtDef, GenericArgKind, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
25};
26use rustc_session::lint::builtin::UNINHABITED_STATIC;
27use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
28use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedDirective;
29use rustc_trait_selection::traits;
30use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
31use rustc_type_ir::fold::TypeFoldable;
32use tracing::{debug, instrument};
33use ty::TypingMode;
34use {rustc_attr_parsing as attr, rustc_hir as hir};
35
36use super::compare_impl_item::check_type_bounds;
37use super::*;
38use crate::check::intrinsicck::InlineAsmCtxt;
39
40pub fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: ExternAbi) {
41 if !tcx.sess.target.is_abi_supported(abi) {
42 struct_span_code_err!(
43 tcx.dcx(),
44 span,
45 E0570,
46 "`{abi}` is not a supported ABI for the current target",
47 )
48 .emit();
49 }
50}
51
52pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) {
53 if !tcx.sess.target.is_abi_supported(abi) {
54 tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| {
55 lint.primary_message(format!(
56 "the calling convention {abi} is not supported on this target"
57 ));
58 });
59 }
60}
61
62fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
63 let def = tcx.adt_def(def_id);
64 let span = tcx.def_span(def_id);
65 def.destructor(tcx); if def.repr().simd() {
68 check_simd(tcx, span, def_id);
69 }
70
71 check_transparent(tcx, def);
72 check_packed(tcx, span, def);
73 check_unsafe_fields(tcx, def_id);
74}
75
76fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
77 let def = tcx.adt_def(def_id);
78 let span = tcx.def_span(def_id);
79 def.destructor(tcx); check_transparent(tcx, def);
81 check_union_fields(tcx, span, def_id);
82 check_packed(tcx, span, def);
83}
84
85fn allowed_union_or_unsafe_field<'tcx>(
86 tcx: TyCtxt<'tcx>,
87 ty: Ty<'tcx>,
88 typing_env: ty::TypingEnv<'tcx>,
89 span: Span,
90) -> bool {
91 if ty.is_trivially_pure_clone_copy() {
96 return true;
97 }
98 let def_id = tcx
101 .lang_items()
102 .get(LangItem::BikeshedGuaranteedNoDrop)
103 .unwrap_or_else(|| tcx.require_lang_item(LangItem::Copy, Some(span)));
104 let Ok(ty) = tcx.try_normalize_erasing_regions(typing_env, ty) else {
105 tcx.dcx().span_delayed_bug(span, "could not normalize field type");
106 return true;
107 };
108 let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env);
109 infcx.predicate_must_hold_modulo_regions(&Obligation::new(
110 tcx,
111 ObligationCause::dummy_with_span(span),
112 param_env,
113 ty::TraitRef::new(tcx, def_id, [ty]),
114 ))
115}
116
117fn check_union_fields(tcx: TyCtxt<'_>, span: Span, item_def_id: LocalDefId) -> bool {
119 let def = tcx.adt_def(item_def_id);
120 assert!(def.is_union());
121
122 let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
123 let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
124
125 for field in &def.non_enum_variant().fields {
126 if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
127 let (field_span, ty_span) = match tcx.hir().get_if_local(field.did) {
128 Some(Node::Field(field)) => (field.span, field.ty.span),
130 _ => unreachable!("mir field has to correspond to hir field"),
131 };
132 tcx.dcx().emit_err(errors::InvalidUnionField {
133 field_span,
134 sugg: errors::InvalidUnionFieldSuggestion {
135 lo: ty_span.shrink_to_lo(),
136 hi: ty_span.shrink_to_hi(),
137 },
138 note: (),
139 });
140 return false;
141 }
142 }
143
144 true
145}
146
147fn check_unsafe_fields(tcx: TyCtxt<'_>, item_def_id: LocalDefId) {
149 let span = tcx.def_span(item_def_id);
150 let def = tcx.adt_def(item_def_id);
151
152 let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id);
153 let args = ty::GenericArgs::identity_for_item(tcx, item_def_id);
154
155 for field in def.all_fields() {
156 if !field.safety.is_unsafe() {
157 continue;
158 }
159
160 if !allowed_union_or_unsafe_field(tcx, field.ty(tcx, args), typing_env, span) {
161 let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.expect_local()) else {
162 unreachable!("field has to correspond to hir field")
163 };
164 let ty_span = field.ty.span;
165 tcx.dcx().emit_err(errors::InvalidUnsafeField {
166 field_span: field.span,
167 sugg: errors::InvalidUnsafeFieldSuggestion {
168 lo: ty_span.shrink_to_lo(),
169 hi: ty_span.shrink_to_hi(),
170 },
171 note: (),
172 });
173 }
174 }
175}
176
177fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
179 let ty = tcx.type_of(def_id).instantiate_identity();
185 let span = tcx.def_span(def_id);
186 let layout = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
187 Ok(l) => l,
188 Err(LayoutError::SizeOverflow(_))
190 if matches!(tcx.def_kind(def_id), DefKind::Static{ .. }
191 if tcx.def_kind(tcx.local_parent(def_id)) == DefKind::ForeignMod) =>
192 {
193 tcx.dcx().emit_err(errors::TooLargeStatic { span });
194 return;
195 }
196 Err(e) => {
198 tcx.dcx().span_delayed_bug(span, format!("{e:?}"));
199 return;
200 }
201 };
202 if layout.is_uninhabited() {
203 tcx.node_span_lint(
204 UNINHABITED_STATIC,
205 tcx.local_def_id_to_hir_id(def_id),
206 span,
207 |lint| {
208 lint.primary_message("static of uninhabited type");
209 lint
210 .note("uninhabited statics cannot be initialized, and any access would be an immediate error");
211 },
212 );
213 }
214}
215
216fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
219 let hir::OpaqueTy { origin, .. } = *tcx.hir().expect_opaque_ty(def_id);
220
221 if tcx.sess.opts.actually_rustdoc {
226 return;
227 }
228
229 if tcx.type_of(def_id).instantiate_identity().references_error() {
230 return;
231 }
232 if check_opaque_for_cycles(tcx, def_id).is_err() {
233 return;
234 }
235
236 let _ = check_opaque_meets_bounds(tcx, def_id, origin);
237}
238
239pub(super) fn check_opaque_for_cycles<'tcx>(
241 tcx: TyCtxt<'tcx>,
242 def_id: LocalDefId,
243) -> Result<(), ErrorGuaranteed> {
244 let args = GenericArgs::identity_for_item(tcx, def_id);
245
246 if tcx.try_expand_impl_trait_type(def_id.to_def_id(), args).is_err() {
249 let reported = opaque_type_cycle_error(tcx, def_id);
250 return Err(reported);
251 }
252
253 Ok(())
254}
255
256#[instrument(level = "debug", skip(tcx))]
272fn check_opaque_meets_bounds<'tcx>(
273 tcx: TyCtxt<'tcx>,
274 def_id: LocalDefId,
275 origin: hir::OpaqueTyOrigin<LocalDefId>,
276) -> Result<(), ErrorGuaranteed> {
277 let (span, definition_def_id) =
278 if let Some((span, def_id)) = best_definition_site_of_opaque(tcx, def_id, origin) {
279 (span, Some(def_id))
280 } else {
281 (tcx.def_span(def_id), None)
282 };
283
284 let defining_use_anchor = match origin {
285 hir::OpaqueTyOrigin::FnReturn { parent, .. }
286 | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
287 | hir::OpaqueTyOrigin::TyAlias { parent, .. } => parent,
288 };
289 let param_env = tcx.param_env(defining_use_anchor);
290
291 let infcx = tcx.infer_ctxt().build(if tcx.next_trait_solver_globally() {
293 TypingMode::post_borrowck_analysis(tcx, defining_use_anchor)
294 } else {
295 TypingMode::analysis_in_body(tcx, defining_use_anchor)
296 });
297 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
298
299 let args = match origin {
300 hir::OpaqueTyOrigin::FnReturn { parent, .. }
301 | hir::OpaqueTyOrigin::AsyncFn { parent, .. }
302 | hir::OpaqueTyOrigin::TyAlias { parent, .. } => GenericArgs::identity_for_item(
303 tcx, parent,
304 )
305 .extend_to(tcx, def_id.to_def_id(), |param, _| {
306 tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local()).into()
307 }),
308 };
309
310 let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
311
312 let hidden_ty = tcx.type_of(def_id.to_def_id()).instantiate(tcx, args);
319 let hidden_ty = fold_regions(tcx, hidden_ty, |re, _dbi| match re.kind() {
320 ty::ReErased => infcx.next_region_var(RegionVariableOrigin::MiscVariable(span)),
321 _ => re,
322 });
323
324 for (predicate, pred_span) in
328 tcx.explicit_item_bounds(def_id).iter_instantiated_copied(tcx, args)
329 {
330 let predicate = predicate.fold_with(&mut BottomUpFolder {
331 tcx,
332 ty_op: |ty| if ty == opaque_ty { hidden_ty } else { ty },
333 lt_op: |lt| lt,
334 ct_op: |ct| ct,
335 });
336
337 ocx.register_obligation(Obligation::new(
338 tcx,
339 ObligationCause::new(
340 span,
341 def_id,
342 ObligationCauseCode::OpaqueTypeBound(pred_span, definition_def_id),
343 ),
344 param_env,
345 predicate,
346 ));
347 }
348
349 let misc_cause = ObligationCause::misc(span, def_id);
350 match ocx.eq(&misc_cause, param_env, opaque_ty, hidden_ty) {
354 Ok(()) => {}
355 Err(ty_err) => {
356 let ty_err = ty_err.to_string(tcx);
362 let guar = tcx.dcx().span_delayed_bug(
363 span,
364 format!("could not unify `{hidden_ty}` with revealed type:\n{ty_err}"),
365 );
366 return Err(guar);
367 }
368 }
369
370 let predicate =
374 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(hidden_ty.into())));
375 ocx.register_obligation(Obligation::new(tcx, misc_cause.clone(), param_env, predicate));
376
377 let errors = ocx.select_all_or_error();
380 if !errors.is_empty() {
381 let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
382 return Err(guar);
383 }
384
385 let wf_tys = ocx.assumed_wf_types_and_report_errors(param_env, defining_use_anchor)?;
386 ocx.resolve_regions_and_report_errors(defining_use_anchor, param_env, wf_tys)?;
387
388 if infcx.next_trait_solver() {
389 Ok(())
390 } else if let hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } =
391 origin
392 {
393 let _ = infcx.take_opaque_types();
399 Ok(())
400 } else {
401 for (mut key, mut ty) in infcx.take_opaque_types() {
403 ty.ty = infcx.resolve_vars_if_possible(ty.ty);
404 key = infcx.resolve_vars_if_possible(key);
405 sanity_check_found_hidden_type(tcx, key, ty)?;
406 }
407 Ok(())
408 }
409}
410
411fn best_definition_site_of_opaque<'tcx>(
412 tcx: TyCtxt<'tcx>,
413 opaque_def_id: LocalDefId,
414 origin: hir::OpaqueTyOrigin<LocalDefId>,
415) -> Option<(Span, LocalDefId)> {
416 struct TaitConstraintLocator<'tcx> {
417 opaque_def_id: LocalDefId,
418 tcx: TyCtxt<'tcx>,
419 }
420 impl<'tcx> TaitConstraintLocator<'tcx> {
421 fn check(&self, item_def_id: LocalDefId) -> ControlFlow<(Span, LocalDefId)> {
422 if !self.tcx.has_typeck_results(item_def_id) {
423 return ControlFlow::Continue(());
424 }
425
426 if let Some(hidden_ty) =
427 self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
428 {
429 ControlFlow::Break((hidden_ty.span, item_def_id))
430 } else {
431 ControlFlow::Continue(())
432 }
433 }
434 }
435 impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
436 type NestedFilter = nested_filter::All;
437 type Result = ControlFlow<(Span, LocalDefId)>;
438 fn nested_visit_map(&mut self) -> Self::Map {
439 self.tcx.hir()
440 }
441 fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) -> Self::Result {
442 if let hir::ExprKind::Closure(closure) = ex.kind {
443 self.check(closure.def_id)?;
444 }
445 intravisit::walk_expr(self, ex)
446 }
447 fn visit_item(&mut self, it: &'tcx hir::Item<'tcx>) -> Self::Result {
448 self.check(it.owner_id.def_id)?;
449 intravisit::walk_item(self, it)
450 }
451 fn visit_impl_item(&mut self, it: &'tcx hir::ImplItem<'tcx>) -> Self::Result {
452 self.check(it.owner_id.def_id)?;
453 intravisit::walk_impl_item(self, it)
454 }
455 fn visit_trait_item(&mut self, it: &'tcx hir::TraitItem<'tcx>) -> Self::Result {
456 self.check(it.owner_id.def_id)?;
457 intravisit::walk_trait_item(self, it)
458 }
459 fn visit_foreign_item(&mut self, it: &'tcx hir::ForeignItem<'tcx>) -> Self::Result {
460 intravisit::walk_foreign_item(self, it)
461 }
462 }
463
464 let mut locator = TaitConstraintLocator { tcx, opaque_def_id };
465 match origin {
466 hir::OpaqueTyOrigin::FnReturn { parent, .. }
467 | hir::OpaqueTyOrigin::AsyncFn { parent, .. } => locator.check(parent).break_value(),
468 hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty: true } => {
469 let impl_def_id = tcx.local_parent(parent);
470 for assoc in tcx.associated_items(impl_def_id).in_definition_order() {
471 match assoc.kind {
472 ty::AssocKind::Const | ty::AssocKind::Fn => {
473 if let ControlFlow::Break(span) = locator.check(assoc.def_id.expect_local())
474 {
475 return Some(span);
476 }
477 }
478 ty::AssocKind::Type => {}
479 }
480 }
481
482 None
483 }
484 hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
485 let scope = tcx.hir().get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
486 let found = if scope == hir::CRATE_HIR_ID {
487 tcx.hir().walk_toplevel_module(&mut locator)
488 } else {
489 match tcx.hir_node(scope) {
490 Node::Item(it) => locator.visit_item(it),
491 Node::ImplItem(it) => locator.visit_impl_item(it),
492 Node::TraitItem(it) => locator.visit_trait_item(it),
493 Node::ForeignItem(it) => locator.visit_foreign_item(it),
494 other => bug!("{:?} is not a valid scope for an opaque type item", other),
495 }
496 };
497 found.break_value()
498 }
499 }
500}
501
502fn sanity_check_found_hidden_type<'tcx>(
503 tcx: TyCtxt<'tcx>,
504 key: ty::OpaqueTypeKey<'tcx>,
505 mut ty: ty::OpaqueHiddenType<'tcx>,
506) -> Result<(), ErrorGuaranteed> {
507 if ty.ty.is_ty_var() {
508 return Ok(());
510 }
511 if let ty::Alias(ty::Opaque, alias) = ty.ty.kind() {
512 if alias.def_id == key.def_id.to_def_id() && alias.args == key.args {
513 return Ok(());
516 }
517 }
518 let strip_vars = |ty: Ty<'tcx>| {
519 ty.fold_with(&mut BottomUpFolder {
520 tcx,
521 ty_op: |t| t,
522 ct_op: |c| c,
523 lt_op: |l| match l.kind() {
524 RegionKind::ReVar(_) => tcx.lifetimes.re_erased,
525 _ => l,
526 },
527 })
528 };
529 ty.ty = strip_vars(ty.ty);
532 let hidden_ty = tcx.type_of(key.def_id).instantiate(tcx, key.args);
534 let hidden_ty = strip_vars(hidden_ty);
535
536 if hidden_ty == ty.ty {
538 Ok(())
539 } else {
540 let span = tcx.def_span(key.def_id);
541 let other = ty::OpaqueHiddenType { ty: hidden_ty, span };
542 Err(ty.build_mismatch_error(&other, tcx)?.emit())
543 }
544}
545
546fn check_opaque_precise_captures<'tcx>(tcx: TyCtxt<'tcx>, opaque_def_id: LocalDefId) {
555 let hir::OpaqueTy { bounds, .. } = *tcx.hir_node_by_def_id(opaque_def_id).expect_opaque_ty();
556 let Some(precise_capturing_args) = bounds.iter().find_map(|bound| match *bound {
557 hir::GenericBound::Use(bounds, ..) => Some(bounds),
558 _ => None,
559 }) else {
560 return;
562 };
563
564 let mut expected_captures = UnordSet::default();
565 let mut shadowed_captures = UnordSet::default();
566 let mut seen_params = UnordMap::default();
567 let mut prev_non_lifetime_param = None;
568 for arg in precise_capturing_args {
569 let (hir_id, ident) = match *arg {
570 hir::PreciseCapturingArg::Param(hir::PreciseCapturingNonLifetimeArg {
571 hir_id,
572 ident,
573 ..
574 }) => {
575 if prev_non_lifetime_param.is_none() {
576 prev_non_lifetime_param = Some(ident);
577 }
578 (hir_id, ident)
579 }
580 hir::PreciseCapturingArg::Lifetime(&hir::Lifetime { hir_id, ident, .. }) => {
581 if let Some(prev_non_lifetime_param) = prev_non_lifetime_param {
582 tcx.dcx().emit_err(errors::LifetimesMustBeFirst {
583 lifetime_span: ident.span,
584 name: ident.name,
585 other_span: prev_non_lifetime_param.span,
586 });
587 }
588 (hir_id, ident)
589 }
590 };
591
592 let ident = ident.normalize_to_macros_2_0();
593 if let Some(span) = seen_params.insert(ident, ident.span) {
594 tcx.dcx().emit_err(errors::DuplicatePreciseCapture {
595 name: ident.name,
596 first_span: span,
597 second_span: ident.span,
598 });
599 }
600
601 match tcx.named_bound_var(hir_id) {
602 Some(ResolvedArg::EarlyBound(def_id)) => {
603 expected_captures.insert(def_id.to_def_id());
604
605 if let DefKind::LifetimeParam = tcx.def_kind(def_id)
611 && let Some(def_id) = tcx
612 .map_opaque_lifetime_to_parent_lifetime(def_id)
613 .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
614 {
615 shadowed_captures.insert(def_id);
616 }
617 }
618 _ => {
619 tcx.dcx().span_delayed_bug(
620 tcx.hir().span(hir_id),
621 "parameter should have been resolved",
622 );
623 }
624 }
625 }
626
627 let variances = tcx.variances_of(opaque_def_id);
628 let mut def_id = Some(opaque_def_id.to_def_id());
629 while let Some(generics) = def_id {
630 let generics = tcx.generics_of(generics);
631 def_id = generics.parent;
632
633 for param in &generics.own_params {
634 if expected_captures.contains(¶m.def_id) {
635 assert_eq!(
636 variances[param.index as usize],
637 ty::Invariant,
638 "precise captured param should be invariant"
639 );
640 continue;
641 }
642 if shadowed_captures.contains(¶m.def_id) {
646 continue;
647 }
648
649 match param.kind {
650 ty::GenericParamDefKind::Lifetime => {
651 let use_span = tcx.def_span(param.def_id);
652 let opaque_span = tcx.def_span(opaque_def_id);
653 if variances[param.index as usize] == ty::Invariant {
655 if let DefKind::OpaqueTy = tcx.def_kind(tcx.parent(param.def_id))
656 && let Some(def_id) = tcx
657 .map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local())
658 .opt_param_def_id(tcx, tcx.parent(opaque_def_id.to_def_id()))
659 {
660 tcx.dcx().emit_err(errors::LifetimeNotCaptured {
661 opaque_span,
662 use_span,
663 param_span: tcx.def_span(def_id),
664 });
665 } else {
666 if tcx.def_kind(tcx.parent(param.def_id)) == DefKind::Trait {
667 tcx.dcx().emit_err(errors::LifetimeImplicitlyCaptured {
668 opaque_span,
669 param_span: tcx.def_span(param.def_id),
670 });
671 } else {
672 tcx.dcx().emit_err(errors::LifetimeNotCaptured {
677 opaque_span,
678 use_span: opaque_span,
679 param_span: use_span,
680 });
681 }
682 }
683 continue;
684 }
685 }
686 ty::GenericParamDefKind::Type { .. } => {
687 if matches!(tcx.def_kind(param.def_id), DefKind::Trait | DefKind::TraitAlias) {
688 tcx.dcx().emit_err(errors::SelfTyNotCaptured {
690 trait_span: tcx.def_span(param.def_id),
691 opaque_span: tcx.def_span(opaque_def_id),
692 });
693 } else {
694 tcx.dcx().emit_err(errors::ParamNotCaptured {
696 param_span: tcx.def_span(param.def_id),
697 opaque_span: tcx.def_span(opaque_def_id),
698 kind: "type",
699 });
700 }
701 }
702 ty::GenericParamDefKind::Const { .. } => {
703 tcx.dcx().emit_err(errors::ParamNotCaptured {
705 param_span: tcx.def_span(param.def_id),
706 opaque_span: tcx.def_span(opaque_def_id),
707 kind: "const",
708 });
709 }
710 }
711 }
712 }
713}
714
715fn is_enum_of_nonnullable_ptr<'tcx>(
716 tcx: TyCtxt<'tcx>,
717 adt_def: AdtDef<'tcx>,
718 args: GenericArgsRef<'tcx>,
719) -> bool {
720 if adt_def.repr().inhibit_enum_layout_opt() {
721 return false;
722 }
723
724 let [var_one, var_two] = &adt_def.variants().raw[..] else {
725 return false;
726 };
727 let (([], [field]) | ([field], [])) = (&var_one.fields.raw[..], &var_two.fields.raw[..]) else {
728 return false;
729 };
730 matches!(field.ty(tcx, args).kind(), ty::FnPtr(..) | ty::Ref(..))
731}
732
733fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
734 if tcx.codegen_fn_attrs(def_id).import_linkage.is_some() {
735 if match tcx.type_of(def_id).instantiate_identity().kind() {
736 ty::RawPtr(_, _) => false,
737 ty::Adt(adt_def, args) => !is_enum_of_nonnullable_ptr(tcx, *adt_def, *args),
738 _ => true,
739 } {
740 tcx.dcx().emit_err(errors::LinkageType { span: tcx.def_span(def_id) });
741 }
742 }
743}
744
745pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
746 match tcx.def_kind(def_id) {
747 DefKind::Static { .. } => {
748 tcx.ensure_ok().typeck(def_id);
749 maybe_check_static_with_link_section(tcx, def_id);
750 check_static_inhabited(tcx, def_id);
751 check_static_linkage(tcx, def_id);
752 }
753 DefKind::Const => {
754 tcx.ensure_ok().typeck(def_id);
755 }
756 DefKind::Enum => {
757 check_enum(tcx, def_id);
758 }
759 DefKind::Fn => {
760 if let Some(i) = tcx.intrinsic(def_id) {
761 intrinsic::check_intrinsic_type(
762 tcx,
763 def_id,
764 tcx.def_ident_span(def_id).unwrap(),
765 i.name,
766 ExternAbi::Rust,
767 )
768 }
769 }
771 DefKind::Impl { of_trait } => {
772 if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
773 if tcx
774 .ensure_ok()
775 .coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
776 .is_ok()
777 {
778 check_impl_items_against_trait(tcx, def_id, impl_trait_header);
779 check_on_unimplemented(tcx, def_id);
780 }
781 }
782 }
783 DefKind::Trait => {
784 let assoc_items = tcx.associated_items(def_id);
785 check_on_unimplemented(tcx, def_id);
786
787 for &assoc_item in assoc_items.in_definition_order() {
788 match assoc_item.kind {
789 ty::AssocKind::Fn => {
790 let abi = tcx.fn_sig(assoc_item.def_id).skip_binder().abi();
791 forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
792 }
793 ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
794 let trait_args = GenericArgs::identity_for_item(tcx, def_id);
795 let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
796 tcx,
797 assoc_item,
798 assoc_item,
799 ty::TraitRef::new_from_args(tcx, def_id.to_def_id(), trait_args),
800 );
801 }
802 _ => {}
803 }
804 }
805 }
806 DefKind::Struct => {
807 check_struct(tcx, def_id);
808 }
809 DefKind::Union => {
810 check_union(tcx, def_id);
811 }
812 DefKind::OpaqueTy => {
813 check_opaque_precise_captures(tcx, def_id);
814
815 let origin = tcx.local_opaque_ty_origin(def_id);
816 if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
817 | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
818 && let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
819 && let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
820 {
821 } else {
823 check_opaque(tcx, def_id);
824 }
825 }
826 DefKind::TyAlias => {
827 check_type_alias_type_params_are_used(tcx, def_id);
828 }
829 DefKind::ForeignMod => {
830 let it = tcx.hir().expect_item(def_id);
831 let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
832 return;
833 };
834 check_abi(tcx, it.span, abi);
835
836 match abi {
837 ExternAbi::RustIntrinsic => {
838 for item in items {
839 intrinsic::check_intrinsic_type(
840 tcx,
841 item.id.owner_id.def_id,
842 item.span,
843 item.ident.name,
844 abi,
845 );
846 }
847 }
848
849 _ => {
850 for item in items {
851 let def_id = item.id.owner_id.def_id;
852 let generics = tcx.generics_of(def_id);
853 let own_counts = generics.own_counts();
854 if generics.own_params.len() - own_counts.lifetimes != 0 {
855 let (kinds, kinds_pl, egs) = match (own_counts.types, own_counts.consts)
856 {
857 (_, 0) => ("type", "types", Some("u32")),
858 (0, _) => ("const", "consts", None),
861 _ => ("type or const", "types or consts", None),
862 };
863 struct_span_code_err!(
864 tcx.dcx(),
865 item.span,
866 E0044,
867 "foreign items may not have {kinds} parameters",
868 )
869 .with_span_label(item.span, format!("can't have {kinds} parameters"))
870 .with_help(
871 format!(
874 "replace the {} parameters with concrete {}{}",
875 kinds,
876 kinds_pl,
877 egs.map(|egs| format!(" like `{egs}`")).unwrap_or_default(),
878 ),
879 )
880 .emit();
881 }
882
883 let item = tcx.hir().foreign_item(item.id);
884 match &item.kind {
885 hir::ForeignItemKind::Fn(sig, _, _) => {
886 require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
887 }
888 hir::ForeignItemKind::Static(..) => {
889 check_static_inhabited(tcx, def_id);
890 check_static_linkage(tcx, def_id);
891 }
892 _ => {}
893 }
894 }
895 }
896 }
897 }
898 DefKind::GlobalAsm => {
899 let it = tcx.hir().expect_item(def_id);
900 let hir::ItemKind::GlobalAsm(asm) = it.kind else {
901 span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it)
902 };
903 InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id);
904 }
905 _ => {}
906 }
907}
908
909pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
910 let _ = OnUnimplementedDirective::of_item(tcx, def_id.to_def_id());
912}
913
914pub(super) fn check_specialization_validity<'tcx>(
915 tcx: TyCtxt<'tcx>,
916 trait_def: &ty::TraitDef,
917 trait_item: ty::AssocItem,
918 impl_id: DefId,
919 impl_item: DefId,
920) {
921 let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
922 let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
923 if parent.is_from_trait() {
924 None
925 } else {
926 Some((parent, parent.item(tcx, trait_item.def_id)))
927 }
928 });
929
930 let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
931 match parent_item {
932 Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => {
935 Some(Err(parent_impl.def_id()))
936 }
937
938 Some(_) => Some(Ok(())),
940
941 None => {
945 if tcx.defaultness(parent_impl.def_id()).is_default() {
946 None
947 } else {
948 Some(Err(parent_impl.def_id()))
949 }
950 }
951 }
952 });
953
954 let result = opt_result.unwrap_or(Ok(()));
957
958 if let Err(parent_impl) = result {
959 if !tcx.is_impl_trait_in_trait(impl_item) {
960 report_forbidden_specialization(tcx, impl_item, parent_impl);
961 } else {
962 tcx.dcx().delayed_bug(format!("parent item: {parent_impl:?} not marked as default"));
963 }
964 }
965}
966
967fn check_impl_items_against_trait<'tcx>(
968 tcx: TyCtxt<'tcx>,
969 impl_id: LocalDefId,
970 impl_trait_header: ty::ImplTraitHeader<'tcx>,
971) {
972 let trait_ref = impl_trait_header.trait_ref.instantiate_identity();
973 if trait_ref.references_error() {
977 return;
978 }
979
980 let impl_item_refs = tcx.associated_item_def_ids(impl_id);
981
982 match impl_trait_header.polarity {
984 ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
985 ty::ImplPolarity::Negative => {
986 if let [first_item_ref, ..] = impl_item_refs {
987 let first_item_span = tcx.def_span(first_item_ref);
988 struct_span_code_err!(
989 tcx.dcx(),
990 first_item_span,
991 E0749,
992 "negative impls cannot have any items"
993 )
994 .emit();
995 }
996 return;
997 }
998 }
999
1000 let trait_def = tcx.trait_def(trait_ref.def_id);
1001
1002 for &impl_item in impl_item_refs {
1003 let ty_impl_item = tcx.associated_item(impl_item);
1004 let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
1005 tcx.associated_item(trait_item_id)
1006 } else {
1007 tcx.dcx().span_delayed_bug(tcx.def_span(impl_item), "missing associated item in trait");
1009 continue;
1010 };
1011
1012 let res = tcx.ensure_ok().compare_impl_item(impl_item.expect_local());
1013
1014 if res.is_ok() {
1015 match ty_impl_item.kind {
1016 ty::AssocKind::Fn => {
1017 compare_impl_item::refine::check_refining_return_position_impl_trait_in_trait(
1018 tcx,
1019 ty_impl_item,
1020 ty_trait_item,
1021 tcx.impl_trait_ref(ty_impl_item.container_id(tcx))
1022 .unwrap()
1023 .instantiate_identity(),
1024 );
1025 }
1026 ty::AssocKind::Const => {}
1027 ty::AssocKind::Type => {}
1028 }
1029 }
1030
1031 check_specialization_validity(
1032 tcx,
1033 trait_def,
1034 ty_trait_item,
1035 impl_id.to_def_id(),
1036 impl_item,
1037 );
1038 }
1039
1040 if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
1041 let mut missing_items = Vec::new();
1043
1044 let mut must_implement_one_of: Option<&[Ident]> =
1045 trait_def.must_implement_one_of.as_deref();
1046
1047 for &trait_item_id in tcx.associated_item_def_ids(trait_ref.def_id) {
1048 let leaf_def = ancestors.leaf_def(tcx, trait_item_id);
1049
1050 let is_implemented = leaf_def
1051 .as_ref()
1052 .is_some_and(|node_item| node_item.item.defaultness(tcx).has_value());
1053
1054 if !is_implemented && tcx.defaultness(impl_id).is_final() {
1055 missing_items.push(tcx.associated_item(trait_item_id));
1056 }
1057
1058 let is_implemented_here =
1060 leaf_def.as_ref().is_some_and(|node_item| !node_item.defining_node.is_from_trait());
1061
1062 if !is_implemented_here {
1063 let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
1064 match tcx.eval_default_body_stability(trait_item_id, full_impl_span) {
1065 EvalResult::Deny { feature, reason, issue, .. } => default_body_is_unstable(
1066 tcx,
1067 full_impl_span,
1068 trait_item_id,
1069 feature,
1070 reason,
1071 issue,
1072 ),
1073
1074 EvalResult::Allow | EvalResult::Unmarked => {}
1076 }
1077 }
1078
1079 if let Some(required_items) = &must_implement_one_of {
1080 if is_implemented_here {
1081 let trait_item = tcx.associated_item(trait_item_id);
1082 if required_items.contains(&trait_item.ident(tcx)) {
1083 must_implement_one_of = None;
1084 }
1085 }
1086 }
1087
1088 if let Some(leaf_def) = &leaf_def
1089 && !leaf_def.is_final()
1090 && let def_id = leaf_def.item.def_id
1091 && tcx.impl_method_has_trait_impl_trait_tys(def_id)
1092 {
1093 let def_kind = tcx.def_kind(def_id);
1094 let descr = tcx.def_kind_descr(def_kind, def_id);
1095 let (msg, feature) = if tcx.asyncness(def_id).is_async() {
1096 (
1097 format!("async {descr} in trait cannot be specialized"),
1098 "async functions in traits",
1099 )
1100 } else {
1101 (
1102 format!(
1103 "{descr} with return-position `impl Trait` in trait cannot be specialized"
1104 ),
1105 "return position `impl Trait` in traits",
1106 )
1107 };
1108 tcx.dcx()
1109 .struct_span_err(tcx.def_span(def_id), msg)
1110 .with_note(format!(
1111 "specialization behaves in inconsistent and surprising ways with \
1112 {feature}, and for now is disallowed"
1113 ))
1114 .emit();
1115 }
1116 }
1117
1118 if !missing_items.is_empty() {
1119 let full_impl_span = tcx.hir().span_with_body(tcx.local_def_id_to_hir_id(impl_id));
1120 missing_items_err(tcx, impl_id, &missing_items, full_impl_span);
1121 }
1122
1123 if let Some(missing_items) = must_implement_one_of {
1124 let attr_span = tcx
1125 .get_attr(trait_ref.def_id, sym::rustc_must_implement_one_of)
1126 .map(|attr| attr.span);
1127
1128 missing_items_must_implement_one_of_err(
1129 tcx,
1130 tcx.def_span(impl_id),
1131 missing_items,
1132 attr_span,
1133 );
1134 }
1135 }
1136}
1137
1138fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
1139 let t = tcx.type_of(def_id).instantiate_identity();
1140 if let ty::Adt(def, args) = t.kind()
1141 && def.is_struct()
1142 {
1143 let fields = &def.non_enum_variant().fields;
1144 if fields.is_empty() {
1145 struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
1146 return;
1147 }
1148
1149 let array_field = &fields[FieldIdx::ZERO];
1150 let array_ty = array_field.ty(tcx, args);
1151 let ty::Array(element_ty, len_const) = array_ty.kind() else {
1152 struct_span_code_err!(
1153 tcx.dcx(),
1154 sp,
1155 E0076,
1156 "SIMD vector's only field must be an array"
1157 )
1158 .with_span_label(tcx.def_span(array_field.did), "not an array")
1159 .emit();
1160 return;
1161 };
1162
1163 if let Some(second_field) = fields.get(FieldIdx::from_u32(1)) {
1164 struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot have multiple fields")
1165 .with_span_label(tcx.def_span(second_field.did), "excess field")
1166 .emit();
1167 return;
1168 }
1169
1170 if let Some(len) = len_const.try_to_target_usize(tcx) {
1175 if len == 0 {
1176 struct_span_code_err!(tcx.dcx(), sp, E0075, "SIMD vector cannot be empty").emit();
1177 return;
1178 } else if len > MAX_SIMD_LANES {
1179 struct_span_code_err!(
1180 tcx.dcx(),
1181 sp,
1182 E0075,
1183 "SIMD vector cannot have more than {MAX_SIMD_LANES} elements",
1184 )
1185 .emit();
1186 return;
1187 }
1188 }
1189
1190 match element_ty.kind() {
1195 ty::Param(_) => (), ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), _ => {
1198 struct_span_code_err!(
1199 tcx.dcx(),
1200 sp,
1201 E0077,
1202 "SIMD vector element type should be a \
1203 primitive scalar (integer/float/pointer) type"
1204 )
1205 .emit();
1206 return;
1207 }
1208 }
1209 }
1210}
1211
1212pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
1213 let repr = def.repr();
1214 if repr.packed() {
1215 for attr in tcx.get_attrs(def.did(), sym::repr) {
1216 for r in attr::parse_repr_attr(tcx.sess, attr) {
1217 if let attr::ReprPacked(pack) = r
1218 && let Some(repr_pack) = repr.pack
1219 && pack != repr_pack
1220 {
1221 struct_span_code_err!(
1222 tcx.dcx(),
1223 sp,
1224 E0634,
1225 "type has conflicting packed representation hints"
1226 )
1227 .emit();
1228 }
1229 }
1230 }
1231 if repr.align.is_some() {
1232 struct_span_code_err!(
1233 tcx.dcx(),
1234 sp,
1235 E0587,
1236 "type has conflicting packed and align representation hints"
1237 )
1238 .emit();
1239 } else if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
1240 let mut err = struct_span_code_err!(
1241 tcx.dcx(),
1242 sp,
1243 E0588,
1244 "packed type cannot transitively contain a `#[repr(align)]` type"
1245 );
1246
1247 err.span_note(
1248 tcx.def_span(def_spans[0].0),
1249 format!("`{}` has a `#[repr(align)]` attribute", tcx.item_name(def_spans[0].0)),
1250 );
1251
1252 if def_spans.len() > 2 {
1253 let mut first = true;
1254 for (adt_def, span) in def_spans.iter().skip(1).rev() {
1255 let ident = tcx.item_name(*adt_def);
1256 err.span_note(
1257 *span,
1258 if first {
1259 format!(
1260 "`{}` contains a field of type `{}`",
1261 tcx.type_of(def.did()).instantiate_identity(),
1262 ident
1263 )
1264 } else {
1265 format!("...which contains a field of type `{ident}`")
1266 },
1267 );
1268 first = false;
1269 }
1270 }
1271
1272 err.emit();
1273 }
1274 }
1275}
1276
1277pub(super) fn check_packed_inner(
1278 tcx: TyCtxt<'_>,
1279 def_id: DefId,
1280 stack: &mut Vec<DefId>,
1281) -> Option<Vec<(DefId, Span)>> {
1282 if let ty::Adt(def, args) = tcx.type_of(def_id).instantiate_identity().kind() {
1283 if def.is_struct() || def.is_union() {
1284 if def.repr().align.is_some() {
1285 return Some(vec![(def.did(), DUMMY_SP)]);
1286 }
1287
1288 stack.push(def_id);
1289 for field in &def.non_enum_variant().fields {
1290 if let ty::Adt(def, _) = field.ty(tcx, args).kind()
1291 && !stack.contains(&def.did())
1292 && let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
1293 {
1294 defs.push((def.did(), field.ident(tcx).span));
1295 return Some(defs);
1296 }
1297 }
1298 stack.pop();
1299 }
1300 }
1301
1302 None
1303}
1304
1305pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
1306 if !adt.repr().transparent() {
1307 return;
1308 }
1309
1310 if adt.is_union() && !tcx.features().transparent_unions() {
1311 feature_err(
1312 &tcx.sess,
1313 sym::transparent_unions,
1314 tcx.def_span(adt.did()),
1315 "transparent unions are unstable",
1316 )
1317 .emit();
1318 }
1319
1320 if adt.variants().len() != 1 {
1321 bad_variant_count(tcx, adt, tcx.def_span(adt.did()), adt.did());
1322 return;
1324 }
1325
1326 let field_infos = adt.all_fields().map(|field| {
1329 let ty = field.ty(tcx, GenericArgs::identity_for_item(tcx, field.did));
1330 let typing_env = ty::TypingEnv::non_body_analysis(tcx, field.did);
1331 let layout = tcx.layout_of(typing_env.as_query_input(ty));
1332 let span = tcx.hir().span_if_local(field.did).unwrap();
1334 let trivial = layout.is_ok_and(|layout| layout.is_1zst());
1335 if !trivial {
1336 return (span, trivial, None);
1337 }
1338 fn check_non_exhaustive<'tcx>(
1341 tcx: TyCtxt<'tcx>,
1342 t: Ty<'tcx>,
1343 ) -> ControlFlow<(&'static str, DefId, GenericArgsRef<'tcx>, bool)> {
1344 match t.kind() {
1345 ty::Tuple(list) => list.iter().try_for_each(|t| check_non_exhaustive(tcx, t)),
1346 ty::Array(ty, _) => check_non_exhaustive(tcx, *ty),
1347 ty::Adt(def, args) => {
1348 if !def.did().is_local() && !tcx.has_attr(def.did(), sym::rustc_pub_transparent)
1349 {
1350 let non_exhaustive = def.is_variant_list_non_exhaustive()
1351 || def
1352 .variants()
1353 .iter()
1354 .any(ty::VariantDef::is_field_list_non_exhaustive);
1355 let has_priv = def.all_fields().any(|f| !f.vis.is_public());
1356 if non_exhaustive || has_priv {
1357 return ControlFlow::Break((
1358 def.descr(),
1359 def.did(),
1360 args,
1361 non_exhaustive,
1362 ));
1363 }
1364 }
1365 def.all_fields()
1366 .map(|field| field.ty(tcx, args))
1367 .try_for_each(|t| check_non_exhaustive(tcx, t))
1368 }
1369 _ => ControlFlow::Continue(()),
1370 }
1371 }
1372
1373 (span, trivial, check_non_exhaustive(tcx, ty).break_value())
1374 });
1375
1376 let non_trivial_fields = field_infos
1377 .clone()
1378 .filter_map(|(span, trivial, _non_exhaustive)| if !trivial { Some(span) } else { None });
1379 let non_trivial_count = non_trivial_fields.clone().count();
1380 if non_trivial_count >= 2 {
1381 bad_non_zero_sized_fields(
1382 tcx,
1383 adt,
1384 non_trivial_count,
1385 non_trivial_fields,
1386 tcx.def_span(adt.did()),
1387 );
1388 return;
1389 }
1390 let mut prev_non_exhaustive_1zst = false;
1391 for (span, _trivial, non_exhaustive_1zst) in field_infos {
1392 if let Some((descr, def_id, args, non_exhaustive)) = non_exhaustive_1zst {
1393 if non_trivial_count > 0 || prev_non_exhaustive_1zst {
1396 tcx.node_span_lint(
1397 REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
1398 tcx.local_def_id_to_hir_id(adt.did().expect_local()),
1399 span,
1400 |lint| {
1401 lint.primary_message(
1402 "zero-sized fields in `repr(transparent)` cannot \
1403 contain external non-exhaustive types",
1404 );
1405 let note = if non_exhaustive {
1406 "is marked with `#[non_exhaustive]`"
1407 } else {
1408 "contains private fields"
1409 };
1410 let field_ty = tcx.def_path_str_with_args(def_id, args);
1411 lint.note(format!(
1412 "this {descr} contains `{field_ty}`, which {note}, \
1413 and makes it not a breaking change to become \
1414 non-zero-sized in the future."
1415 ));
1416 },
1417 )
1418 } else {
1419 prev_non_exhaustive_1zst = true;
1420 }
1421 }
1422 }
1423}
1424
1425#[allow(trivial_numeric_casts)]
1426fn check_enum(tcx: TyCtxt<'_>, def_id: LocalDefId) {
1427 let def = tcx.adt_def(def_id);
1428 def.destructor(tcx); if def.variants().is_empty() {
1431 if let Some(attr) = tcx.get_attrs(def_id, sym::repr).next() {
1432 struct_span_code_err!(
1433 tcx.dcx(),
1434 attr.span,
1435 E0084,
1436 "unsupported representation for zero-variant enum"
1437 )
1438 .with_span_label(tcx.def_span(def_id), "zero-variant enum")
1439 .emit();
1440 }
1441 }
1442
1443 let repr_type_ty = def.repr().discr_type().to_ty(tcx);
1444 if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
1445 if !tcx.features().repr128() {
1446 feature_err(
1447 &tcx.sess,
1448 sym::repr128,
1449 tcx.def_span(def_id),
1450 "repr with 128-bit type is unstable",
1451 )
1452 .emit();
1453 }
1454 }
1455
1456 for v in def.variants() {
1457 if let ty::VariantDiscr::Explicit(discr_def_id) = v.discr {
1458 tcx.ensure_ok().typeck(discr_def_id.expect_local());
1459 }
1460 }
1461
1462 if def.repr().int.is_none() {
1463 let is_unit = |var: &ty::VariantDef| matches!(var.ctor_kind(), Some(CtorKind::Const));
1464 let has_disr = |var: &ty::VariantDef| matches!(var.discr, ty::VariantDiscr::Explicit(_));
1465
1466 let has_non_units = def.variants().iter().any(|var| !is_unit(var));
1467 let disr_units = def.variants().iter().any(|var| is_unit(var) && has_disr(var));
1468 let disr_non_unit = def.variants().iter().any(|var| !is_unit(var) && has_disr(var));
1469
1470 if disr_non_unit || (disr_units && has_non_units) {
1471 struct_span_code_err!(
1472 tcx.dcx(),
1473 tcx.def_span(def_id),
1474 E0732,
1475 "`#[repr(inttype)]` must be specified"
1476 )
1477 .emit();
1478 }
1479 }
1480
1481 detect_discriminant_duplicate(tcx, def);
1482 check_transparent(tcx, def);
1483 check_unsafe_fields(tcx, def_id);
1484}
1485
1486fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) {
1488 let report = |dis: Discr<'tcx>, idx, err: &mut Diag<'_>| {
1491 let var = adt.variant(idx); let (span, display_discr) = match var.discr {
1493 ty::VariantDiscr::Explicit(discr_def_id) => {
1494 if let hir::Node::AnonConst(expr) =
1496 tcx.hir_node_by_def_id(discr_def_id.expect_local())
1497 && let hir::ExprKind::Lit(lit) = &tcx.hir().body(expr.body).value.kind
1498 && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
1499 && *lit_value != dis.val
1500 {
1501 (tcx.def_span(discr_def_id), format!("`{dis}` (overflowed from `{lit_value}`)"))
1502 } else {
1503 (tcx.def_span(discr_def_id), format!("`{dis}`"))
1505 }
1506 }
1507 ty::VariantDiscr::Relative(0) => (tcx.def_span(var.def_id), format!("`{dis}`")),
1509 ty::VariantDiscr::Relative(distance_to_explicit) => {
1510 if let Some(explicit_idx) =
1515 idx.as_u32().checked_sub(distance_to_explicit).map(VariantIdx::from_u32)
1516 {
1517 let explicit_variant = adt.variant(explicit_idx);
1518 let ve_ident = var.name;
1519 let ex_ident = explicit_variant.name;
1520 let sp = if distance_to_explicit > 1 { "variants" } else { "variant" };
1521
1522 err.span_label(
1523 tcx.def_span(explicit_variant.def_id),
1524 format!(
1525 "discriminant for `{ve_ident}` incremented from this startpoint \
1526 (`{ex_ident}` + {distance_to_explicit} {sp} later \
1527 => `{ve_ident}` = {dis})"
1528 ),
1529 );
1530 }
1531
1532 (tcx.def_span(var.def_id), format!("`{dis}`"))
1533 }
1534 };
1535
1536 err.span_label(span, format!("{display_discr} assigned here"));
1537 };
1538
1539 let mut discrs = adt.discriminants(tcx).collect::<Vec<_>>();
1540
1541 let mut i = 0;
1548 while i < discrs.len() {
1549 let var_i_idx = discrs[i].0;
1550 let mut error: Option<Diag<'_, _>> = None;
1551
1552 let mut o = i + 1;
1553 while o < discrs.len() {
1554 let var_o_idx = discrs[o].0;
1555
1556 if discrs[i].1.val == discrs[o].1.val {
1557 let err = error.get_or_insert_with(|| {
1558 let mut ret = struct_span_code_err!(
1559 tcx.dcx(),
1560 tcx.def_span(adt.did()),
1561 E0081,
1562 "discriminant value `{}` assigned more than once",
1563 discrs[i].1,
1564 );
1565
1566 report(discrs[i].1, var_i_idx, &mut ret);
1567
1568 ret
1569 });
1570
1571 report(discrs[o].1, var_o_idx, err);
1572
1573 discrs[o] = *discrs.last().unwrap();
1575 discrs.pop();
1576 } else {
1577 o += 1;
1578 }
1579 }
1580
1581 if let Some(e) = error {
1582 e.emit();
1583 }
1584
1585 i += 1;
1586 }
1587}
1588
1589fn check_type_alias_type_params_are_used<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
1590 if tcx.type_alias_is_lazy(def_id) {
1591 return;
1594 }
1595
1596 let generics = tcx.generics_of(def_id);
1597 if generics.own_counts().types == 0 {
1598 return;
1599 }
1600
1601 let ty = tcx.type_of(def_id).instantiate_identity();
1602 if ty.references_error() {
1603 return;
1605 }
1606
1607 let bounded_params = LazyCell::new(|| {
1609 tcx.explicit_predicates_of(def_id)
1610 .predicates
1611 .iter()
1612 .filter_map(|(predicate, span)| {
1613 let bounded_ty = match predicate.kind().skip_binder() {
1614 ty::ClauseKind::Trait(pred) => pred.trait_ref.self_ty(),
1615 ty::ClauseKind::TypeOutlives(pred) => pred.0,
1616 _ => return None,
1617 };
1618 if let ty::Param(param) = bounded_ty.kind() {
1619 Some((param.index, span))
1620 } else {
1621 None
1622 }
1623 })
1624 .collect::<FxIndexMap<_, _>>()
1630 });
1631
1632 let mut params_used = DenseBitSet::new_empty(generics.own_params.len());
1633 for leaf in ty.walk() {
1634 if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
1635 && let ty::Param(param) = leaf_ty.kind()
1636 {
1637 debug!("found use of ty param {:?}", param);
1638 params_used.insert(param.index);
1639 }
1640 }
1641
1642 for param in &generics.own_params {
1643 if !params_used.contains(param.index)
1644 && let ty::GenericParamDefKind::Type { .. } = param.kind
1645 {
1646 let span = tcx.def_span(param.def_id);
1647 let param_name = Ident::new(param.name, span);
1648
1649 let has_explicit_bounds = bounded_params.is_empty()
1653 || (*bounded_params).get(¶m.index).is_some_and(|&&pred_sp| pred_sp != span);
1654 let const_param_help = !has_explicit_bounds;
1655
1656 let mut diag = tcx.dcx().create_err(errors::UnusedGenericParameter {
1657 span,
1658 param_name,
1659 param_def_kind: tcx.def_descr(param.def_id),
1660 help: errors::UnusedGenericParameterHelp::TyAlias { param_name },
1661 usage_spans: vec![],
1662 const_param_help,
1663 });
1664 diag.code(E0091);
1665 diag.emit();
1666 }
1667 }
1668}
1669
1670fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorGuaranteed {
1679 let span = tcx.def_span(opaque_def_id);
1680 let mut err = struct_span_code_err!(tcx.dcx(), span, E0720, "cannot resolve opaque type");
1681
1682 let mut label = false;
1683 if let Some((def_id, visitor)) = get_owner_return_paths(tcx, opaque_def_id) {
1684 let typeck_results = tcx.typeck(def_id);
1685 if visitor
1686 .returns
1687 .iter()
1688 .filter_map(|expr| typeck_results.node_type_opt(expr.hir_id))
1689 .all(|ty| matches!(ty.kind(), ty::Never))
1690 {
1691 let spans = visitor
1692 .returns
1693 .iter()
1694 .filter(|expr| typeck_results.node_type_opt(expr.hir_id).is_some())
1695 .map(|expr| expr.span)
1696 .collect::<Vec<Span>>();
1697 let span_len = spans.len();
1698 if span_len == 1 {
1699 err.span_label(spans[0], "this returned value is of `!` type");
1700 } else {
1701 let mut multispan: MultiSpan = spans.clone().into();
1702 for span in spans {
1703 multispan.push_span_label(span, "this returned value is of `!` type");
1704 }
1705 err.span_note(multispan, "these returned values have a concrete \"never\" type");
1706 }
1707 err.help("this error will resolve once the item's body returns a concrete type");
1708 } else {
1709 let mut seen = FxHashSet::default();
1710 seen.insert(span);
1711 err.span_label(span, "recursive opaque type");
1712 label = true;
1713 for (sp, ty) in visitor
1714 .returns
1715 .iter()
1716 .filter_map(|e| typeck_results.node_type_opt(e.hir_id).map(|t| (e.span, t)))
1717 .filter(|(_, ty)| !matches!(ty.kind(), ty::Never))
1718 {
1719 #[derive(Default)]
1720 struct OpaqueTypeCollector {
1721 opaques: Vec<DefId>,
1722 closures: Vec<DefId>,
1723 }
1724 impl<'tcx> ty::visit::TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector {
1725 fn visit_ty(&mut self, t: Ty<'tcx>) {
1726 match *t.kind() {
1727 ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => {
1728 self.opaques.push(def);
1729 }
1730 ty::Closure(def_id, ..) | ty::Coroutine(def_id, ..) => {
1731 self.closures.push(def_id);
1732 t.super_visit_with(self);
1733 }
1734 _ => t.super_visit_with(self),
1735 }
1736 }
1737 }
1738
1739 let mut visitor = OpaqueTypeCollector::default();
1740 ty.visit_with(&mut visitor);
1741 for def_id in visitor.opaques {
1742 let ty_span = tcx.def_span(def_id);
1743 if !seen.contains(&ty_span) {
1744 let descr = if ty.is_impl_trait() { "opaque " } else { "" };
1745 err.span_label(ty_span, format!("returning this {descr}type `{ty}`"));
1746 seen.insert(ty_span);
1747 }
1748 err.span_label(sp, format!("returning here with type `{ty}`"));
1749 }
1750
1751 for closure_def_id in visitor.closures {
1752 let Some(closure_local_did) = closure_def_id.as_local() else {
1753 continue;
1754 };
1755 let typeck_results = tcx.typeck(closure_local_did);
1756
1757 let mut label_match = |ty: Ty<'_>, span| {
1758 for arg in ty.walk() {
1759 if let ty::GenericArgKind::Type(ty) = arg.unpack()
1760 && let ty::Alias(
1761 ty::Opaque,
1762 ty::AliasTy { def_id: captured_def_id, .. },
1763 ) = *ty.kind()
1764 && captured_def_id == opaque_def_id.to_def_id()
1765 {
1766 err.span_label(
1767 span,
1768 format!(
1769 "{} captures itself here",
1770 tcx.def_descr(closure_def_id)
1771 ),
1772 );
1773 }
1774 }
1775 };
1776
1777 for capture in typeck_results.closure_min_captures_flattened(closure_local_did)
1779 {
1780 label_match(capture.place.ty(), capture.get_path_span(tcx));
1781 }
1782 if tcx.is_coroutine(closure_def_id)
1784 && let Some(coroutine_layout) = tcx.mir_coroutine_witnesses(closure_def_id)
1785 {
1786 for interior_ty in &coroutine_layout.field_tys {
1787 label_match(interior_ty.ty, interior_ty.source_info.span);
1788 }
1789 }
1790 }
1791 }
1792 }
1793 }
1794 if !label {
1795 err.span_label(span, "cannot resolve opaque type");
1796 }
1797 err.emit()
1798}
1799
1800pub(super) fn check_coroutine_obligations(
1801 tcx: TyCtxt<'_>,
1802 def_id: LocalDefId,
1803) -> Result<(), ErrorGuaranteed> {
1804 debug_assert!(!tcx.is_typeck_child(def_id.to_def_id()));
1805
1806 let typeck_results = tcx.typeck(def_id);
1807 let param_env = tcx.param_env(def_id);
1808
1809 debug!(?typeck_results.coroutine_stalled_predicates);
1810
1811 let mode = if tcx.next_trait_solver_globally() {
1812 TypingMode::post_borrowck_analysis(tcx, def_id)
1813 } else {
1814 TypingMode::analysis_in_body(tcx, def_id)
1815 };
1816
1817 let infcx = tcx
1818 .infer_ctxt()
1819 .ignoring_regions()
1822 .build(mode);
1823
1824 let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
1825 for (predicate, cause) in &typeck_results.coroutine_stalled_predicates {
1826 ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, *predicate));
1827 }
1828
1829 let errors = ocx.select_all_or_error();
1830 debug!(?errors);
1831 if !errors.is_empty() {
1832 return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
1833 }
1834
1835 if !tcx.next_trait_solver_globally() {
1836 for (key, ty) in infcx.take_opaque_types() {
1839 let hidden_type = infcx.resolve_vars_if_possible(ty);
1840 let key = infcx.resolve_vars_if_possible(key);
1841 sanity_check_found_hidden_type(tcx, key, hidden_type)?;
1842 }
1843 }
1844
1845 Ok(())
1846}