diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 0f6f81d7964c4..8773f03525913 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4818,6 +4818,7 @@ impl<'hir> Node<'hir> { ForeignItemKind::Static(ty, ..) => Some(ty), _ => None, }, + Node::Field(f) => Some(f.ty), _ => None, } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f4bbf03f0c26e..42bf232329230 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -37,8 +37,8 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir}; use super::compare_impl_item::check_type_bounds; use super::*; use crate::check::wfcheck::{ - check_associated_item, check_trait_item, check_variances_for_type_defn, check_where_clauses, - enter_wf_checking_ctxt, + check_associated_item, check_trait_item, check_type_defn, check_variances_for_type_defn, + check_where_clauses, enter_wf_checking_ctxt, }; fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_, T>) { @@ -89,7 +89,7 @@ pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>, } } -fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { +fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); def.destructor(tcx); // force the destructor to be evaluated @@ -100,15 +100,17 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) { check_transparent(tcx, def); check_packed(tcx, span, def); + check_type_defn(tcx, def_id, false) } -fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) { +fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { let def = tcx.adt_def(def_id); let span = tcx.def_span(def_id); def.destructor(tcx); // force the destructor to be evaluated check_transparent(tcx, def); check_union_fields(tcx, span, def_id); check_packed(tcx, span, def); + check_type_defn(tcx, def_id, true) } fn allowed_union_or_unsafe_field<'tcx>( @@ -781,9 +783,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id()); + crate::collect::check_enum_variant_types(tcx, def_id.to_def_id()); check_enum(tcx, def_id); check_variances_for_type_defn(tcx, def_id); + res = res.and(check_type_defn(tcx, def_id, true)); + // enums are fully handled by the type based check and have no hir wfcheck logic + return res; } DefKind::Fn => { tcx.ensure_ok().generics_of(def_id); @@ -843,12 +848,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), _ => {} } } + res = res.and(wfcheck::check_trait(tcx, def_id)); + wfcheck::check_gat_where_clauses(tcx, def_id); + // Trait aliases do not have hir checks anymore + return res; } DefKind::TraitAlias => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().explicit_implied_predicates_of(def_id); tcx.ensure_ok().explicit_super_predicates_of(def_id); tcx.ensure_ok().predicates_of(def_id); + res = res.and(wfcheck::check_trait(tcx, def_id)); + // Trait aliases do not have hir checks anymore + return res; } def_kind @ (DefKind::Struct | DefKind::Union) => { tcx.ensure_ok().generics_of(def_id); @@ -863,14 +875,16 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), } if let Some((_, ctor_def_id)) = adt.ctor { - crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local()); + crate::collect::check_ctor(tcx, ctor_def_id.expect_local()); } - match def_kind { + res = res.and(match def_kind { DefKind::Struct => check_struct(tcx, def_id), DefKind::Union => check_union(tcx, def_id), _ => unreachable!(), - } + }); check_variances_for_type_defn(tcx, def_id); + // structs and enums are fully handled by the type based check and have no hir wfcheck logic + return res; } DefKind::OpaqueTy => { check_opaque_precise_captures(tcx, def_id); @@ -921,6 +935,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), })); check_variances_for_type_defn(tcx, def_id); } + // Doesn't have any hir based checks + return res; } DefKind::ForeignMod => { let it = tcx.hir_expect_item(def_id); @@ -983,6 +999,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), _ => (), } } + // Doesn't have any hir based checks + return res; } DefKind::Closure => { // This is guaranteed to be called by metadata encoding, @@ -1058,10 +1076,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), return res; } - // Only `Node::Item` and `Node::ForeignItem` still have HIR based - // checks. Returning early here does not miss any checks and - // avoids this query from having a direct dependency edge on the HIR - DefKind::AnonConst | DefKind::InlineConst => return res, + // These have no wf checks + DefKind::AnonConst + | DefKind::InlineConst + | DefKind::ExternCrate + | DefKind::Macro(..) + | DefKind::Use + | DefKind::GlobalAsm + | DefKind::Mod => return res, _ => {} } let node = tcx.hir_node_by_def_id(def_id); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 428d627ad6f2d..640ada0d32a3f 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -18,9 +18,8 @@ use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::traits::solve::NoSolution; use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::{ - self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, - TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, - Upcast, + self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable, + TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast, }; use rustc_middle::{bug, span_bug}; use rustc_session::parse::feature_err; @@ -290,12 +289,8 @@ pub(super) fn check_item<'tcx>( res } hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl), - hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false), - hir::ItemKind::Union(..) => check_type_defn(tcx, item, true), - hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true), - hir::ItemKind::Trait(..) => check_trait(tcx, item), - hir::ItemKind::TraitAlias(..) => check_trait(tcx, item), - _ => Ok(()), + // Note: do not add new entries to this match. Instead add all new logic in `check_item_type` + _ => span_bug!(item.span, "should have been handled by the type based wf check: {item:?}"), } } @@ -345,7 +340,7 @@ pub(crate) fn check_trait_item<'tcx>( /// fn into_iter<'a>(&'a self) -> Self::Iter<'a>; /// } /// ``` -fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { +pub(crate) fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) { // Associates every GAT's def_id to a list of possibly missing bounds detected by this lint. let mut required_bounds_by_item = FxIndexMap::default(); let associated_items = tcx.associated_items(trait_def_id); @@ -991,15 +986,15 @@ pub(crate) fn check_associated_item( } /// In a type definition, we check that to ensure that the types of the fields are well-formed. -fn check_type_defn<'tcx>( +pub(crate) fn check_type_defn<'tcx>( tcx: TyCtxt<'tcx>, - item: &hir::Item<'tcx>, + item: LocalDefId, all_sized: bool, ) -> Result<(), ErrorGuaranteed> { - let _ = tcx.representability(item.owner_id.def_id); - let adt_def = tcx.adt_def(item.owner_id); + let _ = tcx.representability(item); + let adt_def = tcx.adt_def(item); - enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| { + enter_wf_checking_ctxt(tcx, item, |wfcx| { let variants = adt_def.variants(); let packed = adt_def.repr().packed(); @@ -1026,18 +1021,13 @@ fn check_type_defn<'tcx>( } } let field_id = field.did.expect_local(); - let hir::FieldDef { ty: hir_ty, .. } = - tcx.hir_node_by_def_id(field_id).expect_field(); + let span = tcx.ty_span(field_id); let ty = wfcx.deeply_normalize( - hir_ty.span, + span, None, tcx.type_of(field.did).instantiate_identity(), ); - wfcx.register_wf_obligation( - hir_ty.span, - Some(WellFormedLoc::Ty(field_id)), - ty.into(), - ) + wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(field_id)), ty.into()) } // For DST, or when drop needs to copy things around, all @@ -1057,35 +1047,21 @@ fn check_type_defn<'tcx>( variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate() { let last = idx == variant.fields.len() - 1; - let field_id = field.did.expect_local(); - let hir::FieldDef { ty: hir_ty, .. } = - tcx.hir_node_by_def_id(field_id).expect_field(); - let ty = wfcx.normalize( - hir_ty.span, - None, - tcx.type_of(field.did).instantiate_identity(), - ); + let span = tcx.ty_span(field.did.expect_local()); + let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity()); wfcx.register_bound( traits::ObligationCause::new( - hir_ty.span, + span, wfcx.body_def_id, ObligationCauseCode::FieldSized { - adt_kind: match &item.kind { - ItemKind::Struct(..) => AdtKind::Struct, - ItemKind::Union(..) => AdtKind::Union, - ItemKind::Enum(..) => AdtKind::Enum, - kind => span_bug!( - item.span, - "should be wfchecking an ADT, got {kind:?}" - ), - }, - span: hir_ty.span, + adt_kind: adt_def.adt_kind(), + span, last, }, ), wfcx.param_env, ty, - tcx.require_lang_item(LangItem::Sized, hir_ty.span), + tcx.require_lang_item(LangItem::Sized, span), ); } @@ -1101,16 +1077,13 @@ fn check_type_defn<'tcx>( } } - check_where_clauses(wfcx, item.owner_id.def_id); + check_where_clauses(wfcx, item); Ok(()) }) } -#[instrument(skip(tcx, item))] -fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> { - debug!(?item.owner_id); - - let def_id = item.owner_id.def_id; +#[instrument(skip(tcx))] +pub(crate) fn check_trait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> { if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) { // `PointeeSized` is removed during lowering. return Ok(()); @@ -1136,10 +1109,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant Ok(()) }); - // Only check traits, don't check trait aliases - if let hir::ItemKind::Trait(..) = item.kind { - check_gat_where_clauses(tcx, item.owner_id.def_id); - } res } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index a185291887dc7..3160b12c1ab9d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -600,13 +600,13 @@ fn get_new_lifetime_name<'tcx>( (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap() } -pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) { +pub(super) fn check_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); } -pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { +pub(super) fn check_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { let def = tcx.adt_def(def_id); let repr_type = def.repr().discr_type(); let initial = repr_type.initial_discriminant(tcx); @@ -641,7 +641,7 @@ pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) { // Lower the ctor, if any. This also registers the variant as an item. if let Some(ctor_def_id) = variant.ctor_def_id() { - lower_variant_ctor(tcx, ctor_def_id.expect_local()); + check_ctor(tcx, ctor_def_id.expect_local()); } } } diff --git a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr index 786aa00350c28..7d985a9013f19 100644 --- a/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr +++ b/tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr @@ -82,14 +82,6 @@ help: consider adding an explicit lifetime bound LL | struct Far $DIR/static-lifetime-tip-with-default-type.rs:22:10 - | -LL | struct S<'a, K: 'a = i32>(&'static K); - | ^^ unused lifetime parameter - | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` - error[E0310]: the parameter type `K` may not live long enough --> $DIR/static-lifetime-tip-with-default-type.rs:22:27 | @@ -104,6 +96,14 @@ help: consider adding an explicit lifetime bound LL | struct S<'a, K: 'a + 'static = i32>(&'static K); | +++++++++ +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/static-lifetime-tip-with-default-type.rs:22:10 + | +LL | struct S<'a, K: 'a = i32>(&'static K); + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + error: aborting due to 8 previous errors Some errors have detailed explanations: E0310, E0392. diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr index 4bfbe0eeff774..534ba933ba5d0 100644 --- a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -7,6 +7,12 @@ LL | beta: [(); foo::<&'a ()>()], = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-64173-unused-lifetimes.rs:4:28 + | +LL | array: [(); size_of::<&Self>()], + | ^^^^ + error[E0392]: lifetime parameter `'s` is never used --> $DIR/issue-64173-unused-lifetimes.rs:3:12 | @@ -15,12 +21,6 @@ LL | struct Foo<'s> { | = help: consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData` -error: generic `Self` types are currently not permitted in anonymous constants - --> $DIR/issue-64173-unused-lifetimes.rs:4:28 - | -LL | array: [(); size_of::<&Self>()], - | ^^^^ - error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-64173-unused-lifetimes.rs:15:12 | diff --git a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index e2a5027e710da..b15d2affeea37 100644 --- a/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -4,14 +4,6 @@ error[E0226]: only a single explicit lifetime bound is permitted LL | z: Box+'b+'c>, | ^^ -error[E0392]: lifetime parameter `'c` is never used - --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18 - | -LL | struct Foo<'a,'b,'c> { - | ^^ unused lifetime parameter - | - = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` - error[E0478]: lifetime bound not satisfied --> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8 | @@ -29,6 +21,14 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined here LL | struct Foo<'a,'b,'c> { | ^^ +error[E0392]: lifetime parameter `'c` is never used + --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18 + | +LL | struct Foo<'a,'b,'c> { + | ^^ unused lifetime parameter + | + = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData` + error: aborting due to 3 previous errors Some errors have detailed explanations: E0226, E0392, E0478. diff --git a/tests/ui/traits/issue-105231.stderr b/tests/ui/traits/issue-105231.stderr index b048548018a71..e113f8382b2f4 100644 --- a/tests/ui/traits/issue-105231.stderr +++ b/tests/ui/traits/issue-105231.stderr @@ -1,14 +1,3 @@ -error: type parameter `T` is only used recursively - --> $DIR/issue-105231.rs:1:15 - | -LL | struct A(B); - | - ^ - | | - | type parameter must be used non-recursively in the definition - | - = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` - = note: all type parameters must be used in a non-recursive way in order to constrain their variance - error[E0072]: recursive types `A` and `B` have infinite size --> $DIR/issue-105231.rs:1:1 | @@ -26,6 +15,17 @@ LL | LL ~ struct B(Box>>); | +error: type parameter `T` is only used recursively + --> $DIR/issue-105231.rs:1:15 + | +LL | struct A(B); + | - ^ + | | + | type parameter must be used non-recursively in the definition + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = note: all type parameters must be used in a non-recursive way in order to constrain their variance + error: type parameter `T` is only used recursively --> $DIR/issue-105231.rs:4:17 |