Skip to content

Commit 51abd09

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 b94bd12 + ae395ef commit 51abd09

File tree

11 files changed

+106
-96
lines changed

11 files changed

+106
-96
lines changed

compiler/rustc_errors/src/diagnostic.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,14 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
12641264
self
12651265
} }
12661266

1267+
with_fn! { with_replace_span,
1268+
/// Replace all occurrences of the first span with the second one
1269+
#[rustc_lint_diagnostics]
1270+
pub fn replace_span(&mut self, before: Span, after: Span) -> &mut Self {
1271+
self.span.replace(before, after);
1272+
self
1273+
} }
1274+
12671275
#[rustc_lint_diagnostics]
12681276
pub fn is_lint(&mut self, name: String, has_future_breakage: bool) -> &mut Self {
12691277
self.is_lint = Some(IsLint { name, has_future_breakage });

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>(
@@ -782,9 +784,12 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
782784
tcx.ensure_ok().generics_of(def_id);
783785
tcx.ensure_ok().type_of(def_id);
784786
tcx.ensure_ok().predicates_of(def_id);
785-
crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id());
787+
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);
@@ -844,12 +849,19 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
844849
_ => {}
845850
}
846851
}
852+
res = res.and(wfcheck::check_trait(tcx, def_id));
853+
wfcheck::check_gat_where_clauses(tcx, def_id);
854+
// Trait aliases do not have hir checks anymore
855+
return res;
847856
}
848857
DefKind::TraitAlias => {
849858
tcx.ensure_ok().generics_of(def_id);
850859
tcx.ensure_ok().explicit_implied_predicates_of(def_id);
851860
tcx.ensure_ok().explicit_super_predicates_of(def_id);
852861
tcx.ensure_ok().predicates_of(def_id);
862+
res = res.and(wfcheck::check_trait(tcx, def_id));
863+
// Trait aliases do not have hir checks anymore
864+
return res;
853865
}
854866
def_kind @ (DefKind::Struct | DefKind::Union) => {
855867
tcx.ensure_ok().generics_of(def_id);
@@ -864,14 +876,16 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
864876
}
865877

866878
if let Some((_, ctor_def_id)) = adt.ctor {
867-
crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local());
879+
crate::collect::check_ctor(tcx, ctor_def_id.expect_local());
868880
}
869-
match def_kind {
881+
res = res.and(match def_kind {
870882
DefKind::Struct => check_struct(tcx, def_id),
871883
DefKind::Union => check_union(tcx, def_id),
872884
_ => unreachable!(),
873-
}
885+
});
874886
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;
875889
}
876890
DefKind::OpaqueTy => {
877891
check_opaque_precise_captures(tcx, def_id);
@@ -922,6 +936,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
922936
}));
923937
check_variances_for_type_defn(tcx, def_id);
924938
}
939+
// Doesn't have any hir based checks
940+
return res;
925941
}
926942
DefKind::ForeignMod => {
927943
let it = tcx.hir_expect_item(def_id);
@@ -984,6 +1000,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
9841000
_ => (),
9851001
}
9861002
}
1003+
// Doesn't have any hir based checks
1004+
return res;
9871005
}
9881006
DefKind::Closure => {
9891007
// This is guaranteed to be called by metadata encoding,
@@ -1059,10 +1077,14 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
10591077
return res;
10601078
}
10611079

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

compiler/rustc_hir_analysis/src/check/wfcheck.rs

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

