Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4818,6 +4818,7 @@ impl<'hir> Node<'hir> {
ForeignItemKind::Static(ty, ..) => Some(ty),
_ => None,
},
Node::Field(f) => Some(f.ty),
_ => None,
}
}
Expand Down
19 changes: 13 additions & 6 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
Expand Down Expand Up @@ -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
Expand All @@ -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>(
Expand Down Expand Up @@ -784,6 +786,9 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
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);
Expand Down Expand Up @@ -872,12 +877,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
if let Some((_, ctor_def_id)) = adt.ctor {
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);
Expand Down
57 changes: 17 additions & 40 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -290,9 +289,6 @@ 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),
// 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:?}"),
}
Expand Down Expand Up @@ -990,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();

Expand All @@ -1025,18 +1021,13 @@ fn check_type_defn<'tcx>(
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we check def_kind is DefKind::AnonConst | DefKind::InlineConst before fetching HIR here?

}
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
Expand All @@ -1056,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),
);
}

Expand All @@ -1100,7 +1077,7 @@ fn check_type_defn<'tcx>(
}
}

check_where_clauses(wfcx, item.owner_id.def_id);
check_where_clauses(wfcx, item);
Ok(())
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,6 @@ help: consider adding an explicit lifetime bound
LL | struct Far<T: 'static
| +++++++++

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[E0310]: the parameter type `K` may not live long enough
--> $DIR/static-lifetime-tip-with-default-type.rs:22:27
|
Expand All @@ -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.
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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
|
Expand All @@ -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
|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,6 @@ error[E0226]: only a single explicit lifetime bound is permitted
LL | z: Box<dyn Is<'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[E0478]: lifetime bound not satisfied
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8
|
Expand All @@ -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.
Expand Down
22 changes: 11 additions & 11 deletions tests/ui/traits/issue-105231.stderr
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
error: type parameter `T` is only used recursively
--> $DIR/issue-105231.rs:1:15
|
LL | struct A<T>(B<T>);
| - ^
| |
| 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
|
Expand All @@ -26,6 +15,17 @@ LL |
LL ~ struct B<T>(Box<A<A<T>>>);
|

error: type parameter `T` is only used recursively
--> $DIR/issue-105231.rs:1:15
|
LL | struct A<T>(B<T>);
| - ^
| |
| 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
|
Expand Down
Loading