Skip to content

Commit e3d6d33

Browse files
committed
Check structs/enums/unions without loading their HIR
1 parent 324d950 commit e3d6d33

File tree

7 files changed

+64
-79
lines changed

7 files changed

+64
-79
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4818,6 +4818,7 @@ impl<'hir> Node<'hir> {
48184818
ForeignItemKind::Static(ty, ..) => Some(ty),
48194819
_ => None,
48204820
},
4821+
Node::Field(f) => Some(f.ty),
48214822
_ => None,
48224823
}
48234824
}

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>(
@@ -784,6 +786,9 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
784786
crate::collect::check_enum_variant_types(tcx, def_id.to_def_id());
785787
check_enum(tcx, def_id);
786788
check_variances_for_type_defn(tcx, def_id);
789+
res = res.and(check_type_defn(tcx, def_id, true));
790+
// enums are fully handled by the type based check and have no hir wfcheck logic
791+
return res;
787792
}
788793
DefKind::Fn => {
789794
tcx.ensure_ok().generics_of(def_id);
@@ -872,12 +877,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
872877
if let Some((_, ctor_def_id)) = adt.ctor {
873878
crate::collect::check_ctor(tcx, ctor_def_id.expect_local());
874879
}
875-
match def_kind {
880+
res = res.and(match def_kind {
876881
DefKind::Struct => check_struct(tcx, def_id),
877882
DefKind::Union => check_union(tcx, def_id),
878883
_ => unreachable!(),
879-
}
884+
});
880885
check_variances_for_type_defn(tcx, def_id);
886+
// structs and enums are fully handled by the type based check and have no hir wfcheck logic
887+
return res;
881888
}
882889
DefKind::OpaqueTy => {
883890
check_opaque_precise_captures(tcx, def_id);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

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

992988
/// In a type definition, we check that to ensure that the types of the fields are well-formed.
993-
fn check_type_defn<'tcx>(
989+
pub(crate) fn check_type_defn<'tcx>(
994990
tcx: TyCtxt<'tcx>,
995-
item: &hir::Item<'tcx>,
991+
item: LocalDefId,
996992
all_sized: bool,
997993
) -> Result<(), ErrorGuaranteed> {
998-
let _ = tcx.representability(item.owner_id.def_id);
999-
let adt_def = tcx.adt_def(item.owner_id);
994+
let _ = tcx.representability(item);
995+
let adt_def = tcx.adt_def(item);
1000996

1001-
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
997+
enter_wf_checking_ctxt(tcx, item, |wfcx| {
1002998
let variants = adt_def.variants();
1003999
let packed = adt_def.repr().packed();
10041000

@@ -1025,18 +1021,13 @@ fn check_type_defn<'tcx>(
10251021
}
10261022
}
10271023
let field_id = field.did.expect_local();
1028-
let hir::FieldDef { ty: hir_ty, .. } =
1029-
tcx.hir_node_by_def_id(field_id).expect_field();
1024+
let span = tcx.ty_span(field_id);
10301025
let ty = wfcx.deeply_normalize(
1031-
hir_ty.span,
1026+
span,
10321027
None,
10331028
tcx.type_of(field.did).instantiate_identity(),
10341029
);
1035-
wfcx.register_wf_obligation(
1036-
hir_ty.span,
1037-
Some(WellFormedLoc::Ty(field_id)),
1038-
ty.into(),
1039-
)
1030+
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(field_id)), ty.into())
10401031
}
10411032

10421033
// For DST, or when drop needs to copy things around, all
@@ -1056,35 +1047,21 @@ fn check_type_defn<'tcx>(
10561047
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
10571048
{
10581049
let last = idx == variant.fields.len() - 1;
1059-
let field_id = field.did.expect_local();
1060-
let hir::FieldDef { ty: hir_ty, .. } =
1061-
tcx.hir_node_by_def_id(field_id).expect_field();
1062-
let ty = wfcx.normalize(
1063-
hir_ty.span,
1064-
None,
1065-
tcx.type_of(field.did).instantiate_identity(),
1066-
);
1050+
let span = tcx.ty_span(field.did.expect_local());
1051+
let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity());
10671052
wfcx.register_bound(
10681053
traits::ObligationCause::new(
1069-
hir_ty.span,
1054+
span,
10701055
wfcx.body_def_id,
10711056
ObligationCauseCode::FieldSized {
1072-
adt_kind: match &item.kind {
1073-
ItemKind::Struct(..) => AdtKind::Struct,
1074-
ItemKind::Union(..) => AdtKind::Union,
1075-
ItemKind::Enum(..) => AdtKind::Enum,
1076-
kind => span_bug!(
1077-
item.span,
1078-
"should be wfchecking an ADT, got {kind:?}"
1079-
),
1080-
},
1081-
span: hir_ty.span,
1057+
adt_kind: adt_def.adt_kind(),
1058+
span,
10821059
last,
10831060
},
10841061
),
10851062
wfcx.param_env,
10861063
ty,
1087-
tcx.require_lang_item(LangItem::Sized, hir_ty.span),
1064+
tcx.require_lang_item(LangItem::Sized, span),
10881065
);
10891066
}
10901067

@@ -1100,7 +1077,7 @@ fn check_type_defn<'tcx>(
11001077
}
11011078
}
11021079

1103-
check_where_clauses(wfcx, item.owner_id.def_id);
1080+
check_where_clauses(wfcx, item);
11041081
Ok(())
11051082
})
11061083
}

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)