Skip to content

Commit 2fb9abc

Browse files
committed
Auto merge of #143328 - oli-obk:ty-decl-wf-check, r=<try>
Avoid loading HIR for check_well_formed on type declarations r? `@compiler-errors` the last commit is quite hacky. I could add a `ty_span` query to work together with `def_span` and `def_ident_span`, which would nicely solve all those cases, but potentially add lots of new dep graph edges
2 parents d350797 + 74ee3af commit 2fb9abc

File tree

8 files changed

+93
-101
lines changed

8 files changed

+93
-101
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: 34 additions & 12 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>(
@@ -781,9 +783,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
781783
tcx.ensure_ok().generics_of(def_id);
782784
tcx.ensure_ok().type_of(def_id);
783785
tcx.ensure_ok().predicates_of(def_id);
784-
crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id());
786+
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);
@@ -843,12 +848,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
843848
_ => {}
844849
}
845850
}
851+
res = res.and(wfcheck::check_trait(tcx, def_id));
852+
wfcheck::check_gat_where_clauses(tcx, def_id);
853+
// Trait aliases do not have hir checks anymore
854+
return res;
846855
}
847856
DefKind::TraitAlias => {
848857
tcx.ensure_ok().generics_of(def_id);
849858
tcx.ensure_ok().explicit_implied_predicates_of(def_id);
850859
tcx.ensure_ok().explicit_super_predicates_of(def_id);
851860
tcx.ensure_ok().predicates_of(def_id);
861+
res = res.and(wfcheck::check_trait(tcx, def_id));
862+
// Trait aliases do not have hir checks anymore
863+
return res;
852864
}
853865
def_kind @ (DefKind::Struct | DefKind::Union) => {
854866
tcx.ensure_ok().generics_of(def_id);
@@ -863,14 +875,16 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
863875
}
864876

865877
if let Some((_, ctor_def_id)) = adt.ctor {
866-
crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local());
878+
crate::collect::check_ctor(tcx, ctor_def_id.expect_local());
867879
}
868-
match def_kind {
880+
res = res.and(match def_kind {
869881
DefKind::Struct => check_struct(tcx, def_id),
870882
DefKind::Union => check_union(tcx, def_id),
871883
_ => unreachable!(),
872-
}
884+
});
873885
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;
874888
}
875889
DefKind::OpaqueTy => {
876890
check_opaque_precise_captures(tcx, def_id);
@@ -921,6 +935,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
921935
}));
922936
check_variances_for_type_defn(tcx, def_id);
923937
}
938+
// Doesn't have any hir based checks
939+
return res;
924940
}
925941
DefKind::ForeignMod => {
926942
let it = tcx.hir_expect_item(def_id);
@@ -983,6 +999,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
983999
_ => (),
9841000
}
9851001
}
1002+
// Doesn't have any hir based checks
1003+
return res;
9861004
}
9871005
DefKind::Closure => {
9881006
// 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<(),
10581076
return res;
10591077
}
10601078

1061-
// Only `Node::Item` and `Node::ForeignItem` still have HIR based
1062-
// checks. Returning early here does not miss any checks and
1063-
// avoids this query from having a direct dependency edge on the HIR
1064-
DefKind::AnonConst | DefKind::InlineConst => return res,
1079+
// These have no wf checks
1080+
DefKind::AnonConst
1081+
| DefKind::InlineConst
1082+
| DefKind::ExternCrate
1083+
| DefKind::Macro(..)
1084+
| DefKind::Use
1085+
| DefKind::GlobalAsm
1086+
| DefKind::Mod => return res,
10651087
_ => {}
10661088
}
10671089
let node = tcx.hir_node_by_def_id(def_id);

compiler/rustc_hir_analysis/src/check/wfcheck.rs

Lines changed: 22 additions & 53 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,12 +289,8 @@ 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),
296-
hir::ItemKind::Trait(..) => check_trait(tcx, item),
297-
hir::ItemKind::TraitAlias(..) => check_trait(tcx, item),
298-
_ => Ok(()),
292+
// Note: do not add new entries to this match. Instead add all new logic in `check_item_type`
293+
_ => span_bug!(item.span, "should have been handled by the type based wf check: {item:?}"),
299294
}
300295
}
301296

@@ -345,7 +340,7 @@ pub(crate) fn check_trait_item<'tcx>(
345340
/// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
346341
/// }
347342
/// ```
348-
fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
343+
pub(crate) fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
349344
// Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.
350345
let mut required_bounds_by_item = FxIndexMap::default();
351346
let associated_items = tcx.associated_items(trait_def_id);
@@ -991,15 +986,15 @@ pub(crate) fn check_associated_item(
991986
}
992987

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

