1 use crate::check
::wfcheck
::for_item
;
3 use super::coercion
::CoerceMany
;
4 use super::compare_method
::check_type_bounds
;
5 use super::compare_method
::{compare_const_impl, compare_impl_method, compare_ty_impl}
;
8 use rustc_attr
as attr
;
9 use rustc_errors
::{Applicability, ErrorGuaranteed, MultiSpan}
;
11 use rustc_hir
::def
::{DefKind, Res}
;
12 use rustc_hir
::def_id
::{DefId, LocalDefId}
;
13 use rustc_hir
::intravisit
::Visitor
;
14 use rustc_hir
::lang_items
::LangItem
;
15 use rustc_hir
::{ItemKind, Node, PathSegment}
;
16 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
17 use rustc_infer
::infer
::{RegionVariableOrigin, TyCtxtInferExt}
;
18 use rustc_infer
::traits
::Obligation
;
19 use rustc_middle
::hir
::nested_filter
;
20 use rustc_middle
::ty
::layout
::{LayoutError, MAX_SIMD_LANES}
;
21 use rustc_middle
::ty
::subst
::GenericArgKind
;
22 use rustc_middle
::ty
::util
::{Discr, IntTypeExt}
;
23 use rustc_middle
::ty
::{self, ParamEnv, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable}
;
24 use rustc_session
::lint
::builtin
::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS}
;
25 use rustc_span
::symbol
::sym
;
26 use rustc_span
::{self, Span}
;
27 use rustc_target
::spec
::abi
::Abi
;
28 use rustc_trait_selection
::traits
;
29 use rustc_trait_selection
::traits
::error_reporting
::InferCtxtExt
as _
;
30 use rustc_ty_utils
::representability
::{self, Representability}
;
33 use std
::ops
::ControlFlow
;
35 pub fn check_wf_new(tcx
: TyCtxt
<'_
>) {
36 let visit
= wfcheck
::CheckTypeWellFormedVisitor
::new(tcx
);
37 tcx
.hir().par_visit_all_item_likes(&visit
);
40 pub(super) fn check_abi(tcx
: TyCtxt
<'_
>, hir_id
: hir
::HirId
, span
: Span
, abi
: Abi
) {
41 match tcx
.sess
.target
.is_abi_supported(abi
) {
48 "`{abi}` is not a supported ABI for the current target",
53 tcx
.struct_span_lint_hir(UNSUPPORTED_CALLING_CONVENTIONS
, hir_id
, span
, |lint
| {
54 lint
.build("use of calling convention not supported on this target").emit();
59 // This ABI is only allowed on function pointers
60 if abi
== Abi
::CCmseNonSecureCall
{
65 "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers"
71 /// Helper used for fns and closures. Does the grungy work of checking a function
72 /// body and returns the function context used for that purpose, since in the case of a fn item
73 /// there is still a bit more to do.
76 /// * inherited: other fields inherited from the enclosing fn (if any)
77 #[instrument(skip(inherited, body), level = "debug")]
78 pub(super) fn check_fn
<'a
, 'tcx
>(
79 inherited
: &'a Inherited
<'a
, 'tcx
>,
80 param_env
: ty
::ParamEnv
<'tcx
>,
81 fn_sig
: ty
::FnSig
<'tcx
>,
82 decl
: &'tcx hir
::FnDecl
<'tcx
>,
84 body
: &'tcx hir
::Body
<'tcx
>,
85 can_be_generator
: Option
<hir
::Movability
>,
86 return_type_pre_known
: bool
,
87 ) -> (FnCtxt
<'a
, 'tcx
>, Option
<GeneratorTypes
<'tcx
>>) {
88 // Create the function context. This is either derived from scratch or,
89 // in the case of closures, based on the outer context.
90 let mut fcx
= FnCtxt
::new(inherited
, param_env
, body
.value
.hir_id
);
91 fcx
.ps
.set(UnsafetyState
::function(fn_sig
.unsafety
, fn_id
));
92 fcx
.return_type_pre_known
= return_type_pre_known
;
97 let declared_ret_ty
= fn_sig
.output();
100 fcx
.register_infer_ok_obligations(fcx
.infcx
.replace_opaque_types_with_inference_vars(
104 traits
::ObligationCauseCode
::OpaqueReturnType(None
),
107 // If we replaced declared_ret_ty with infer vars, then we must be infering
108 // an opaque type, so set a flag so we can improve diagnostics.
109 fcx
.return_type_has_opaque
= ret_ty
!= declared_ret_ty
;
111 fcx
.ret_coercion
= Some(RefCell
::new(CoerceMany
::new(ret_ty
)));
112 fcx
.ret_type_span
= Some(decl
.output
.span());
114 let span
= body
.value
.span
;
116 fn_maybe_err(tcx
, span
, fn_sig
.abi
);
118 if fn_sig
.abi
== Abi
::RustCall
{
119 let expected_args
= if let ImplicitSelfKind
::None
= decl
.implicit_self { 1 }
else { 2 }
;
122 let item
= match tcx
.hir().get(fn_id
) {
123 Node
::Item(hir
::Item { kind: ItemKind::Fn(header, ..), .. }
) => Some(header
),
124 Node
::ImplItem(hir
::ImplItem
{
125 kind
: hir
::ImplItemKind
::Fn(header
, ..), ..
127 Node
::TraitItem(hir
::TraitItem
{
128 kind
: hir
::TraitItemKind
::Fn(header
, ..),
131 // Closures are RustCall, but they tuple their arguments, so shouldn't be checked
132 Node
::Expr(hir
::Expr { kind: hir::ExprKind::Closure { .. }
, .. }) => None
,
133 node
=> bug
!("Item being checked wasn't a function/closure: {:?}", node
),
136 if let Some(header
) = item
{
137 tcx
.sess
.span_err(header
.span
, "functions with the \"rust-call\" ABI must take a single non-self argument that is a tuple");
141 if fn_sig
.inputs().len() != expected_args
{
144 // FIXME(CraftSpider) Add a check on parameter expansion, so we don't just make the ICE happen later on
145 // This will probably require wide-scale changes to support a TupleKind obligation
146 // We can't resolve this without knowing the type of the param
147 if !matches
!(fn_sig
.inputs()[expected_args
- 1].kind(), ty
::Tuple(_
) | ty
::Param(_
)) {
153 if body
.generator_kind
.is_some() && can_be_generator
.is_some() {
155 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }
);
156 fcx
.require_type_is_sized(yield_ty
, span
, traits
::SizedYieldType
);
158 // Resume type defaults to `()` if the generator has no argument.
159 let resume_ty
= fn_sig
.inputs().get(0).copied().unwrap_or_else(|| tcx
.mk_unit());
161 fcx
.resume_yield_tys
= Some((resume_ty
, yield_ty
));
164 GatherLocalsVisitor
::new(&fcx
).visit_body(body
);
166 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
167 // (as it's created inside the body itself, not passed in from outside).
168 let maybe_va_list
= if fn_sig
.c_variadic
{
169 let span
= body
.params
.last().unwrap().span
;
170 let va_list_did
= tcx
.require_lang_item(LangItem
::VaList
, Some(span
));
171 let region
= fcx
.next_region_var(RegionVariableOrigin
::MiscVariable(span
));
173 Some(tcx
.bound_type_of(va_list_did
).subst(tcx
, &[region
.into()]))
178 // Add formal parameters.
179 let inputs_hir
= hir
.fn_decl_by_hir_id(fn_id
).map(|decl
| &decl
.inputs
);
180 let inputs_fn
= fn_sig
.inputs().iter().copied();
181 for (idx
, (param_ty
, param
)) in inputs_fn
.chain(maybe_va_list
).zip(body
.params
).enumerate() {
182 // Check the pattern.
183 let ty_span
= try { inputs_hir?.get(idx)?.span }
;
184 fcx
.check_pat_top(¶m
.pat
, param_ty
, ty_span
, false);
186 // Check that argument is Sized.
187 // The check for a non-trivial pattern is a hack to avoid duplicate warnings
188 // for simple cases like `fn foo(x: Trait)`,
189 // where we would error once on the parameter as a whole, and once on the binding `x`.
190 if param
.pat
.simple_ident().is_none() && !tcx
.features().unsized_fn_params
{
191 fcx
.require_type_is_sized(param_ty
, param
.pat
.span
, traits
::SizedArgumentType(ty_span
));
194 fcx
.write_ty(param
.hir_id
, param_ty
);
197 inherited
.typeck_results
.borrow_mut().liberated_fn_sigs_mut().insert(fn_id
, fn_sig
);
199 fcx
.in_tail_expr
= true;
200 if let ty
::Dynamic(..) = declared_ret_ty
.kind() {
201 // FIXME: We need to verify that the return type is `Sized` after the return expression has
202 // been evaluated so that we have types available for all the nodes being returned, but that
203 // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
204 // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
205 // while keeping the current ordering we will ignore the tail expression's type because we
206 // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
207 // because we will trigger "unreachable expression" lints unconditionally.
208 // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
209 // case that a newcomer might make, returning a bare trait, and in that case we populate
210 // the tail expression's type so that the suggestion will be correct, but ignore all other
212 fcx
.check_expr(&body
.value
);
213 fcx
.require_type_is_sized(declared_ret_ty
, decl
.output
.span(), traits
::SizedReturnType
);
215 fcx
.require_type_is_sized(declared_ret_ty
, decl
.output
.span(), traits
::SizedReturnType
);
216 fcx
.check_return_expr(&body
.value
, false);
218 fcx
.in_tail_expr
= false;
220 // We insert the deferred_generator_interiors entry after visiting the body.
221 // This ensures that all nested generators appear before the entry of this generator.
222 // resolve_generator_interiors relies on this property.
223 let gen_ty
= if let (Some(_
), Some(gen_kind
)) = (can_be_generator
, body
.generator_kind
) {
225 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span }
);
226 fcx
.deferred_generator_interiors
.borrow_mut().push((body
.id(), interior
, gen_kind
));
228 let (resume_ty
, yield_ty
) = fcx
.resume_yield_tys
.unwrap();
229 Some(GeneratorTypes
{
233 movability
: can_be_generator
.unwrap(),
239 // Finalize the return check by taking the LUB of the return types
240 // we saw and assigning it to the expected return type. This isn't
241 // really expected to fail, since the coercions would have failed
242 // earlier when trying to find a LUB.
243 let coercion
= fcx
.ret_coercion
.take().unwrap().into_inner();
244 let mut actual_return_ty
= coercion
.complete(&fcx
);
245 debug
!("actual_return_ty = {:?}", actual_return_ty
);
246 if let ty
::Dynamic(..) = declared_ret_ty
.kind() {
247 // We have special-cased the case where the function is declared
248 // `-> dyn Foo` and we don't actually relate it to the
249 // `fcx.ret_coercion`, so just substitute a type variable.
251 fcx
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::DynReturnFn, span }
);
252 debug
!("actual_return_ty replaced with {:?}", actual_return_ty
);
255 // HACK(oli-obk, compiler-errors): We should be comparing this against
256 // `declared_ret_ty`, but then anything uninferred would be inferred to
257 // the opaque type itself. That again would cause writeback to assume
258 // we have a recursive call site and do the sadly stabilized fallback to `()`.
259 fcx
.demand_suptype(span
, ret_ty
, actual_return_ty
);
261 // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
262 if let Some(panic_impl_did
) = tcx
.lang_items().panic_impl()
263 && panic_impl_did
== hir
.local_def_id(fn_id
).to_def_id()
265 check_panic_info_fn(tcx
, panic_impl_did
.expect_local(), fn_sig
, decl
, declared_ret_ty
);
268 // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
269 if let Some(alloc_error_handler_did
) = tcx
.lang_items().oom()
270 && alloc_error_handler_did
== hir
.local_def_id(fn_id
).to_def_id()
272 check_alloc_error_fn(tcx
, alloc_error_handler_did
.expect_local(), fn_sig
, decl
, declared_ret_ty
);
278 fn check_panic_info_fn(
281 fn_sig
: ty
::FnSig
<'_
>,
282 decl
: &hir
::FnDecl
<'_
>,
283 declared_ret_ty
: Ty
<'_
>,
285 let Some(panic_info_did
) = tcx
.lang_items().panic_info() else {
286 tcx
.sess
.err("language item required, but not found: `panic_info`");
290 if *declared_ret_ty
.kind() != ty
::Never
{
291 tcx
.sess
.span_err(decl
.output
.span(), "return type should be `!`");
294 let span
= tcx
.def_span(fn_id
);
295 let inputs
= fn_sig
.inputs();
296 if inputs
.len() != 1 {
297 let span
= tcx
.sess
.source_map().guess_head_span(span
);
298 tcx
.sess
.span_err(span
, "function should have one argument");
302 let arg_is_panic_info
= match *inputs
[0].kind() {
303 ty
::Ref(region
, ty
, mutbl
) => match *ty
.kind() {
304 ty
::Adt(ref adt
, _
) => {
305 adt
.did() == panic_info_did
&& mutbl
== hir
::Mutability
::Not
&& !region
.is_static()
312 if !arg_is_panic_info
{
313 tcx
.sess
.span_err(decl
.inputs
[0].span
, "argument should be `&PanicInfo`");
316 let DefKind
::Fn
= tcx
.def_kind(fn_id
) else {
317 let span
= tcx
.def_span(fn_id
);
318 tcx
.sess
.span_err(span
, "should be a function");
322 let generic_counts
= tcx
.generics_of(fn_id
).own_counts();
323 if generic_counts
.types
!= 0 {
324 let span
= tcx
.def_span(fn_id
);
325 tcx
.sess
.span_err(span
, "should have no type parameters");
327 if generic_counts
.consts
!= 0 {
328 let span
= tcx
.def_span(fn_id
);
329 tcx
.sess
.span_err(span
, "should have no const parameters");
333 fn check_alloc_error_fn(
336 fn_sig
: ty
::FnSig
<'_
>,
337 decl
: &hir
::FnDecl
<'_
>,
338 declared_ret_ty
: Ty
<'_
>,
340 let Some(alloc_layout_did
) = tcx
.lang_items().alloc_layout() else {
341 tcx
.sess
.err("language item required, but not found: `alloc_layout`");
345 if *declared_ret_ty
.kind() != ty
::Never
{
346 tcx
.sess
.span_err(decl
.output
.span(), "return type should be `!`");
349 let inputs
= fn_sig
.inputs();
350 if inputs
.len() != 1 {
351 let span
= tcx
.def_span(fn_id
);
352 let span
= tcx
.sess
.source_map().guess_head_span(span
);
353 tcx
.sess
.span_err(span
, "function should have one argument");
357 let arg_is_alloc_layout
= match inputs
[0].kind() {
358 ty
::Adt(ref adt
, _
) => adt
.did() == alloc_layout_did
,
362 if !arg_is_alloc_layout
{
363 tcx
.sess
.span_err(decl
.inputs
[0].span
, "argument should be `Layout`");
366 let DefKind
::Fn
= tcx
.def_kind(fn_id
) else {
367 let span
= tcx
.def_span(fn_id
);
368 tcx
.sess
.span_err(span
, "`#[alloc_error_handler]` should be a function");
372 let generic_counts
= tcx
.generics_of(fn_id
).own_counts();
373 if generic_counts
.types
!= 0 {
374 let span
= tcx
.def_span(fn_id
);
375 tcx
.sess
.span_err(span
, "`#[alloc_error_handler]` function should have no type parameters");
377 if generic_counts
.consts
!= 0 {
378 let span
= tcx
.def_span(fn_id
);
380 .span_err(span
, "`#[alloc_error_handler]` function should have no const parameters");
384 fn check_struct(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
, span
: Span
) {
385 let def
= tcx
.adt_def(def_id
);
386 def
.destructor(tcx
); // force the destructor to be evaluated
387 check_representable(tcx
, span
, def_id
);
389 if def
.repr().simd() {
390 check_simd(tcx
, span
, def_id
);
393 check_transparent(tcx
, span
, def
);
394 check_packed(tcx
, span
, def
);
397 fn check_union(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
, span
: Span
) {
398 let def
= tcx
.adt_def(def_id
);
399 def
.destructor(tcx
); // force the destructor to be evaluated
400 check_representable(tcx
, span
, def_id
);
401 check_transparent(tcx
, span
, def
);
402 check_union_fields(tcx
, span
, def_id
);
403 check_packed(tcx
, span
, def
);
406 /// Check that the fields of the `union` do not need dropping.
407 fn check_union_fields(tcx
: TyCtxt
<'_
>, span
: Span
, item_def_id
: LocalDefId
) -> bool
{
408 let item_type
= tcx
.type_of(item_def_id
);
409 if let ty
::Adt(def
, substs
) = item_type
.kind() {
410 assert
!(def
.is_union());
411 let fields
= &def
.non_enum_variant().fields
;
412 let param_env
= tcx
.param_env(item_def_id
);
413 for field
in fields
{
414 let field_ty
= field
.ty(tcx
, substs
);
415 if field_ty
.needs_drop(tcx
, param_env
) {
416 let (field_span
, ty_span
) = match tcx
.hir().get_if_local(field
.did
) {
417 // We are currently checking the type this field came from, so it must be local.
418 Some(Node
::Field(field
)) => (field
.span
, field
.ty
.span
),
419 _
=> unreachable
!("mir field has to correspond to hir field"),
425 "unions cannot contain fields that may need dropping"
428 "a type is guaranteed not to need dropping \
429 when it implements `Copy`, or when it is the special `ManuallyDrop<_>` type",
431 .multipart_suggestion_verbose(
432 "when the type does not implement `Copy`, \
433 wrap it inside a `ManuallyDrop<_>` and ensure it is manually dropped",
435 (ty_span
.shrink_to_lo(), "std::mem::ManuallyDrop<".into()),
436 (ty_span
.shrink_to_hi(), ">".into()),
438 Applicability
::MaybeIncorrect
,
445 span_bug
!(span
, "unions must be ty::Adt, but got {:?}", item_type
.kind());
450 /// Check that a `static` is inhabited.
451 fn check_static_inhabited
<'tcx
>(tcx
: TyCtxt
<'tcx
>, def_id
: LocalDefId
, span
: Span
) {
452 // Make sure statics are inhabited.
453 // Other parts of the compiler assume that there are no uninhabited places. In principle it
454 // would be enough to check this for `extern` statics, as statics with an initializer will
455 // have UB during initialization if they are uninhabited, but there also seems to be no good
456 // reason to allow any statics to be uninhabited.
457 let ty
= tcx
.type_of(def_id
);
458 let layout
= match tcx
.layout_of(ParamEnv
::reveal_all().and(ty
)) {
460 // Foreign statics that overflow their allowed size should emit an error
461 Err(LayoutError
::SizeOverflow(_
))
463 let node
= tcx
.hir().get_by_def_id(def_id
);
466 hir
::Node
::ForeignItem(hir
::ForeignItem
{
467 kind
: hir
::ForeignItemKind
::Static(..),
474 .struct_span_err(span
, "extern static is too large for the current architecture")
478 // Generic statics are rejected, but we still reach this case.
480 tcx
.sess
.delay_span_bug(span
, &e
.to_string());
484 if layout
.abi
.is_uninhabited() {
485 tcx
.struct_span_lint_hir(
487 tcx
.hir().local_def_id_to_hir_id(def_id
),
490 lint
.build("static of uninhabited type")
491 .note("uninhabited statics cannot be initialized, and any access would be an immediate error")
498 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
499 /// projections that would result in "inheriting lifetimes".
500 pub(super) fn check_opaque
<'tcx
>(
503 substs
: SubstsRef
<'tcx
>,
505 origin
: &hir
::OpaqueTyOrigin
,
507 check_opaque_for_inheriting_lifetimes(tcx
, def_id
, span
);
508 if tcx
.type_of(def_id
).references_error() {
511 if check_opaque_for_cycles(tcx
, def_id
, substs
, span
, origin
).is_err() {
514 check_opaque_meets_bounds(tcx
, def_id
, substs
, span
, origin
);
517 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
518 /// in "inheriting lifetimes".
519 #[instrument(level = "debug", skip(tcx, span))]
520 pub(super) fn check_opaque_for_inheriting_lifetimes
<'tcx
>(
525 let item
= tcx
.hir().expect_item(def_id
);
526 debug
!(?item
, ?span
);
528 struct FoundParentLifetime
;
529 struct FindParentLifetimeVisitor
<'tcx
>(&'tcx ty
::Generics
);
530 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for FindParentLifetimeVisitor
<'tcx
> {
531 type BreakTy
= FoundParentLifetime
;
533 fn visit_region(&mut self, r
: ty
::Region
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
534 debug
!("FindParentLifetimeVisitor: r={:?}", r
);
535 if let ty
::ReEarlyBound(ty
::EarlyBoundRegion { index, .. }
) = *r
{
536 if index
< self.0.parent_count
as u32 {
537 return ControlFlow
::Break(FoundParentLifetime
);
539 return ControlFlow
::CONTINUE
;
543 r
.super_visit_with(self)
546 fn visit_const(&mut self, c
: ty
::Const
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
547 if let ty
::ConstKind
::Unevaluated(..) = c
.kind() {
548 // FIXME(#72219) We currently don't detect lifetimes within substs
549 // which would violate this check. Even though the particular substitution is not used
550 // within the const, this should still be fixed.
551 return ControlFlow
::CONTINUE
;
553 c
.super_visit_with(self)
557 struct ProhibitOpaqueVisitor
<'tcx
> {
559 opaque_identity_ty
: Ty
<'tcx
>,
560 generics
: &'tcx ty
::Generics
,
561 selftys
: Vec
<(Span
, Option
<String
>)>,
564 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for ProhibitOpaqueVisitor
<'tcx
> {
565 type BreakTy
= Ty
<'tcx
>;
567 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
568 debug
!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t
);
569 if t
== self.opaque_identity_ty
{
570 ControlFlow
::CONTINUE
572 t
.super_visit_with(&mut FindParentLifetimeVisitor(self.generics
))
573 .map_break(|FoundParentLifetime
| t
)
578 impl<'tcx
> Visitor
<'tcx
> for ProhibitOpaqueVisitor
<'tcx
> {
579 type NestedFilter
= nested_filter
::OnlyBodies
;
581 fn nested_visit_map(&mut self) -> Self::Map
{
585 fn visit_ty(&mut self, arg
: &'tcx hir
::Ty
<'tcx
>) {
587 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, path
)) => match &path
.segments
{
590 res
: Some(Res
::SelfTy { trait_: _, alias_to: impl_ref }
),
595 impl_ref
.map(|(def_id
, _
)| self.tcx
.def_path_str(def_id
));
596 self.selftys
.push((path
.span
, impl_ty_name
));
602 hir
::intravisit
::walk_ty(self, arg
);
606 if let ItemKind
::OpaqueTy(hir
::OpaqueTy
{
607 origin
: hir
::OpaqueTyOrigin
::AsyncFn(..) | hir
::OpaqueTyOrigin
::FnReturn(..),
611 let mut visitor
= ProhibitOpaqueVisitor
{
612 opaque_identity_ty
: tcx
.mk_opaque(
614 InternalSubsts
::identity_for_item(tcx
, def_id
.to_def_id()),
616 generics
: tcx
.generics_of(def_id
),
620 let prohibit_opaque
= tcx
621 .explicit_item_bounds(def_id
)
623 .try_for_each(|(predicate
, _
)| predicate
.visit_with(&mut visitor
));
625 "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor.opaque_identity_ty={:?}, visitor.generics={:?}",
626 prohibit_opaque
, visitor
.opaque_identity_ty
, visitor
.generics
629 if let Some(ty
) = prohibit_opaque
.break_value() {
630 visitor
.visit_item(&item
);
631 let is_async
= match item
.kind
{
632 ItemKind
::OpaqueTy(hir
::OpaqueTy { origin, .. }
) => {
633 matches
!(origin
, hir
::OpaqueTyOrigin
::AsyncFn(..))
638 let mut err
= struct_span_err
!(
642 "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
644 if is_async { "async fn" }
else { "impl Trait" }
,
647 for (span
, name
) in visitor
.selftys
{
650 "consider spelling out the type instead",
651 name
.unwrap_or_else(|| format
!("{:?}", ty
)),
652 Applicability
::MaybeIncorrect
,
660 /// Checks that an opaque type does not contain cycles.
661 pub(super) fn check_opaque_for_cycles
<'tcx
>(
664 substs
: SubstsRef
<'tcx
>,
666 origin
: &hir
::OpaqueTyOrigin
,
667 ) -> Result
<(), ErrorGuaranteed
> {
668 if tcx
.try_expand_impl_trait_type(def_id
.to_def_id(), substs
).is_err() {
669 let reported
= match origin
{
670 hir
::OpaqueTyOrigin
::AsyncFn(..) => async_opaque_type_cycle_error(tcx
, span
),
671 _
=> opaque_type_cycle_error(tcx
, def_id
, span
),
679 /// Check that the concrete type behind `impl Trait` actually implements `Trait`.
681 /// This is mostly checked at the places that specify the opaque type, but we
682 /// check those cases in the `param_env` of that function, which may have
683 /// bounds not on this opaque type:
685 /// type X<T> = impl Clone
686 /// fn f<T: Clone>(t: T) -> X<T> {
690 /// Without this check the above code is incorrectly accepted: we would ICE if
691 /// some tried, for example, to clone an `Option<X<&mut ()>>`.
692 #[instrument(level = "debug", skip(tcx))]
693 fn check_opaque_meets_bounds
<'tcx
>(
696 substs
: SubstsRef
<'tcx
>,
698 origin
: &hir
::OpaqueTyOrigin
,
700 let hidden_type
= tcx
.bound_type_of(def_id
.to_def_id()).subst(tcx
, substs
);
702 let hir_id
= tcx
.hir().local_def_id_to_hir_id(def_id
);
703 let defining_use_anchor
= match *origin
{
704 hir
::OpaqueTyOrigin
::FnReturn(did
) | hir
::OpaqueTyOrigin
::AsyncFn(did
) => did
,
705 hir
::OpaqueTyOrigin
::TyAlias
=> def_id
,
707 let param_env
= tcx
.param_env(defining_use_anchor
);
709 tcx
.infer_ctxt().with_opaque_type_inference(defining_use_anchor
).enter(move |infcx
| {
710 let inh
= Inherited
::new(infcx
, def_id
);
711 let infcx
= &inh
.infcx
;
712 let opaque_ty
= tcx
.mk_opaque(def_id
.to_def_id(), substs
);
714 let misc_cause
= traits
::ObligationCause
::misc(span
, hir_id
);
716 match infcx
.at(&misc_cause
, param_env
).eq(opaque_ty
, hidden_type
) {
717 Ok(infer_ok
) => inh
.register_infer_ok_obligations(infer_ok
),
719 tcx
.sess
.delay_span_bug(
721 &format
!("could not unify `{hidden_type}` with revealed type:\n{ty_err}"),
726 // Additionally require the hidden type to be well-formed with only the generics of the opaque type.
727 // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
728 // hidden type is well formed even without those bounds.
730 ty
::Binder
::dummy(ty
::PredicateKind
::WellFormed(hidden_type
.into())).to_predicate(tcx
);
731 inh
.register_predicate(Obligation
::new(misc_cause
, param_env
, predicate
));
733 // Check that all obligations are satisfied by the implementation's
735 let errors
= inh
.fulfillment_cx
.borrow_mut().select_all_or_error(&infcx
);
736 if !errors
.is_empty() {
737 infcx
.report_fulfillment_errors(&errors
, None
, false);
741 // Checked when type checking the function containing them.
742 hir
::OpaqueTyOrigin
::FnReturn(..) | hir
::OpaqueTyOrigin
::AsyncFn(..) => {}
743 // Can have different predicates to their defining use
744 hir
::OpaqueTyOrigin
::TyAlias
=> {
745 // Finally, resolve all regions. This catches wily misuses of
746 // lifetime parameters.
747 let fcx
= FnCtxt
::new(&inh
, param_env
, hir_id
);
748 fcx
.regionck_item(hir_id
, span
, FxHashSet
::default());
752 // Clean up after ourselves
753 let _
= infcx
.inner
.borrow_mut().opaque_type_storage
.take_opaque_types();
757 pub fn check_item_type
<'tcx
>(tcx
: TyCtxt
<'tcx
>, id
: hir
::ItemId
) {
759 "check_item_type(it.def_id={:?}, it.name={})",
761 tcx
.def_path_str(id
.def_id
.to_def_id())
763 let _indenter
= indenter();
764 match tcx
.def_kind(id
.def_id
) {
765 DefKind
::Static(..) => {
766 tcx
.ensure().typeck(id
.def_id
);
767 maybe_check_static_with_link_section(tcx
, id
.def_id
, tcx
.def_span(id
.def_id
));
768 check_static_inhabited(tcx
, id
.def_id
, tcx
.def_span(id
.def_id
));
771 tcx
.ensure().typeck(id
.def_id
);
774 let item
= tcx
.hir().item(id
);
775 let hir
::ItemKind
::Enum(ref enum_definition
, _
) = item
.kind
else {
778 check_enum(tcx
, item
.span
, &enum_definition
.variants
, item
.def_id
);
780 DefKind
::Fn
=> {}
// entirely within check_item_body
782 let it
= tcx
.hir().item(id
);
783 let hir
::ItemKind
::Impl(ref impl_
) = it
.kind
else {
786 debug
!("ItemKind::Impl {} with id {:?}", it
.ident
, it
.def_id
);
787 if let Some(impl_trait_ref
) = tcx
.impl_trait_ref(it
.def_id
) {
788 check_impl_items_against_trait(
795 check_on_unimplemented(tcx
, it
);
799 let it
= tcx
.hir().item(id
);
800 let hir
::ItemKind
::Trait(_
, _
, _
, _
, ref items
) = it
.kind
else {
803 check_on_unimplemented(tcx
, it
);
805 for item
in items
.iter() {
806 let item
= tcx
.hir().trait_item(item
.id
);
808 hir
::TraitItemKind
::Fn(ref sig
, _
) => {
809 let abi
= sig
.header
.abi
;
810 fn_maybe_err(tcx
, item
.ident
.span
, abi
);
812 hir
::TraitItemKind
::Type(.., Some(default)) => {
813 let assoc_item
= tcx
.associated_item(item
.def_id
);
815 InternalSubsts
::identity_for_item(tcx
, it
.def_id
.to_def_id());
816 let _
: Result
<_
, rustc_errors
::ErrorGuaranteed
> = check_type_bounds(
821 ty
::TraitRef { def_id: it.def_id.to_def_id(), substs: trait_substs }
,
829 check_struct(tcx
, id
.def_id
, tcx
.def_span(id
.def_id
));
832 check_union(tcx
, id
.def_id
, tcx
.def_span(id
.def_id
));
834 DefKind
::OpaqueTy
=> {
835 let item
= tcx
.hir().item(id
);
836 let hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { origin, .. }
) = item
.kind
else {
839 // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
840 // `async-std` (and `pub async fn` in general).
841 // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
842 // See https://github.com/rust-lang/rust/issues/75100
843 if !tcx
.sess
.opts
.actually_rustdoc
{
844 let substs
= InternalSubsts
::identity_for_item(tcx
, item
.def_id
.to_def_id());
845 check_opaque(tcx
, item
.def_id
, substs
, item
.span
, &origin
);
848 DefKind
::TyAlias
=> {
849 let pty_ty
= tcx
.type_of(id
.def_id
);
850 let generics
= tcx
.generics_of(id
.def_id
);
851 check_type_params_are_used(tcx
, &generics
, pty_ty
);
853 DefKind
::ForeignMod
=> {
854 let it
= tcx
.hir().item(id
);
855 let hir
::ItemKind
::ForeignMod { abi, items }
= it
.kind
else {
858 check_abi(tcx
, it
.hir_id(), it
.span
, abi
);
860 if abi
== Abi
::RustIntrinsic
{
862 let item
= tcx
.hir().foreign_item(item
.id
);
863 intrinsic
::check_intrinsic_type(tcx
, item
);
865 } else if abi
== Abi
::PlatformIntrinsic
{
867 let item
= tcx
.hir().foreign_item(item
.id
);
868 intrinsic
::check_platform_intrinsic_type(tcx
, item
);
872 let def_id
= item
.id
.def_id
;
873 let generics
= tcx
.generics_of(def_id
);
874 let own_counts
= generics
.own_counts();
875 if generics
.params
.len() - own_counts
.lifetimes
!= 0 {
876 let (kinds
, kinds_pl
, egs
) = match (own_counts
.types
, own_counts
.consts
) {
877 (_
, 0) => ("type", "types", Some("u32")),
878 // We don't specify an example value, because we can't generate
879 // a valid value for any type.
880 (0, _
) => ("const", "consts", None
),
881 _
=> ("type or const", "types or consts", None
),
887 "foreign items may not have {kinds} parameters",
889 .span_label(item
.span
, &format
!("can't have {kinds} parameters"))
891 // FIXME: once we start storing spans for type arguments, turn this
892 // into a suggestion.
894 "replace the {} parameters with concrete {}{}",
897 egs
.map(|egs
| format
!(" like `{}`", egs
)).unwrap_or_default(),
903 let item
= tcx
.hir().foreign_item(item
.id
);
905 hir
::ForeignItemKind
::Fn(ref fn_decl
, _
, _
) => {
906 require_c_abi_if_c_variadic(tcx
, fn_decl
, abi
, item
.span
);
908 hir
::ForeignItemKind
::Static(..) => {
909 check_static_inhabited(tcx
, def_id
, item
.span
);
916 DefKind
::GlobalAsm
=> {
917 let it
= tcx
.hir().item(id
);
918 let hir
::ItemKind
::GlobalAsm(asm
) = it
.kind
else { span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}
", it) };
919 for_item(tcx, it).with_fcx(|fcx| {
920 fcx.check_asm(asm, it.hir_id());
928 pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
929 // an error would be reported if this fails.
930 let _ = traits::OnUnimplementedDirective::of_item(tcx, item.def_id.to_def_id());
933 pub(super) fn check_specialization_validity<'tcx>(
935 trait_def: &ty::TraitDef,
936 trait_item: &ty::AssocItem,
938 impl_item: &hir::ImplItemRef,
940 let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) else { return };
941 let mut ancestor_impls = ancestors.skip(1).filter_map(|parent| {
942 if parent.is_from_trait() {
945 Some((parent, parent.item(tcx, trait_item.def_id)))
949 let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| {
951 // Parent impl exists, and contains the parent item we're trying to specialize, but
952 // doesn't mark it `default`.
953 Some(parent_item) if traits::impl_item_is_final(tcx, &parent_item) => {
954 Some(Err(parent_impl.def_id()))
957 // Parent impl contains item and makes it specializable.
958 Some(_) => Some(Ok(())),
960 // Parent impl doesn't mention the item. This means it's inherited from the
961 // grandparent. In that case, if parent is a `default impl`, inherited items use the
962 // "defaultness
" from the grandparent, else they are final.
964 if tcx.impl_defaultness(parent_impl.def_id()).is_default() {
967 Some(Err(parent_impl.def_id()))
973 // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the
974 // item. This is allowed, the item isn't actually getting specialized here.
975 let result = opt_result.unwrap_or(Ok(()));
977 if let Err(parent_impl) = result {
978 report_forbidden_specialization(tcx, impl_item, parent_impl);
982 fn check_impl_items_against_trait<'tcx>(
984 full_impl_span: Span,
986 impl_trait_ref: ty::TraitRef<'tcx>,
987 impl_item_refs: &[hir::ImplItemRef],
989 // If the trait reference itself is erroneous (so the compilation is going
990 // to fail), skip checking the items here -- the `impl_item` table in `tcx`
991 // isn't populated for such impls.
992 if impl_trait_ref.references_error() {
996 // Negative impls are not expected to have any items
997 match tcx.impl_polarity(impl_id) {
998 ty::ImplPolarity::Reservation | ty::ImplPolarity::Positive => {}
999 ty::ImplPolarity::Negative => {
1000 if let [first_item_ref, ..] = impl_item_refs {
1001 let first_item_span = tcx.hir().impl_item(first_item_ref.id).span;
1006 "negative impls cannot have any items
"
1014 let trait_def = tcx.trait_def(impl_trait_ref.def_id);
1016 for impl_item in impl_item_refs {
1017 let ty_impl_item = tcx.associated_item(impl_item.id.def_id);
1018 let ty_trait_item = if let Some(trait_item_id) = ty_impl_item.trait_item_def_id {
1019 tcx.associated_item(trait_item_id)
1021 // Checked in `associated_item`.
1022 tcx.sess.delay_span_bug(impl_item.span, "missing associated item
in trait");
1025 let impl_item_full = tcx.hir().impl_item(impl_item.id);
1026 match impl_item_full.kind {
1027 hir::ImplItemKind::Const(..) => {
1028 // Find associated const definition.
1037 hir::ImplItemKind::Fn(..) => {
1038 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
1039 compare_impl_method(
1048 hir::ImplItemKind::TyAlias(impl_ty) => {
1049 let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id);
1061 check_specialization_validity(
1065 impl_id.to_def_id(),
1070 if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) {
1071 // Check for missing items from trait
1072 let mut missing_items = Vec::new();
1074 let mut must_implement_one_of: Option<&[Ident]> =
1075 trait_def.must_implement_one_of.as_deref();
1077 for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) {
1078 let is_implemented = ancestors
1079 .leaf_def(tcx, trait_item_id)
1080 .map_or(false, |node_item| node_item.item.defaultness.has_value());
1082 if !is_implemented && tcx.impl_defaultness(impl_id).is_final() {
1083 missing_items.push(tcx.associated_item(trait_item_id));
1086 if let Some(required_items) = &must_implement_one_of {
1087 // true if this item is specifically implemented in this impl
1088 let is_implemented_here = ancestors
1089 .leaf_def(tcx, trait_item_id)
1090 .map_or(false, |node_item| !node_item.defining_node.is_from_trait());
1092 if is_implemented_here {
1093 let trait_item = tcx.associated_item(trait_item_id);
1094 if required_items.contains(&trait_item.ident(tcx)) {
1095 must_implement_one_of = None;
1101 if !missing_items.is_empty() {
1102 let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
1103 missing_items_err(tcx, impl_span, &missing_items, full_impl_span);
1106 if let Some(missing_items) = must_implement_one_of {
1107 let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span);
1109 .get_attr(impl_trait_ref.def_id, sym::rustc_must_implement_one_of)
1110 .map(|attr| attr.span);
1112 missing_items_must_implement_one_of_err(tcx, impl_span, missing_items, attr_span);
1117 /// Checks whether a type can be represented in memory. In particular, it
1118 /// identifies types that contain themselves without indirection through a
1119 /// pointer, which would mean their size is unbounded.
1120 pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bool {
1121 let rty = tcx.type_of(item_def_id);
1123 // Check that it is possible to represent this type. This call identifies
1124 // (1) types that contain themselves and (2) types that contain a different
1125 // recursive type. It is only necessary to throw an error on those that
1126 // contain themselves. For case 2, there must be an inner type that will be
1127 // caught by case 1.
1128 match representability::ty_is_representable(tcx, rty, sp, None) {
1129 Representability::SelfRecursive(spans) => {
1130 recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
1133 Representability::Representable | Representability::ContainsRecursive => (),
1138 pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) {
1139 let t = tcx.type_of(def_id);
1140 if let ty::Adt(def, substs) = t.kind()
1143 let fields = &def.non_enum_variant().fields;
1144 if fields.is_empty() {
1145 struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty
").emit();
1148 let e = fields[0].ty(tcx, substs);
1149 if !fields.iter().all(|f| f.ty(tcx, substs) == e) {
1150 struct_span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous
")
1151 .span_label(sp, "SIMD elements must have the same
type")
1156 let len = if let ty::Array(_ty, c) = e.kind() {
1157 c.try_eval_usize(tcx, tcx.param_env(def.did()))
1159 Some(fields.len() as u64)
1161 if let Some(len) = len {
1163 struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty
").emit();
1165 } else if len > MAX_SIMD_LANES {
1170 "SIMD vector cannot have more than {MAX_SIMD_LANES} elements
",
1177 // Check that we use types valid for use in the lanes of a SIMD "vector register
"
1178 // These are scalar types which directly match a "machine
" type
1179 // Yes: Integers, floats, "thin
" pointers
1180 // No: char, "fat
" pointers, compound types
1182 ty::Param(_) => (), // pass struct<T>(T, T, T, T) through, let monomorphization catch errors
1183 ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_) => (), // struct(u8, u8, u8, u8) is ok
1184 ty::Array(t, _) if matches!(t.kind(), ty::Param(_)) => (), // pass struct<T>([T; N]) through, let monomorphization catch errors
1188 ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_)
1190 { /* struct([f32; 4]) is ok */ }
1196 "SIMD vector element
type should be a
\
1197 primitive
scalar (integer
/float
/pointer
) type"
1206 pub(super) fn check_packed(tcx: TyCtxt<'_>, sp: Span, def: ty::AdtDef<'_>) {
1207 let repr = def.repr();
1209 for attr in tcx.get_attrs(def.did(), sym::repr) {
1210 for r in attr::parse_repr_attr(&tcx.sess, attr) {
1211 if let attr::ReprPacked(pack) = r
1212 && let Some(repr_pack) = repr.pack
1213 && pack as u64 != repr_pack.bytes()
1219 "type has conflicting packed representation hints
"
1225 if repr.align.is_some() {
1230 "type has conflicting packed and align representation hints
"
1234 if let Some(def_spans) = check_packed_inner(tcx, def.did(), &mut vec![]) {
1235 let mut err = struct_span_err!(
1239 "packed
type cannot transitively contain a `
#[repr(align)]` type"
1243 tcx.def_span(def_spans[0].0),
1245 "`{}` has a `#[repr(align)]` attribute",
1246 tcx.item_name(def_spans[0].0)
1250 if def_spans.len() > 2 {
1251 let mut first = true;
1252 for (adt_def, span) in def_spans.iter().skip(1).rev() {
1253 let ident = tcx.item_name(*adt_def);
1258 "`{}` contains a field of type `{}`",
1259 tcx.type_of(def.did()),
1263 format!("...which contains a field of type `{ident}`")
1276 pub(super) fn check_packed_inner(
1279 stack: &mut Vec<DefId>,
1280 ) -> Option<Vec<(DefId, Span)>> {
1281 if let ty::Adt(def, substs) = tcx.type_of(def_id).kind() {
1282 if def.is_struct() || def.is_union() {
1283 if def.repr().align.is_some() {
1284 return Some(vec![(def.did(), DUMMY_SP)]);
1288 for field in &def.non_enum_variant().fields {
1289 if let ty::Adt(def, _) = field.ty(tcx, substs).kind()
1290 && !stack.contains(&def.did())
1291 && let Some(mut defs) = check_packed_inner(tcx, def.did(), stack)
1293 defs.push((def.did(), field.ident(tcx).span));
1304 pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, sp: Span, adt: ty::AdtDef<'tcx>) {
1305 if !adt.repr().transparent() {
1308 let sp = tcx.sess.source_map().guess_head_span(sp);
1310 if adt.is_union() && !tcx.features().transparent_unions {
1312 &tcx.sess.parse_sess,
1313 sym::transparent_unions,
1315 "transparent unions are unstable",
1320 if adt.variants().len() != 1 {
1321 bad_variant_count(tcx, adt, sp, adt.did());
1322 if adt.variants().is_empty() {
1323 // Don't bother checking the fields. No variants (and thus no fields) exist.
1328 // For each field, figure out if it's known to be a ZST and align(1)
1329 let field_infos = adt.all_fields().map(|field| {
1330 let ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, field.did));
1331 let param_env = tcx.param_env(field.did);
1332 let layout = tcx.layout_of(param_env.and(ty));
1333 // We are currently checking the type this field came from, so it must be local
1334 let span = tcx.hir().span_if_local(field.did).unwrap();
1335 let zst = layout.map_or(false, |layout| layout.is_zst());
1336 let align1 = layout.map_or(false, |layout| layout.align.abi.bytes() == 1);
1340 let non_zst_fields =
1341 field_infos.clone().filter_map(|(span, zst, _align1)| if !zst { Some(span) } else { None });
1342 let non_zst_count = non_zst_fields.clone().count();
1343 if non_zst_count >= 2 {
1344 bad_non_zero_sized_fields(tcx, adt, non_zst_count, non_zst_fields, sp);
1346 for (span, zst, align1) in field_infos {
1352 "zero-sized field in transparent {} has alignment larger than 1",
1355 .span_label(span, "has alignment larger than 1")
1361 #[allow(trivial_numeric_casts)]
1362 fn check_enum<'tcx>(
1365 vs: &'tcx [hir::Variant<'tcx>],
1368 let def = tcx.adt_def(def_id);
1369 def.destructor(tcx); // force the destructor to be evaluated
1372 if let Some(attr) = tcx.get_attr(def_id.to_def_id(), sym::repr) {
1377 "unsupported representation for zero-variant enum"
1379 .span_label(sp, "zero-variant enum")
1384 let repr_type_ty = def.repr().discr_type().to_ty(tcx);
1385 if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 {
1386 if !tcx.features().repr128 {
1388 &tcx.sess.parse_sess,
1391 "repr with 128-bit type is unstable",
1398 if let Some(ref e) = v.disr_expr {
1399 tcx.ensure().typeck(tcx.hir().local_def_id(e.hir_id));
1403 if tcx.adt_def(def_id).repr().int.is_none() && tcx.features().arbitrary_enum_discriminant {
1404 let is_unit = |var: &hir::Variant<'_>| matches!(var.data, hir::VariantData::Unit(..));
1406 let has_disr = |var: &hir::Variant<'_>| var.disr_expr.is_some();
1407 let has_non_units = vs.iter().any(|var| !is_unit(var));
1408 let disr_units = vs.iter().any(|var| is_unit(&var) && has_disr(&var));
1409 let disr_non_unit = vs.iter().any(|var| !is_unit(&var) && has_disr(&var));
1411 if disr_non_unit || (disr_units && has_non_units) {
1413 struct_span_err!(tcx.sess, sp, E0732, "`#[repr(inttype)]` must be specified");
1418 let mut disr_vals: Vec<Discr<'tcx>> = Vec::with_capacity(vs.len());
1419 // This tracks the previous variant span (in the loop) incase we need it for diagnostics
1420 let mut prev_variant_span: Span = DUMMY_SP;
1421 for ((_, discr), v) in iter::zip(def.discriminants(tcx), vs) {
1422 // Check for duplicate discriminant values
1423 if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) {
1424 let variant_did = def.variant(VariantIdx::new(i)).def_id;
1425 let variant_i_hir_id = tcx.hir().local_def_id_to_hir_id(variant_did.expect_local());
1426 let variant_i = tcx.hir().expect_variant(variant_i_hir_id);
1427 let i_span = match variant_i.disr_expr {
1428 Some(ref expr) => tcx.hir().span(expr.hir_id),
1429 None => tcx.def_span(variant_did),
1431 let span = match v.disr_expr {
1432 Some(ref expr) => tcx.hir().span(expr.hir_id),
1435 let display_discr = format_discriminant_overflow(tcx, v, discr);
1436 let display_discr_i = format_discriminant_overflow(tcx, variant_i, disr_vals[i]);
1437 let no_disr = v.disr_expr.is_none();
1438 let mut err = struct_span_err!(
1442 "discriminant value `{}` assigned more than once",
1446 err.span_label(i_span, format!("first assignment of {display_discr_i}"));
1447 err.span_label(span, format!("second assignment of {display_discr}"));
1453 "assigned discriminant for `{}` was incremented from this discriminant",
1461 disr_vals.push(discr);
1462 prev_variant_span = v.span;
1465 check_representable(tcx, sp, def_id);
1466 check_transparent(tcx, sp, def);
1469 /// In the case that a discriminant is both a duplicate and an overflowing literal,
1470 /// we insert both the assigned discriminant and the literal it overflowed from into the formatted
1471 /// output. Otherwise we format the discriminant normally.
1472 fn format_discriminant_overflow<'tcx>(
1474 variant: &hir::Variant<'_>,
1477 if let Some(expr) = &variant.disr_expr {
1478 let body = &tcx.hir().body(expr.body).value;
1479 if let hir::ExprKind::Lit(lit) = &body.kind
1480 && let rustc_ast::LitKind::Int(lit_value, _int_kind) = &lit.node
1481 && dis.val != *lit_value
1483 return format!("`{dis}` (overflowed from `{lit_value}`)");
1490 pub(super) fn check_type_params_are_used<'tcx>(
1492 generics: &ty::Generics,
1495 debug!("check_type_params_are_used(generics={:?}, ty={:?})", generics, ty);
1497 assert_eq!(generics.parent, None);
1499 if generics.own_counts().types == 0 {
1503 let mut params_used = BitSet::new_empty(generics.params.len());
1505 if ty.references_error() {
1506 // If there is already another error, do not emit
1507 // an error for not using a type parameter.
1508 assert!(tcx.sess.has_errors().is_some());
1512 for leaf in ty.walk() {
1513 if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
1514 && let ty::Param(param) = leaf_ty.kind()
1516 debug!("found use of ty param {:?}", param);
1517 params_used.insert(param.index);
1521 for param in &generics.params {
1522 if !params_used.contains(param.index)
1523 && let ty::GenericParamDefKind::Type { .. } = param.kind
1525 let span = tcx.def_span(param.def_id);
1530 "type parameter `{}` is unused",
1533 .span_label(span, "unused type parameter")
1539 pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
1540 let module = tcx.hir_module_items(module_def_id);
1541 for id in module.items() {
1542 check_item_type(tcx, id);
1546 pub(super) use wfcheck::check_item_well_formed;
1548 pub(super) use wfcheck::check_trait_item as check_trait_item_well_formed;
1550 pub(super) use wfcheck::check_impl_item as check_impl_item_well_formed;
1552 fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
1553 struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
1554 .span_label(span, "recursive `async fn`")
1555 .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
1557 "consider using the `async_recursion` crate: https://crates.io/crates/async_recursion",
1562 /// Emit an error for recursive opaque types.
1564 /// If this is a return `impl Trait`, find the item's return expressions and point at them. For
1565 /// direct recursion this is enough, but for indirect recursion also point at the last intermediary
1568 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
1569 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1570 fn opaque_type_cycle_error(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
, span
: Span
) -> ErrorGuaranteed
{
1571 let mut err
= struct_span_err
!(tcx
.sess
, span
, E0720
, "cannot resolve opaque type");
1573 let mut label
= false;
1574 if let Some((def_id
, visitor
)) = get_owner_return_paths(tcx
, def_id
) {
1575 let typeck_results
= tcx
.typeck(def_id
);
1579 .filter_map(|expr
| typeck_results
.node_type_opt(expr
.hir_id
))
1580 .all(|ty
| matches
!(ty
.kind(), ty
::Never
))
1585 .filter(|expr
| typeck_results
.node_type_opt(expr
.hir_id
).is_some())
1586 .map(|expr
| expr
.span
)
1587 .collect
::<Vec
<Span
>>();
1588 let span_len
= spans
.len();
1590 err
.span_label(spans
[0], "this returned value is of `!` type");
1592 let mut multispan
: MultiSpan
= spans
.clone().into();
1595 .push_span_label(span
, "this returned value is of `!` type".to_string());
1597 err
.span_note(multispan
, "these returned values have a concrete \"never\" type");
1599 err
.help("this error will resolve once the item's body returns a concrete type");
1601 let mut seen
= FxHashSet
::default();
1603 err
.span_label(span
, "recursive opaque type");
1605 for (sp
, ty
) in visitor
1608 .filter_map(|e
| typeck_results
.node_type_opt(e
.hir_id
).map(|t
| (e
.span
, t
)))
1609 .filter(|(_
, ty
)| !matches
!(ty
.kind(), ty
::Never
))
1611 struct OpaqueTypeCollector(Vec
<DefId
>);
1612 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for OpaqueTypeCollector
{
1613 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> ControlFlow
<Self::BreakTy
> {
1615 ty
::Opaque(def
, _
) => {
1617 ControlFlow
::CONTINUE
1619 _
=> t
.super_visit_with(self),
1623 let mut visitor
= OpaqueTypeCollector(vec
![]);
1624 ty
.visit_with(&mut visitor
);
1625 for def_id
in visitor
.0 {
1626 let ty_span
= tcx
.def_span(def_id
);
1627 if !seen
.contains(&ty_span
) {
1628 err
.span_label(ty_span
, &format
!("returning this opaque type `{ty}`"));
1629 seen
.insert(ty_span
);
1631 err
.span_label(sp
, &format
!("returning here with type `{ty}`"));
1637 err
.span_label(span
, "cannot resolve opaque type");