Skip to content

Commit 584f2b4

Browse files
committed
Check structs/enums/unions without loading their HIR
1 parent 2ac93ab commit 584f2b4

File tree

6 files changed

+55
-60
lines changed

6 files changed

+55
-60
lines changed

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
3737
use super::compare_impl_item::check_type_bounds;
3838
use super::*;
3939
use crate::check::wfcheck::{
40-
check_associated_item, check_trait_item, check_variances_for_type_defn, check_where_clauses,
41-
enter_wf_checking_ctxt,
40+
check_associated_item, check_trait_item, check_type_defn, check_variances_for_type_defn,
41+
check_where_clauses, enter_wf_checking_ctxt,
4242
};
4343

4444
fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
@@ -89,7 +89,7 @@ pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>,
8989
}
9090
}
9191

92-
fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
92+
fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
9393
let def = tcx.adt_def(def_id);
9494
let span = tcx.def_span(def_id);
9595
def.destructor(tcx); // force the destructor to be evaluated
@@ -100,15 +100,17 @@ fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
100100

101101
check_transparent(tcx, def);
102102
check_packed(tcx, span, def);
103+
check_type_defn(tcx, def_id, false)
103104
}
104105

105-
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) {
106+
fn check_union(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
106107
let def = tcx.adt_def(def_id);
107108
let span = tcx.def_span(def_id);
108109
def.destructor(tcx); // force the destructor to be evaluated
109110
check_transparent(tcx, def);
110111
check_union_fields(tcx, span, def_id);
111112
check_packed(tcx, span, def);
113+
check_type_defn(tcx, def_id, true)
112114
}
113115

114116
fn allowed_union_or_unsafe_field<'tcx>(
@@ -785,6 +787,9 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
785787
crate::collect::check_enum_variant_types(tcx, def_id.to_def_id());
786788
check_enum(tcx, def_id);
787789
check_variances_for_type_defn(tcx, def_id);
790+
res = res.and(check_type_defn(tcx, def_id, true));
791+
// enums are fully handled by the type based check and have no hir wfcheck logic
792+
return res;
788793
}
789794
DefKind::Fn => {
790795
tcx.ensure_ok().generics_of(def_id);
@@ -873,12 +878,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
873878
if let Some((_, ctor_def_id)) = adt.ctor {
874879
crate::collect::check_ctor(tcx, ctor_def_id.expect_local());
875880
}
876-
match def_kind {
881+
res = res.and(match def_kind {
877882
DefKind::Struct => check_struct(tcx, def_id),
878883
DefKind::Union => check_union(tcx, def_id),
879884
_ => unreachable!(),
880-
}
885+
});
881886
check_variances_for_type_defn(tcx, def_id);
887+
// structs and enums are fully handled by the type based check and have no hir wfcheck logic
888+
return res;
882889
}
883890
DefKind::OpaqueTy => {
884891
check_opaque_precise_captures(tcx, def_id);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,8 @@ use rustc_middle::query::Providers;
1919
use rustc_middle::traits::solve::NoSolution;
2020
use rustc_middle::ty::trait_def::TraitSpecializationKind;
2121
use rustc_middle::ty::{
22-
self, AdtKind, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags,
23-
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode,
24-
Upcast,
22+
self, GenericArgKind, GenericArgs, GenericParamDefKind, Ty, TyCtxt, TypeFlags, TypeFoldable,
23+
TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Upcast,
2524
};
2625
use rustc_middle::{bug, span_bug};
2726
use rustc_session::parse::feature_err;
@@ -289,9 +288,6 @@ pub(super) fn check_item<'tcx>(
289288
}
290289
hir::ItemKind::Fn { sig, .. } => check_item_fn(tcx, def_id, sig.decl),
291290
hir::ItemKind::Const(_, _, ty, _) => check_const_item(tcx, def_id, ty.span),
292-
hir::ItemKind::Struct(..) => check_type_defn(tcx, item, false),
293-
hir::ItemKind::Union(..) => check_type_defn(tcx, item, true),
294-
hir::ItemKind::Enum(..) => check_type_defn(tcx, item, true),
295291
// Note: do not add new entries to this match. Instead add all new logic in `check_item_type`
296292
_ => span_bug!(item.span, "should have been handled by the type based wf check: {item:?}"),
297293
}
@@ -989,15 +985,15 @@ pub(crate) fn check_associated_item(
989985
}
990986

991987
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
992-
fn check_type_defn<'tcx>(
988+
pub(crate) fn check_type_defn<'tcx>(
993989
tcx: TyCtxt<'tcx>,
994-
item: &hir::Item<'tcx>,
990+
item: LocalDefId,
995991
all_sized: bool,
996992
) -> Result<(), ErrorGuaranteed> {
997-
let _ = tcx.representability(item.owner_id.def_id);
998-
let adt_def = tcx.adt_def(item.owner_id);
993+
let _ = tcx.representability(item);
994+
let adt_def = tcx.adt_def(item);
999995

1000-
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
996+
enter_wf_checking_ctxt(tcx, item, |wfcx| {
1001997
let variants = adt_def.variants();
1002998
let packed = adt_def.repr().packed();
1003999

@@ -1068,15 +1064,7 @@ fn check_type_defn<'tcx>(
10681064
hir_ty.span,
10691065
wfcx.body_def_id,
10701066
ObligationCauseCode::FieldSized {
1071-
adt_kind: match &item.kind {
1072-
ItemKind::Struct(..) => AdtKind::Struct,
1073-
ItemKind::Union(..) => AdtKind::Union,
1074-
ItemKind::Enum(..) => AdtKind::Enum,
1075-
kind => span_bug!(
1076-
item.span,
1077-
"should be wfchecking an ADT, got {kind:?}"
1078-
),
1079-
},
1067+
adt_kind: adt_def.adt_kind(),
10801068
span: hir_ty.span,
10811069
last,
10821070
},
@@ -1099,7 +1087,7 @@ fn check_type_defn<'tcx>(
10991087
}
11001088
}
11011089

1102-
check_where_clauses(wfcx, item.owner_id.def_id);
1090+
check_where_clauses(wfcx, item);
11031091
Ok(())
11041092
})
11051093
}

