1 use super::coercion
::CoerceMany
;
2 use super::compare_method
::{compare_const_impl, compare_impl_method, compare_ty_impl}
;
5 use rustc_attr
as attr
;
6 use rustc_errors
::Applicability
;
8 use rustc_hir
::def_id
::{DefId, LocalDefId, LOCAL_CRATE}
;
9 use rustc_hir
::lang_items
::LangItem
;
10 use rustc_hir
::{ItemKind, Node}
;
11 use rustc_infer
::infer
::type_variable
::{TypeVariableOrigin, TypeVariableOriginKind}
;
12 use rustc_infer
::infer
::RegionVariableOrigin
;
13 use rustc_middle
::ty
::fold
::TypeFoldable
;
14 use rustc_middle
::ty
::subst
::GenericArgKind
;
15 use rustc_middle
::ty
::util
::{Discr, IntTypeExt, Representability}
;
16 use rustc_middle
::ty
::{self, RegionKind, ToPredicate, Ty, TyCtxt}
;
17 use rustc_session
::config
::EntryFnType
;
18 use rustc_span
::symbol
::sym
;
19 use rustc_span
::{self, MultiSpan, Span}
;
20 use rustc_target
::spec
::abi
::Abi
;
21 use rustc_trait_selection
::traits
::{self, ObligationCauseCode}
;
23 pub fn check_wf_new(tcx
: TyCtxt
<'_
>) {
24 let visit
= wfcheck
::CheckTypeWellFormedVisitor
::new(tcx
);
25 tcx
.hir().krate().par_visit_all_item_likes(&visit
);
28 pub(super) fn check_abi(tcx
: TyCtxt
<'_
>, span
: Span
, abi
: Abi
) {
29 if !tcx
.sess
.target
.target
.is_abi_supported(abi
) {
34 "The ABI `{}` is not supported for the current target",
41 /// Helper used for fns and closures. Does the grungy work of checking a function
42 /// body and returns the function context used for that purpose, since in the case of a fn item
43 /// there is still a bit more to do.
46 /// * inherited: other fields inherited from the enclosing fn (if any)
47 pub(super) fn check_fn
<'a
, 'tcx
>(
48 inherited
: &'a Inherited
<'a
, 'tcx
>,
49 param_env
: ty
::ParamEnv
<'tcx
>,
50 fn_sig
: ty
::FnSig
<'tcx
>,
51 decl
: &'tcx hir
::FnDecl
<'tcx
>,
53 body
: &'tcx hir
::Body
<'tcx
>,
54 can_be_generator
: Option
<hir
::Movability
>,
55 ) -> (FnCtxt
<'a
, 'tcx
>, Option
<GeneratorTypes
<'tcx
>>) {
56 let mut fn_sig
= fn_sig
;
58 debug
!("check_fn(sig={:?}, fn_id={}, param_env={:?})", fn_sig
, fn_id
, param_env
);
60 // Create the function context. This is either derived from scratch or,
61 // in the case of closures, based on the outer context.
62 let mut fcx
= FnCtxt
::new(inherited
, param_env
, body
.value
.hir_id
);
63 *fcx
.ps
.borrow_mut() = UnsafetyState
::function(fn_sig
.unsafety
, fn_id
);
69 let declared_ret_ty
= fn_sig
.output();
72 fcx
.instantiate_opaque_types_from_value(fn_id
, &declared_ret_ty
, decl
.output
.span());
73 debug
!("check_fn: declared_ret_ty: {}, revealed_ret_ty: {}", declared_ret_ty
, revealed_ret_ty
);
74 fcx
.ret_coercion
= Some(RefCell
::new(CoerceMany
::new(revealed_ret_ty
)));
75 fcx
.ret_type_span
= Some(decl
.output
.span());
76 if let ty
::Opaque(..) = declared_ret_ty
.kind() {
77 fcx
.ret_coercion_impl_trait
= Some(declared_ret_ty
);
79 fn_sig
= tcx
.mk_fn_sig(
80 fn_sig
.inputs().iter().cloned(),
87 let span
= body
.value
.span
;
89 fn_maybe_err(tcx
, span
, fn_sig
.abi
);
91 if body
.generator_kind
.is_some() && can_be_generator
.is_some() {
93 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span }
);
94 fcx
.require_type_is_sized(yield_ty
, span
, traits
::SizedYieldType
);
96 // Resume type defaults to `()` if the generator has no argument.
97 let resume_ty
= fn_sig
.inputs().get(0).copied().unwrap_or_else(|| tcx
.mk_unit());
99 fcx
.resume_yield_tys
= Some((resume_ty
, yield_ty
));
102 let outer_def_id
= tcx
.closure_base_def_id(hir
.local_def_id(fn_id
).to_def_id()).expect_local();
103 let outer_hir_id
= hir
.local_def_id_to_hir_id(outer_def_id
);
104 GatherLocalsVisitor
::new(&fcx
, outer_hir_id
).visit_body(body
);
106 // C-variadic fns also have a `VaList` input that's not listed in `fn_sig`
107 // (as it's created inside the body itself, not passed in from outside).
108 let maybe_va_list
= if fn_sig
.c_variadic
{
109 let span
= body
.params
.last().unwrap().span
;
110 let va_list_did
= tcx
.require_lang_item(LangItem
::VaList
, Some(span
));
111 let region
= fcx
.next_region_var(RegionVariableOrigin
::MiscVariable(span
));
113 Some(tcx
.type_of(va_list_did
).subst(tcx
, &[region
.into()]))
118 // Add formal parameters.
119 let inputs_hir
= hir
.fn_decl_by_hir_id(fn_id
).map(|decl
| &decl
.inputs
);
120 let inputs_fn
= fn_sig
.inputs().iter().copied();
121 for (idx
, (param_ty
, param
)) in inputs_fn
.chain(maybe_va_list
).zip(body
.params
).enumerate() {
122 // Check the pattern.
123 let ty_span
= try { inputs_hir?.get(idx)?.span }
;
124 fcx
.check_pat_top(¶m
.pat
, param_ty
, ty_span
, false);
126 // Check that argument is Sized.
127 // The check for a non-trivial pattern is a hack to avoid duplicate warnings
128 // for simple cases like `fn foo(x: Trait)`,
129 // where we would error once on the parameter as a whole, and once on the binding `x`.
130 if param
.pat
.simple_ident().is_none() && !tcx
.features().unsized_locals
{
131 fcx
.require_type_is_sized(param_ty
, param
.pat
.span
, traits
::SizedArgumentType(ty_span
));
134 fcx
.write_ty(param
.hir_id
, param_ty
);
137 inherited
.typeck_results
.borrow_mut().liberated_fn_sigs_mut().insert(fn_id
, fn_sig
);
139 fcx
.in_tail_expr
= true;
140 if let ty
::Dynamic(..) = declared_ret_ty
.kind() {
141 // FIXME: We need to verify that the return type is `Sized` after the return expression has
142 // been evaluated so that we have types available for all the nodes being returned, but that
143 // requires the coerced evaluated type to be stored. Moving `check_return_expr` before this
144 // causes unsized errors caused by the `declared_ret_ty` to point at the return expression,
145 // while keeping the current ordering we will ignore the tail expression's type because we
146 // don't know it yet. We can't do `check_expr_kind` while keeping `check_return_expr`
147 // because we will trigger "unreachable expression" lints unconditionally.
148 // Because of all of this, we perform a crude check to know whether the simplest `!Sized`
149 // case that a newcomer might make, returning a bare trait, and in that case we populate
150 // the tail expression's type so that the suggestion will be correct, but ignore all other
152 fcx
.check_expr(&body
.value
);
153 fcx
.require_type_is_sized(declared_ret_ty
, decl
.output
.span(), traits
::SizedReturnType
);
154 tcx
.sess
.delay_span_bug(decl
.output
.span(), "`!Sized` return type");
156 fcx
.require_type_is_sized(declared_ret_ty
, decl
.output
.span(), traits
::SizedReturnType
);
157 fcx
.check_return_expr(&body
.value
);
159 fcx
.in_tail_expr
= false;
161 // We insert the deferred_generator_interiors entry after visiting the body.
162 // This ensures that all nested generators appear before the entry of this generator.
163 // resolve_generator_interiors relies on this property.
164 let gen_ty
= if let (Some(_
), Some(gen_kind
)) = (can_be_generator
, body
.generator_kind
) {
166 .next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::MiscVariable, span }
);
167 fcx
.deferred_generator_interiors
.borrow_mut().push((body
.id(), interior
, gen_kind
));
169 let (resume_ty
, yield_ty
) = fcx
.resume_yield_tys
.unwrap();
170 Some(GeneratorTypes
{
174 movability
: can_be_generator
.unwrap(),
180 // Finalize the return check by taking the LUB of the return types
181 // we saw and assigning it to the expected return type. This isn't
182 // really expected to fail, since the coercions would have failed
183 // earlier when trying to find a LUB.
185 // However, the behavior around `!` is sort of complex. In the
186 // event that the `actual_return_ty` comes back as `!`, that
187 // indicates that the fn either does not return or "returns" only
188 // values of type `!`. In this case, if there is an expected
189 // return type that is *not* `!`, that should be ok. But if the
190 // return type is being inferred, we want to "fallback" to `!`:
192 // let x = move || panic!();
194 // To allow for that, I am creating a type variable with diverging
195 // fallback. This was deemed ever so slightly better than unifying
196 // the return value with `!` because it allows for the caller to
197 // make more assumptions about the return type (e.g., they could do
199 // let y: Option<u32> = Some(x());
201 // which would then cause this return type to become `u32`, not
203 let coercion
= fcx
.ret_coercion
.take().unwrap().into_inner();
204 let mut actual_return_ty
= coercion
.complete(&fcx
);
205 if actual_return_ty
.is_never() {
206 actual_return_ty
= fcx
.next_diverging_ty_var(TypeVariableOrigin
{
207 kind
: TypeVariableOriginKind
::DivergingFn
,
211 fcx
.demand_suptype(span
, revealed_ret_ty
, actual_return_ty
);
213 // Check that the main return type implements the termination trait.
214 if let Some(term_id
) = tcx
.lang_items().termination() {
215 if let Some((def_id
, EntryFnType
::Main
)) = tcx
.entry_fn(LOCAL_CRATE
) {
216 let main_id
= hir
.local_def_id_to_hir_id(def_id
);
217 if main_id
== fn_id
{
218 let substs
= tcx
.mk_substs_trait(declared_ret_ty
, &[]);
219 let trait_ref
= ty
::TraitRef
::new(term_id
, substs
);
220 let return_ty_span
= decl
.output
.span();
221 let cause
= traits
::ObligationCause
::new(
224 ObligationCauseCode
::MainFunctionType
,
227 inherited
.register_predicate(traits
::Obligation
::new(
230 trait_ref
.without_const().to_predicate(tcx
),
236 // Check that a function marked as `#[panic_handler]` has signature `fn(&PanicInfo) -> !`
237 if let Some(panic_impl_did
) = tcx
.lang_items().panic_impl() {
238 if panic_impl_did
== hir
.local_def_id(fn_id
).to_def_id() {
239 if let Some(panic_info_did
) = tcx
.lang_items().panic_info() {
240 if *declared_ret_ty
.kind() != ty
::Never
{
241 sess
.span_err(decl
.output
.span(), "return type should be `!`");
244 let inputs
= fn_sig
.inputs();
245 let span
= hir
.span(fn_id
);
246 if inputs
.len() == 1 {
247 let arg_is_panic_info
= match *inputs
[0].kind() {
248 ty
::Ref(region
, ty
, mutbl
) => match *ty
.kind() {
249 ty
::Adt(ref adt
, _
) => {
250 adt
.did
== panic_info_did
251 && mutbl
== hir
::Mutability
::Not
252 && *region
!= RegionKind
::ReStatic
259 if !arg_is_panic_info
{
260 sess
.span_err(decl
.inputs
[0].span
, "argument should be `&PanicInfo`");
263 if let Node
::Item(item
) = hir
.get(fn_id
) {
264 if let ItemKind
::Fn(_
, ref generics
, _
) = item
.kind
{
265 if !generics
.params
.is_empty() {
266 sess
.span_err(span
, "should have no type parameters");
271 let span
= sess
.source_map().guess_head_span(span
);
272 sess
.span_err(span
, "function should have one argument");
275 sess
.err("language item required, but not found: `panic_info`");
280 // Check that a function marked as `#[alloc_error_handler]` has signature `fn(Layout) -> !`
281 if let Some(alloc_error_handler_did
) = tcx
.lang_items().oom() {
282 if alloc_error_handler_did
== hir
.local_def_id(fn_id
).to_def_id() {
283 if let Some(alloc_layout_did
) = tcx
.lang_items().alloc_layout() {
284 if *declared_ret_ty
.kind() != ty
::Never
{
285 sess
.span_err(decl
.output
.span(), "return type should be `!`");
288 let inputs
= fn_sig
.inputs();
289 let span
= hir
.span(fn_id
);
290 if inputs
.len() == 1 {
291 let arg_is_alloc_layout
= match inputs
[0].kind() {
292 ty
::Adt(ref adt
, _
) => adt
.did
== alloc_layout_did
,
296 if !arg_is_alloc_layout
{
297 sess
.span_err(decl
.inputs
[0].span
, "argument should be `Layout`");
300 if let Node
::Item(item
) = hir
.get(fn_id
) {
301 if let ItemKind
::Fn(_
, ref generics
, _
) = item
.kind
{
302 if !generics
.params
.is_empty() {
305 "`#[alloc_error_handler]` function should have no type \
312 let span
= sess
.source_map().guess_head_span(span
);
313 sess
.span_err(span
, "function should have one argument");
316 sess
.err("language item required, but not found: `alloc_layout`");
324 pub(super) fn check_struct(tcx
: TyCtxt
<'_
>, id
: hir
::HirId
, span
: Span
) {
325 let def_id
= tcx
.hir().local_def_id(id
);
326 let def
= tcx
.adt_def(def_id
);
327 def
.destructor(tcx
); // force the destructor to be evaluated
328 check_representable(tcx
, span
, def_id
);
331 check_simd(tcx
, span
, def_id
);
334 check_transparent(tcx
, span
, def
);
335 check_packed(tcx
, span
, def
);
338 pub(super) fn check_union(tcx
: TyCtxt
<'_
>, id
: hir
::HirId
, span
: Span
) {
339 let def_id
= tcx
.hir().local_def_id(id
);
340 let def
= tcx
.adt_def(def_id
);
341 def
.destructor(tcx
); // force the destructor to be evaluated
342 check_representable(tcx
, span
, def_id
);
343 check_transparent(tcx
, span
, def
);
344 check_union_fields(tcx
, span
, def_id
);
345 check_packed(tcx
, span
, def
);
348 /// When the `#![feature(untagged_unions)]` gate is active,
349 /// check that the fields of the `union` does not contain fields that need dropping.
350 pub(super) fn check_union_fields(tcx
: TyCtxt
<'_
>, span
: Span
, item_def_id
: LocalDefId
) -> bool
{
351 let item_type
= tcx
.type_of(item_def_id
);
352 if let ty
::Adt(def
, substs
) = item_type
.kind() {
353 assert
!(def
.is_union());
354 let fields
= &def
.non_enum_variant().fields
;
355 let param_env
= tcx
.param_env(item_def_id
);
356 for field
in fields
{
357 let field_ty
= field
.ty(tcx
, substs
);
358 // We are currently checking the type this field came from, so it must be local.
359 let field_span
= tcx
.hir().span_if_local(field
.did
).unwrap();
360 if field_ty
.needs_drop(tcx
, param_env
) {
365 "unions may not contain fields that need dropping"
367 .span_note(field_span
, "`std::mem::ManuallyDrop` can be used to wrap the type")
373 span_bug
!(span
, "unions must be ty::Adt, but got {:?}", item_type
.kind());
378 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
379 /// projections that would result in "inheriting lifetimes".
380 pub(super) fn check_opaque
<'tcx
>(
383 substs
: SubstsRef
<'tcx
>,
385 origin
: &hir
::OpaqueTyOrigin
,
387 check_opaque_for_inheriting_lifetimes(tcx
, def_id
, span
);
388 tcx
.ensure().type_of(def_id
);
389 check_opaque_for_cycles(tcx
, def_id
, substs
, span
, origin
);
392 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
393 /// in "inheriting lifetimes".
394 pub(super) fn check_opaque_for_inheriting_lifetimes(
399 let item
= tcx
.hir().expect_item(tcx
.hir().local_def_id_to_hir_id(def_id
));
401 "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
406 struct ProhibitOpaqueVisitor
<'tcx
> {
407 opaque_identity_ty
: Ty
<'tcx
>,
408 generics
: &'tcx ty
::Generics
,
409 ty
: Option
<Ty
<'tcx
>>,
412 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for ProhibitOpaqueVisitor
<'tcx
> {
413 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> bool
{
414 debug
!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t
);
415 if t
!= self.opaque_identity_ty
&& t
.super_visit_with(self) {
422 fn visit_region(&mut self, r
: ty
::Region
<'tcx
>) -> bool
{
423 debug
!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r
);
424 if let RegionKind
::ReEarlyBound(ty
::EarlyBoundRegion { index, .. }
) = r
{
425 return *index
< self.generics
.parent_count
as u32;
428 r
.super_visit_with(self)
431 fn visit_const(&mut self, c
: &'tcx ty
::Const
<'tcx
>) -> bool
{
432 if let ty
::ConstKind
::Unevaluated(..) = c
.val
{
433 // FIXME(#72219) We currenctly don't detect lifetimes within substs
434 // which would violate this check. Even though the particular substitution is not used
435 // within the const, this should still be fixed.
438 c
.super_visit_with(self)
442 if let ItemKind
::OpaqueTy(hir
::OpaqueTy
{
443 origin
: hir
::OpaqueTyOrigin
::AsyncFn
| hir
::OpaqueTyOrigin
::FnReturn
,
447 let mut visitor
= ProhibitOpaqueVisitor
{
448 opaque_identity_ty
: tcx
.mk_opaque(
450 InternalSubsts
::identity_for_item(tcx
, def_id
.to_def_id()),
452 generics
: tcx
.generics_of(def_id
),
455 let prohibit_opaque
= tcx
456 .predicates_of(def_id
)
459 .any(|(predicate
, _
)| predicate
.visit_with(&mut visitor
));
461 "check_opaque_for_inheriting_lifetimes: prohibit_opaque={:?}, visitor={:?}",
462 prohibit_opaque
, visitor
466 let is_async
= match item
.kind
{
467 ItemKind
::OpaqueTy(hir
::OpaqueTy { origin, .. }
) => match origin
{
468 hir
::OpaqueTyOrigin
::AsyncFn
=> true,
474 let mut err
= struct_span_err
!(
478 "`{}` return type cannot contain a projection or `Self` that references lifetimes from \
480 if is_async { "async fn" }
else { "impl Trait" }
,
483 if let Ok(snippet
) = tcx
.sess
.source_map().span_to_snippet(span
) {
484 if snippet
== "Self" {
485 if let Some(ty
) = visitor
.ty
{
488 "consider spelling out the type instead",
490 Applicability
::MaybeIncorrect
,
500 /// Checks that an opaque type does not contain cycles.
501 pub(super) fn check_opaque_for_cycles
<'tcx
>(
504 substs
: SubstsRef
<'tcx
>,
506 origin
: &hir
::OpaqueTyOrigin
,
508 if let Err(partially_expanded_type
) = tcx
.try_expand_impl_trait_type(def_id
.to_def_id(), substs
)
511 hir
::OpaqueTyOrigin
::AsyncFn
=> async_opaque_type_cycle_error(tcx
, span
),
512 hir
::OpaqueTyOrigin
::Binding
=> {
513 binding_opaque_type_cycle_error(tcx
, def_id
, span
, partially_expanded_type
)
515 _
=> opaque_type_cycle_error(tcx
, def_id
, span
),
520 pub fn check_item_type
<'tcx
>(tcx
: TyCtxt
<'tcx
>, it
: &'tcx hir
::Item
<'tcx
>) {
522 "check_item_type(it.hir_id={}, it.name={})",
524 tcx
.def_path_str(tcx
.hir().local_def_id(it
.hir_id
).to_def_id())
526 let _indenter
= indenter();
528 // Consts can play a role in type-checking, so they are included here.
529 hir
::ItemKind
::Static(..) => {
530 let def_id
= tcx
.hir().local_def_id(it
.hir_id
);
531 tcx
.ensure().typeck(def_id
);
532 maybe_check_static_with_link_section(tcx
, def_id
, it
.span
);
534 hir
::ItemKind
::Const(..) => {
535 tcx
.ensure().typeck(tcx
.hir().local_def_id(it
.hir_id
));
537 hir
::ItemKind
::Enum(ref enum_definition
, _
) => {
538 check_enum(tcx
, it
.span
, &enum_definition
.variants
, it
.hir_id
);
540 hir
::ItemKind
::Fn(..) => {}
// entirely within check_item_body
541 hir
::ItemKind
::Impl { ref items, .. }
=> {
542 debug
!("ItemKind::Impl {} with id {}", it
.ident
, it
.hir_id
);
543 let impl_def_id
= tcx
.hir().local_def_id(it
.hir_id
);
544 if let Some(impl_trait_ref
) = tcx
.impl_trait_ref(impl_def_id
) {
545 check_impl_items_against_trait(tcx
, it
.span
, impl_def_id
, impl_trait_ref
, items
);
546 let trait_def_id
= impl_trait_ref
.def_id
;
547 check_on_unimplemented(tcx
, trait_def_id
, it
);
550 hir
::ItemKind
::Trait(_
, _
, _
, _
, ref items
) => {
551 let def_id
= tcx
.hir().local_def_id(it
.hir_id
);
552 check_on_unimplemented(tcx
, def_id
.to_def_id(), it
);
554 for item
in items
.iter() {
555 let item
= tcx
.hir().trait_item(item
.id
);
556 if let hir
::TraitItemKind
::Fn(sig
, _
) = &item
.kind
{
557 let abi
= sig
.header
.abi
;
558 fn_maybe_err(tcx
, item
.ident
.span
, abi
);
562 hir
::ItemKind
::Struct(..) => {
563 check_struct(tcx
, it
.hir_id
, it
.span
);
565 hir
::ItemKind
::Union(..) => {
566 check_union(tcx
, it
.hir_id
, it
.span
);
568 hir
::ItemKind
::OpaqueTy(hir
::OpaqueTy { origin, .. }
) => {
569 // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
570 // `async-std` (and `pub async fn` in general).
571 // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
572 // See https://github.com/rust-lang/rust/issues/75100
573 if !tcx
.sess
.opts
.actually_rustdoc
{
574 let def_id
= tcx
.hir().local_def_id(it
.hir_id
);
576 let substs
= InternalSubsts
::identity_for_item(tcx
, def_id
.to_def_id());
577 check_opaque(tcx
, def_id
, substs
, it
.span
, &origin
);
580 hir
::ItemKind
::TyAlias(..) => {
581 let def_id
= tcx
.hir().local_def_id(it
.hir_id
);
582 let pty_ty
= tcx
.type_of(def_id
);
583 let generics
= tcx
.generics_of(def_id
);
584 check_type_params_are_used(tcx
, &generics
, pty_ty
);
586 hir
::ItemKind
::ForeignMod(ref m
) => {
587 check_abi(tcx
, it
.span
, m
.abi
);
589 if m
.abi
== Abi
::RustIntrinsic
{
590 for item
in m
.items
{
591 intrinsic
::check_intrinsic_type(tcx
, item
);
593 } else if m
.abi
== Abi
::PlatformIntrinsic
{
594 for item
in m
.items
{
595 intrinsic
::check_platform_intrinsic_type(tcx
, item
);
598 for item
in m
.items
{
599 let generics
= tcx
.generics_of(tcx
.hir().local_def_id(item
.hir_id
));
600 let own_counts
= generics
.own_counts();
601 if generics
.params
.len() - own_counts
.lifetimes
!= 0 {
602 let (kinds
, kinds_pl
, egs
) = match (own_counts
.types
, own_counts
.consts
) {
603 (_
, 0) => ("type", "types", Some("u32")),
604 // We don't specify an example value, because we can't generate
605 // a valid value for any type.
606 (0, _
) => ("const", "consts", None
),
607 _
=> ("type or const", "types or consts", None
),
613 "foreign items may not have {} parameters",
616 .span_label(item
.span
, &format
!("can't have {} parameters", kinds
))
618 // FIXME: once we start storing spans for type arguments, turn this
619 // into a suggestion.
621 "replace the {} parameters with concrete {}{}",
624 egs
.map(|egs
| format
!(" like `{}`", egs
)).unwrap_or_default(),
630 if let hir
::ForeignItemKind
::Fn(ref fn_decl
, _
, _
) = item
.kind
{
631 require_c_abi_if_c_variadic(tcx
, fn_decl
, m
.abi
, item
.span
);
636 _
=> { /* nothing to do */ }
640 pub(super) fn check_on_unimplemented(tcx
: TyCtxt
<'_
>, trait_def_id
: DefId
, item
: &hir
::Item
<'_
>) {
641 let item_def_id
= tcx
.hir().local_def_id(item
.hir_id
);
642 // an error would be reported if this fails.
643 let _
= traits
::OnUnimplementedDirective
::of_item(tcx
, trait_def_id
, item_def_id
.to_def_id());
646 pub(super) fn check_specialization_validity
<'tcx
>(
648 trait_def
: &ty
::TraitDef
,
649 trait_item
: &ty
::AssocItem
,
651 impl_item
: &hir
::ImplItem
<'_
>,
653 let kind
= match impl_item
.kind
{
654 hir
::ImplItemKind
::Const(..) => ty
::AssocKind
::Const
,
655 hir
::ImplItemKind
::Fn(..) => ty
::AssocKind
::Fn
,
656 hir
::ImplItemKind
::TyAlias(_
) => ty
::AssocKind
::Type
,
659 let ancestors
= match trait_def
.ancestors(tcx
, impl_id
) {
660 Ok(ancestors
) => ancestors
,
663 let mut ancestor_impls
= ancestors
665 .filter_map(|parent
| {
666 if parent
.is_from_trait() {
669 Some((parent
, parent
.item(tcx
, trait_item
.ident
, kind
, trait_def
.def_id
)))
674 if ancestor_impls
.peek().is_none() {
675 // No parent, nothing to specialize.
679 let opt_result
= ancestor_impls
.find_map(|(parent_impl
, parent_item
)| {
681 // Parent impl exists, and contains the parent item we're trying to specialize, but
682 // doesn't mark it `default`.
683 Some(parent_item
) if traits
::impl_item_is_final(tcx
, &parent_item
) => {
684 Some(Err(parent_impl
.def_id()))
687 // Parent impl contains item and makes it specializable.
688 Some(_
) => Some(Ok(())),
690 // Parent impl doesn't mention the item. This means it's inherited from the
691 // grandparent. In that case, if parent is a `default impl`, inherited items use the
692 // "defaultness" from the grandparent, else they are final.
694 if tcx
.impl_defaultness(parent_impl
.def_id()).is_default() {
697 Some(Err(parent_impl
.def_id()))
703 // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the
704 // item. This is allowed, the item isn't actually getting specialized here.
705 let result
= opt_result
.unwrap_or(Ok(()));
707 if let Err(parent_impl
) = result
{
708 report_forbidden_specialization(tcx
, impl_item
, parent_impl
);
712 pub(super) fn check_impl_items_against_trait
<'tcx
>(
714 full_impl_span
: Span
,
716 impl_trait_ref
: ty
::TraitRef
<'tcx
>,
717 impl_item_refs
: &[hir
::ImplItemRef
<'_
>],
719 let impl_span
= tcx
.sess
.source_map().guess_head_span(full_impl_span
);
721 // If the trait reference itself is erroneous (so the compilation is going
722 // to fail), skip checking the items here -- the `impl_item` table in `tcx`
723 // isn't populated for such impls.
724 if impl_trait_ref
.references_error() {
728 // Negative impls are not expected to have any items
729 match tcx
.impl_polarity(impl_id
) {
730 ty
::ImplPolarity
::Reservation
| ty
::ImplPolarity
::Positive
=> {}
731 ty
::ImplPolarity
::Negative
=> {
732 if let [first_item_ref
, ..] = impl_item_refs
{
733 let first_item_span
= tcx
.hir().impl_item(first_item_ref
.id
).span
;
738 "negative impls cannot have any items"
746 // Locate trait definition and items
747 let trait_def
= tcx
.trait_def(impl_trait_ref
.def_id
);
749 let impl_items
= || impl_item_refs
.iter().map(|iiref
| tcx
.hir().impl_item(iiref
.id
));
751 // Check existing impl methods to see if they are both present in trait
752 // and compatible with trait signature
753 for impl_item
in impl_items() {
754 let namespace
= impl_item
.kind
.namespace();
755 let ty_impl_item
= tcx
.associated_item(tcx
.hir().local_def_id(impl_item
.hir_id
));
756 let ty_trait_item
= tcx
757 .associated_items(impl_trait_ref
.def_id
)
758 .find_by_name_and_namespace(tcx
, ty_impl_item
.ident
, namespace
, impl_trait_ref
.def_id
)
760 // Not compatible, but needed for the error message
761 tcx
.associated_items(impl_trait_ref
.def_id
)
762 .filter_by_name(tcx
, ty_impl_item
.ident
, impl_trait_ref
.def_id
)
766 // Check that impl definition matches trait definition
767 if let Some(ty_trait_item
) = ty_trait_item
{
768 match impl_item
.kind
{
769 hir
::ImplItemKind
::Const(..) => {
770 // Find associated const definition.
771 if ty_trait_item
.kind
== ty
::AssocKind
::Const
{
780 let mut err
= struct_span_err
!(
784 "item `{}` is an associated const, \
785 which doesn't match its trait `{}`",
787 impl_trait_ref
.print_only_trait_path()
789 err
.span_label(impl_item
.span
, "does not match trait");
790 // We can only get the spans from local trait definition
791 // Same for E0324 and E0325
792 if let Some(trait_span
) = tcx
.hir().span_if_local(ty_trait_item
.def_id
) {
793 err
.span_label(trait_span
, "item in trait");
798 hir
::ImplItemKind
::Fn(..) => {
799 let opt_trait_span
= tcx
.hir().span_if_local(ty_trait_item
.def_id
);
800 if ty_trait_item
.kind
== ty
::AssocKind
::Fn
{
810 let mut err
= struct_span_err
!(
814 "item `{}` is an associated method, \
815 which doesn't match its trait `{}`",
817 impl_trait_ref
.print_only_trait_path()
819 err
.span_label(impl_item
.span
, "does not match trait");
820 if let Some(trait_span
) = opt_trait_span
{
821 err
.span_label(trait_span
, "item in trait");
826 hir
::ImplItemKind
::TyAlias(_
) => {
827 let opt_trait_span
= tcx
.hir().span_if_local(ty_trait_item
.def_id
);
828 if ty_trait_item
.kind
== ty
::AssocKind
::Type
{
838 let mut err
= struct_span_err
!(
842 "item `{}` is an associated type, \
843 which doesn't match its trait `{}`",
845 impl_trait_ref
.print_only_trait_path()
847 err
.span_label(impl_item
.span
, "does not match trait");
848 if let Some(trait_span
) = opt_trait_span
{
849 err
.span_label(trait_span
, "item in trait");
856 check_specialization_validity(
866 // Check for missing items from trait
867 let mut missing_items
= Vec
::new();
868 if let Ok(ancestors
) = trait_def
.ancestors(tcx
, impl_id
.to_def_id()) {
869 for trait_item
in tcx
.associated_items(impl_trait_ref
.def_id
).in_definition_order() {
870 let is_implemented
= ancestors
871 .leaf_def(tcx
, trait_item
.ident
, trait_item
.kind
)
872 .map(|node_item
| !node_item
.defining_node
.is_from_trait())
875 if !is_implemented
&& tcx
.impl_defaultness(impl_id
).is_final() {
876 if !trait_item
.defaultness
.has_value() {
877 missing_items
.push(*trait_item
);
883 if !missing_items
.is_empty() {
884 missing_items_err(tcx
, impl_span
, &missing_items
, full_impl_span
);
888 /// Checks whether a type can be represented in memory. In particular, it
889 /// identifies types that contain themselves without indirection through a
890 /// pointer, which would mean their size is unbounded.
891 pub(super) fn check_representable(tcx
: TyCtxt
<'_
>, sp
: Span
, item_def_id
: LocalDefId
) -> bool
{
892 let rty
= tcx
.type_of(item_def_id
);
894 // Check that it is possible to represent this type. This call identifies
895 // (1) types that contain themselves and (2) types that contain a different
896 // recursive type. It is only necessary to throw an error on those that
897 // contain themselves. For case 2, there must be an inner type that will be
899 match rty
.is_representable(tcx
, sp
) {
900 Representability
::SelfRecursive(spans
) => {
901 recursive_type_with_infinite_size_error(tcx
, item_def_id
.to_def_id(), spans
);
904 Representability
::Representable
| Representability
::ContainsRecursive
=> (),
909 pub fn check_simd(tcx
: TyCtxt
<'_
>, sp
: Span
, def_id
: LocalDefId
) {
910 let t
= tcx
.type_of(def_id
);
911 if let ty
::Adt(def
, substs
) = t
.kind() {
913 let fields
= &def
.non_enum_variant().fields
;
914 if fields
.is_empty() {
915 struct_span_err
!(tcx
.sess
, sp
, E0075
, "SIMD vector cannot be empty").emit();
918 let e
= fields
[0].ty(tcx
, substs
);
919 if !fields
.iter().all(|f
| f
.ty(tcx
, substs
) == e
) {
920 struct_span_err
!(tcx
.sess
, sp
, E0076
, "SIMD vector should be homogeneous")
921 .span_label(sp
, "SIMD elements must have the same type")
926 ty
::Param(_
) => { /* struct<T>(T, T, T, T) is ok */ }
927 _
if e
.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ }
933 "SIMD vector element type should be machine type"
943 pub(super) fn check_packed(tcx
: TyCtxt
<'_
>, sp
: Span
, def
: &ty
::AdtDef
) {
946 for attr
in tcx
.get_attrs(def
.did
).iter() {
947 for r
in attr
::find_repr_attrs(&tcx
.sess
, attr
) {
948 if let attr
::ReprPacked(pack
) = r
{
949 if let Some(repr_pack
) = repr
.pack
{
950 if pack
as u64 != repr_pack
.bytes() {
955 "type has conflicting packed representation hints"
963 if repr
.align
.is_some() {
968 "type has conflicting packed and align representation hints"
972 if let Some(def_spans
) = check_packed_inner(tcx
, def
.did
, &mut vec
![]) {
973 let mut err
= struct_span_err
!(
977 "packed type cannot transitively contain a `#[repr(align)]` type"
981 tcx
.def_span(def_spans
[0].0),
983 "`{}` has a `#[repr(align)]` attribute",
984 tcx
.item_name(def_spans
[0].0)
988 if def_spans
.len() > 2 {
989 let mut first
= true;
990 for (adt_def
, span
) in def_spans
.iter().skip(1).rev() {
991 let ident
= tcx
.item_name(*adt_def
);
996 "`{}` contains a field of type `{}`",
997 tcx
.type_of(def
.did
),
1001 format
!("...which contains a field of type `{}`", ident
)
1014 pub(super) fn check_packed_inner(
1017 stack
: &mut Vec
<DefId
>,
1018 ) -> Option
<Vec
<(DefId
, Span
)>> {
1019 if let ty
::Adt(def
, substs
) = tcx
.type_of(def_id
).kind() {
1020 if def
.is_struct() || def
.is_union() {
1021 if def
.repr
.align
.is_some() {
1022 return Some(vec
![(def
.did
, DUMMY_SP
)]);
1026 for field
in &def
.non_enum_variant().fields
{
1027 if let ty
::Adt(def
, _
) = field
.ty(tcx
, substs
).kind() {
1028 if !stack
.contains(&def
.did
) {
1029 if let Some(mut defs
) = check_packed_inner(tcx
, def
.did
, stack
) {
1030 defs
.push((def
.did
, field
.ident
.span
));
1043 pub(super) fn check_transparent
<'tcx
>(tcx
: TyCtxt
<'tcx
>, sp
: Span
, adt
: &'tcx ty
::AdtDef
) {
1044 if !adt
.repr
.transparent() {
1047 let sp
= tcx
.sess
.source_map().guess_head_span(sp
);
1049 if adt
.is_union() && !tcx
.features().transparent_unions
{
1051 &tcx
.sess
.parse_sess
,
1052 sym
::transparent_unions
,
1054 "transparent unions are unstable",
1059 if adt
.variants
.len() != 1 {
1060 bad_variant_count(tcx
, adt
, sp
, adt
.did
);
1061 if adt
.variants
.is_empty() {
1062 // Don't bother checking the fields. No variants (and thus no fields) exist.
1067 // For each field, figure out if it's known to be a ZST and align(1)
1068 let field_infos
= adt
.all_fields().map(|field
| {
1069 let ty
= field
.ty(tcx
, InternalSubsts
::identity_for_item(tcx
, field
.did
));
1070 let param_env
= tcx
.param_env(field
.did
);
1071 let layout
= tcx
.layout_of(param_env
.and(ty
));
1072 // We are currently checking the type this field came from, so it must be local
1073 let span
= tcx
.hir().span_if_local(field
.did
).unwrap();
1074 let zst
= layout
.map(|layout
| layout
.is_zst()).unwrap_or(false);
1075 let align1
= layout
.map(|layout
| layout
.align
.abi
.bytes() == 1).unwrap_or(false);
1079 let non_zst_fields
=
1080 field_infos
.clone().filter_map(|(span
, zst
, _align1
)| if !zst { Some(span) }
else { None }
);
1081 let non_zst_count
= non_zst_fields
.clone().count();
1082 if non_zst_count
!= 1 {
1083 bad_non_zero_sized_fields(tcx
, adt
, non_zst_count
, non_zst_fields
, sp
);
1085 for (span
, zst
, align1
) in field_infos
{
1091 "zero-sized field in transparent {} has alignment larger than 1",
1094 .span_label(span
, "has alignment larger than 1")
1100 #[allow(trivial_numeric_casts)]
1101 pub fn check_enum
<'tcx
>(
1104 vs
: &'tcx
[hir
::Variant
<'tcx
>],
1107 let def_id
= tcx
.hir().local_def_id(id
);
1108 let def
= tcx
.adt_def(def_id
);
1109 def
.destructor(tcx
); // force the destructor to be evaluated
1112 let attributes
= tcx
.get_attrs(def_id
.to_def_id());
1113 if let Some(attr
) = tcx
.sess
.find_by_name(&attributes
, sym
::repr
) {
1118 "unsupported representation for zero-variant enum"
1120 .span_label(sp
, "zero-variant enum")
1125 let repr_type_ty
= def
.repr
.discr_type().to_ty(tcx
);
1126 if repr_type_ty
== tcx
.types
.i128
|| repr_type_ty
== tcx
.types
.u128
{
1127 if !tcx
.features().repr128
{
1129 &tcx
.sess
.parse_sess
,
1132 "repr with 128-bit type is unstable",
1139 if let Some(ref e
) = v
.disr_expr
{
1140 tcx
.ensure().typeck(tcx
.hir().local_def_id(e
.hir_id
));
1144 if tcx
.adt_def(def_id
).repr
.int
.is_none() && tcx
.features().arbitrary_enum_discriminant
{
1145 let is_unit
= |var
: &hir
::Variant
<'_
>| match var
.data
{
1146 hir
::VariantData
::Unit(..) => true,
1150 let has_disr
= |var
: &hir
::Variant
<'_
>| var
.disr_expr
.is_some();
1151 let has_non_units
= vs
.iter().any(|var
| !is_unit(var
));
1152 let disr_units
= vs
.iter().any(|var
| is_unit(&var
) && has_disr(&var
));
1153 let disr_non_unit
= vs
.iter().any(|var
| !is_unit(&var
) && has_disr(&var
));
1155 if disr_non_unit
|| (disr_units
&& has_non_units
) {
1157 struct_span_err
!(tcx
.sess
, sp
, E0732
, "`#[repr(inttype)]` must be specified");
1162 let mut disr_vals
: Vec
<Discr
<'tcx
>> = Vec
::with_capacity(vs
.len());
1163 for ((_
, discr
), v
) in def
.discriminants(tcx
).zip(vs
) {
1164 // Check for duplicate discriminant values
1165 if let Some(i
) = disr_vals
.iter().position(|&x
| x
.val
== discr
.val
) {
1166 let variant_did
= def
.variants
[VariantIdx
::new(i
)].def_id
;
1167 let variant_i_hir_id
= tcx
.hir().local_def_id_to_hir_id(variant_did
.expect_local());
1168 let variant_i
= tcx
.hir().expect_variant(variant_i_hir_id
);
1169 let i_span
= match variant_i
.disr_expr
{
1170 Some(ref expr
) => tcx
.hir().span(expr
.hir_id
),
1171 None
=> tcx
.hir().span(variant_i_hir_id
),
1173 let span
= match v
.disr_expr
{
1174 Some(ref expr
) => tcx
.hir().span(expr
.hir_id
),
1181 "discriminant value `{}` already exists",
1184 .span_label(i_span
, format
!("first use of `{}`", disr_vals
[i
]))
1185 .span_label(span
, format
!("enum already has `{}`", disr_vals
[i
]))
1188 disr_vals
.push(discr
);
1191 check_representable(tcx
, sp
, def_id
);
1192 check_transparent(tcx
, sp
, def
);
1195 pub(super) fn check_type_params_are_used
<'tcx
>(
1197 generics
: &ty
::Generics
,
1200 debug
!("check_type_params_are_used(generics={:?}, ty={:?})", generics
, ty
);
1202 assert_eq
!(generics
.parent
, None
);
1204 if generics
.own_counts().types
== 0 {
1208 let mut params_used
= BitSet
::new_empty(generics
.params
.len());
1210 if ty
.references_error() {
1211 // If there is already another error, do not emit
1212 // an error for not using a type parameter.
1213 assert
!(tcx
.sess
.has_errors());
1217 for leaf
in ty
.walk() {
1218 if let GenericArgKind
::Type(leaf_ty
) = leaf
.unpack() {
1219 if let ty
::Param(param
) = leaf_ty
.kind() {
1220 debug
!("found use of ty param {:?}", param
);
1221 params_used
.insert(param
.index
);
1226 for param
in &generics
.params
{
1227 if !params_used
.contains(param
.index
) {
1228 if let ty
::GenericParamDefKind
::Type { .. }
= param
.kind
{
1229 let span
= tcx
.def_span(param
.def_id
);
1234 "type parameter `{}` is unused",
1237 .span_label(span
, "unused type parameter")
1244 pub(super) fn check_mod_item_types(tcx
: TyCtxt
<'_
>, module_def_id
: LocalDefId
) {
1245 tcx
.hir().visit_item_likes_in_module(module_def_id
, &mut CheckItemTypesVisitor { tcx }
);
1248 pub(super) fn check_item_well_formed(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) {
1249 wfcheck
::check_item_well_formed(tcx
, def_id
);
1252 pub(super) fn check_trait_item_well_formed(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) {
1253 wfcheck
::check_trait_item(tcx
, def_id
);
1256 pub(super) fn check_impl_item_well_formed(tcx
: TyCtxt
<'_
>, def_id
: LocalDefId
) {
1257 wfcheck
::check_impl_item(tcx
, def_id
);
1260 fn async_opaque_type_cycle_error(tcx
: TyCtxt
<'tcx
>, span
: Span
) {
1261 struct_span_err
!(tcx
.sess
, span
, E0733
, "recursion in an `async fn` requires boxing")
1262 .span_label(span
, "recursive `async fn`")
1263 .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
1267 /// Emit an error for recursive opaque types.
1269 /// If this is a return `impl Trait`, find the item's return expressions and point at them. For
1270 /// direct recursion this is enough, but for indirect recursion also point at the last intermediary
1273 /// If all the return expressions evaluate to `!`, then we explain that the error will go away
1274 /// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
1275 fn opaque_type_cycle_error(tcx
: TyCtxt
<'tcx
>, def_id
: LocalDefId
, span
: Span
) {
1276 let mut err
= struct_span_err
!(tcx
.sess
, span
, E0720
, "cannot resolve opaque type");
1278 let mut label
= false;
1279 if let Some((hir_id
, visitor
)) = get_owner_return_paths(tcx
, def_id
) {
1280 let typeck_results
= tcx
.typeck(tcx
.hir().local_def_id(hir_id
));
1284 .filter_map(|expr
| typeck_results
.node_type_opt(expr
.hir_id
))
1285 .all(|ty
| matches
!(ty
.kind(), ty
::Never
))
1290 .filter(|expr
| typeck_results
.node_type_opt(expr
.hir_id
).is_some())
1291 .map(|expr
| expr
.span
)
1292 .collect
::<Vec
<Span
>>();
1293 let span_len
= spans
.len();
1295 err
.span_label(spans
[0], "this returned value is of `!` type");
1297 let mut multispan
: MultiSpan
= spans
.clone().into();
1300 .push_span_label(span
, "this returned value is of `!` type".to_string());
1302 err
.span_note(multispan
, "these returned values have a concrete \"never\" type");
1304 err
.help("this error will resolve once the item's body returns a concrete type");
1306 let mut seen
= FxHashSet
::default();
1308 err
.span_label(span
, "recursive opaque type");
1310 for (sp
, ty
) in visitor
1313 .filter_map(|e
| typeck_results
.node_type_opt(e
.hir_id
).map(|t
| (e
.span
, t
)))
1314 .filter(|(_
, ty
)| !matches
!(ty
.kind(), ty
::Never
))
1316 struct VisitTypes(Vec
<DefId
>);
1317 impl<'tcx
> ty
::fold
::TypeVisitor
<'tcx
> for VisitTypes
{
1318 fn visit_ty(&mut self, t
: Ty
<'tcx
>) -> bool
{
1320 ty
::Opaque(def
, _
) => {
1324 _
=> t
.super_visit_with(self),
1328 let mut visitor
= VisitTypes(vec
![]);
1329 ty
.visit_with(&mut visitor
);
1330 for def_id
in visitor
.0 {
1331 let ty_span
= tcx
.def_span(def_id
);
1332 if !seen
.contains(&ty_span
) {
1333 err
.span_label(ty_span
, &format
!("returning this opaque type `{}`", ty
));
1334 seen
.insert(ty_span
);
1336 err
.span_label(sp
, &format
!("returning here with type `{}`", ty
));
1342 err
.span_label(span
, "cannot resolve opaque type");