1002-
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
997+
enter_wf_checking_ctxt(tcx, item, |wfcx| {
1003998
let variants = adt_def.variants();
1004999
let packed = adt_def.repr().packed();
10051000

@@ -1026,18 +1021,13 @@ fn check_type_defn<'tcx>(
10261021
}
10271022
}
10281023
let field_id = field.did.expect_local();
1029-
let hir::FieldDef { ty: hir_ty, .. } =
1030-
tcx.hir_node_by_def_id(field_id).expect_field();
1024+
let span = tcx.ty_span(field_id);
10311025
let ty = wfcx.deeply_normalize(
1032-
hir_ty.span,
1026+
span,
10331027
None,
10341028
tcx.type_of(field.did).instantiate_identity(),
10351029
);
1036-
wfcx.register_wf_obligation(
1037-
hir_ty.span,
1038-
Some(WellFormedLoc::Ty(field_id)),
1039-
ty.into(),
1040-
)
1030+
wfcx.register_wf_obligation(span, Some(WellFormedLoc::Ty(field_id)), ty.into())
10411031
}
10421032

10431033
// For DST, or when drop needs to copy things around, all
@@ -1057,35 +1047,21 @@ fn check_type_defn<'tcx>(
10571047
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
10581048
{
10591049
let last = idx == variant.fields.len() - 1;
1060-
let field_id = field.did.expect_local();
1061-
let hir::FieldDef { ty: hir_ty, .. } =
1062-
tcx.hir_node_by_def_id(field_id).expect_field();
1063-
let ty = wfcx.normalize(
1064-
hir_ty.span,
1065-
None,
1066-
tcx.type_of(field.did).instantiate_identity(),
1067-
);
1050+
let span = tcx.ty_span(field.did.expect_local());
1051+
let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity());
10681052
wfcx.register_bound(
10691053
traits::ObligationCause::new(
1070-
hir_ty.span,
1054+
span,
10711055
wfcx.body_def_id,
10721056
ObligationCauseCode::FieldSized {
1073-
adt_kind: match &item.kind {
1074-
ItemKind::Struct(..) => AdtKind::Struct,
1075-
ItemKind::Union(..) => AdtKind::Union,
1076-
ItemKind::Enum(..) => AdtKind::Enum,
1077-
kind => span_bug!(
1078-
item.span,
1079-
"should be wfchecking an ADT, got {kind:?}"
1080-
),
1081-
},
1082-
span: hir_ty.span,
1057+
adt_kind: adt_def.adt_kind(),
1058+
span,
10831059
last,
10841060
},
10851061
),
10861062
wfcx.param_env,
10871063
ty,
1088-
tcx.require_lang_item(LangItem::Sized, hir_ty.span),
1064+
tcx.require_lang_item(LangItem::Sized, span),
10891065
);
10901066
}
10911067

@@ -1101,16 +1077,13 @@ fn check_type_defn<'tcx>(
11011077
}
11021078
}
11031079

1104-
check_where_clauses(wfcx, item.owner_id.def_id);
1080+
check_where_clauses(wfcx, item);
11051081
Ok(())
11061082
})
11071083
}
11081084

1109-
#[instrument(skip(tcx, item))]
1110-
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> {
1111-
debug!(?item.owner_id);
1112-
1113-
let def_id = item.owner_id.def_id;
1085+
#[instrument(skip(tcx))]
1086+
pub(crate) fn check_trait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
11141087
if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {
11151088
// `PointeeSized` is removed during lowering.
11161089
return Ok(());
@@ -1136,10 +1109,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
11361109
Ok(())
11371110
});
11381111

1139-
// Only check traits, don't check trait aliases
1140-
if let hir::ItemKind::Trait(..) = item.kind {
1141-
check_gat_where_clauses(tcx, item.owner_id.def_id);
1142-
}
11431112
res
11441113
}
11451114

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -600,13 +600,13 @@ fn get_new_lifetime_name<'tcx>(
600600
(1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap()
601601
}
602602

603-
pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
603+
pub(super) fn check_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
604604
tcx.ensure_ok().generics_of(def_id);
605605
tcx.ensure_ok().type_of(def_id);
606606
tcx.ensure_ok().predicates_of(def_id);
607607
}
608608

609-
pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
609+
pub(super) fn check_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
610610
let def = tcx.adt_def(def_id);
611611
let repr_type = def.repr().discr_type();
612612
let initial = repr_type.initial_discriminant(tcx);
@@ -641,7 +641,7 @@ pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
641641

642642
// Lower the ctor, if any. This also registers the variant as an item.
643643
if let Some(ctor_def_id) = variant.ctor_def_id() {
644-
lower_variant_ctor(tcx, ctor_def_id.expect_local());
644+
check_ctor(tcx, ctor_def_id.expect_local());
645645
}
646646
}
647647
}

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
|

0 commit comments

Comments
 (0)