@@ -344,7 +339,7 @@ pub(crate) fn check_trait_item<'tcx>(
344339
/// fn into_iter<'a>(&'a self) -> Self::Iter<'a>;
345340
/// }
346341
/// ```
347-
fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
342+
pub(crate) fn check_gat_where_clauses(tcx: TyCtxt<'_>, trait_def_id: LocalDefId) {
348343
// Associates every GAT's def_id to a list of possibly missing bounds detected by this lint.
349344
let mut required_bounds_by_item = FxIndexMap::default();
350345
let associated_items = tcx.associated_items(trait_def_id);
@@ -990,15 +985,15 @@ pub(crate) fn check_associated_item(
990985
}
991986

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

1001-
enter_wf_checking_ctxt(tcx, item.owner_id.def_id, |wfcx| {
996+
enter_wf_checking_ctxt(tcx, item, |wfcx| {
1002997
let variants = adt_def.variants();
1003998
let packed = adt_def.repr().packed();
1004999

@@ -1056,35 +1051,21 @@ fn check_type_defn<'tcx>(
10561051
variant.fields.raw[..variant.fields.len() - unsized_len].iter().enumerate()
10571052
{
10581053
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-
);
1054+
let span = tcx.def_span(field.did);
1055+
let ty = wfcx.normalize(span, None, tcx.type_of(field.did).instantiate_identity());
10671056
wfcx.register_bound(
10681057
traits::ObligationCause::new(
1069-
hir_ty.span,
1058+
span,
10701059
wfcx.body_def_id,
10711060
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,
1061+
adt_kind: adt_def.adt_kind(),
1062+
field: field.did,
10821063
last,
10831064
},
10841065
),
10851066
wfcx.param_env,
10861067
ty,
1087-
tcx.require_lang_item(LangItem::Sized, hir_ty.span),
1068+
tcx.require_lang_item(LangItem::Sized, span),
10881069
);
10891070
}
10901071

@@ -1100,16 +1081,13 @@ fn check_type_defn<'tcx>(
11001081
}
11011082
}
11021083

1103-
check_where_clauses(wfcx, item.owner_id.def_id);
1084+
check_where_clauses(wfcx, item);
11041085
Ok(())
11051086
})
11061087
}
11071088

1108-
#[instrument(skip(tcx, item))]
1109-
fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuaranteed> {
1110-
debug!(?item.owner_id);
1111-
1112-
let def_id = item.owner_id.def_id;
1089+
#[instrument(skip(tcx))]
1090+
pub(crate) fn check_trait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
11131091
if tcx.is_lang_item(def_id.into(), LangItem::PointeeSized) {
11141092
// `PointeeSized` is removed during lowering.
11151093
return Ok(());
@@ -1135,10 +1113,6 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) -> Result<(), ErrorGuarant
11351113
Ok(())
11361114
});
11371115

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

compiler/rustc_hir_analysis/src/collect.rs

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

608-
pub(super) fn lower_variant_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
608+
pub(super) fn check_ctor(tcx: TyCtxt<'_>, def_id: LocalDefId) {
609609
tcx.ensure_ok().generics_of(def_id);
610610
tcx.ensure_ok().type_of(def_id);
611611
tcx.ensure_ok().predicates_of(def_id);
612612
}
613613

614-
pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
614+
pub(super) fn check_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
615615
let def = tcx.adt_def(def_id);
616616
let repr_type = def.repr().discr_type();
617617
let initial = repr_type.initial_discriminant(tcx);
@@ -646,7 +646,7 @@ pub(super) fn lower_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
646646

647647
// Lower the ctor, if any. This also registers the variant as an item.
648648
if let Some(ctor_def_id) = variant.ctor_def_id() {
649-
lower_variant_ctor(tcx, ctor_def_id.expect_local());
649+
check_ctor(tcx, ctor_def_id.expect_local());
650650
}
651651
}
652652
}

compiler/rustc_hir_typeck/src/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3910,7 +3910,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
39103910
expr.span,
39113911
ObligationCauseCode::FieldSized {
39123912
adt_kind: AdtKind::Enum,
3913-
span: self.tcx.def_span(field.did),
3913+
field: field.did,
39143914
last: false,
39153915
},
39163916
);

compiler/rustc_middle/src/traits/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ pub enum ObligationCauseCode<'tcx> {
261261
/// Types of fields (other than the last, except for packed structs) in a struct must be sized.
262262
FieldSized {
263263
adt_kind: AdtKind,
264-
span: Span,
264+
field: DefId,
265265
last: bool,
266266
},
267267

compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3121,7 +3121,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
31213121
ObligationCauseCode::StructInitializerSized => {
31223122
err.note("structs must have a statically known size to be initialized");
31233123
}
3124-
ObligationCauseCode::FieldSized { adt_kind: ref item, last, span } => {
3124+
ObligationCauseCode::FieldSized { adt_kind: ref item, last, field } => {
3125+
let def_span = tcx.def_span(field);
3126+
let span = field
3127+
.as_local()
3128+
.map(|field| tcx.hir_node_by_def_id(field).expect_field().ty.span)
3129+
.unwrap_or(def_span);
3130+
err.replace_span(def_span, span);
31253131
match *item {
31263132
AdtKind::Struct => {
31273133
if last {

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)