tests/ui/generic-associated-types/static-lifetime-tip-with-default-type.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,6 @@ help: consider adding an explicit lifetime bound
8282
LL | struct Far<T: 'static
8383
| +++++++++
8484

85-
error[E0392]: lifetime parameter `'a` is never used
86-
--> $DIR/static-lifetime-tip-with-default-type.rs:22:10
87-
|
88-
LL | struct S<'a, K: 'a = i32>(&'static K);
89-
| ^^ unused lifetime parameter
90-
|
91-
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
92-
9385
error[E0310]: the parameter type `K` may not live long enough
9486
--> $DIR/static-lifetime-tip-with-default-type.rs:22:27
9587
|
@@ -104,6 +96,14 @@ help: consider adding an explicit lifetime bound
10496
LL | struct S<'a, K: 'a + 'static = i32>(&'static K);
10597
| +++++++++
10698

99+
error[E0392]: lifetime parameter `'a` is never used
100+
--> $DIR/static-lifetime-tip-with-default-type.rs:22:10
101+
|
102+
LL | struct S<'a, K: 'a = i32>(&'static K);
103+
| ^^ unused lifetime parameter
104+
|
105+
= help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
106+
107107
error: aborting due to 8 previous errors
108108

109109
Some errors have detailed explanations: E0310, E0392.

tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ LL | beta: [(); foo::<&'a ()>()],
77
= note: lifetime parameters may not be used in const expressions
88
= help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
99

10+
error: generic `Self` types are currently not permitted in anonymous constants
11+
--> $DIR/issue-64173-unused-lifetimes.rs:4:28
12+
|
13+
LL | array: [(); size_of::<&Self>()],
14+
| ^^^^
15+
1016
error[E0392]: lifetime parameter `'s` is never used
1117
--> $DIR/issue-64173-unused-lifetimes.rs:3:12
1218
|
@@ -15,12 +21,6 @@ LL | struct Foo<'s> {
1521
|
1622
= help: consider removing `'s`, referring to it in a field, or using a marker such as `PhantomData`
1723

18-
error: generic `Self` types are currently not permitted in anonymous constants
19-
--> $DIR/issue-64173-unused-lifetimes.rs:4:28
20-
|
21-
LL | array: [(); size_of::<&Self>()],
22-
| ^^^^
23-
2424
error[E0392]: lifetime parameter `'a` is never used
2525
--> $DIR/issue-64173-unused-lifetimes.rs:15:12
2626
|

tests/ui/regions/region-bounds-on-objects-and-type-parameters.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,6 @@ error[E0226]: only a single explicit lifetime bound is permitted
44
LL | z: Box<dyn Is<'a>+'b+'c>,
55
| ^^
66

7-
error[E0392]: lifetime parameter `'c` is never used
8-
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18
9-
|
10-
LL | struct Foo<'a,'b,'c> {
11-
| ^^ unused lifetime parameter
12-
|
13-
= help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
14-
157
error[E0478]: lifetime bound not satisfied
168
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:21:8
179
|
@@ -29,6 +21,14 @@ note: but lifetime parameter must outlive the lifetime `'a` as defined here
2921
LL | struct Foo<'a,'b,'c> {
3022
| ^^
3123

24+
error[E0392]: lifetime parameter `'c` is never used
25+
--> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:18
26+
|
27+
LL | struct Foo<'a,'b,'c> {
28+
| ^^ unused lifetime parameter
29+
|
30+
= help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
31+
3232
error: aborting due to 3 previous errors
3333

3434
Some errors have detailed explanations: E0226, E0392, E0478.

tests/ui/traits/issue-105231.stderr

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error: type parameter `T` is only used recursively
2-
--> $DIR/issue-105231.rs:1:15
3-
|
4-
LL | struct A<T>(B<T>);
5-
| - ^
6-
| |
7-
| type parameter must be used non-recursively in the definition
8-
|
9-
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
10-
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
11-
121
error[E0072]: recursive types `A` and `B` have infinite size
132
--> $DIR/issue-105231.rs:1:1
143
|
@@ -26,6 +15,17 @@ LL |
2615
LL ~ struct B<T>(Box<A<A<T>>>);
2716
|
2817

18+
error: type parameter `T` is only used recursively
19+
--> $DIR/issue-105231.rs:1:15
20+
|
21+
LL | struct A<T>(B<T>);
22+
| - ^
23+
| |
24+
| type parameter must be used non-recursively in the definition
25+
|
26+
= help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
27+
= note: all type parameters must be used in a non-recursive way in order to constrain their variance
28+
2929
error: type parameter `T` is only used recursively
3030
--> $DIR/issue-105231.rs:4:17
3131
|

0 commit comments

Comments
 (0)