Skip to content

Commit 128972a

Browse files
committed
Auto merge of #142030 - oli-obk:wfck-less-hir, r=<try>
Start moving wf checking away from HIR I'm trying to only access the HIR in the error path. My hope is that once we move significant portions of wfcheck off HIR that incremental will be able to cache wfcheck queries significantly better. I think I am reaching a blocker because we normally need to provide good spans to `ObligationCause`, so that the trait solver can report good errors. In some cases I have been able to use bad spans and improve them depending on the `ObligationCauseCode` (by loading HIR in the case where we actually want to error). To scale that further we'll likely need to remove spans from the `ObligationCause` entirely (leaving it to some variants of `ObligationCauseCode` to have a span when they can't recompute the information later). Unsure this is the right approach, but we've already been using it. I will create an MCP about it, but that should not affect this PR, which is fairly limited in where it does those kind of tricks. Especially b862d88 is interesting here, because I think it improves spans in all cases
2 parents bc4376f + d587a01 commit 128972a

File tree

139 files changed

+1487
-1624
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+1487
-1624
lines changed

compiler/rustc_hir/src/hir.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3141,6 +3141,15 @@ pub enum TraitItemKind<'hir> {
31413141
/// type.
31423142
Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>),
31433143
}
3144+
impl TraitItemKind<'_> {
3145+
pub fn descr(&self) -> &'static str {
3146+
match self {
3147+
TraitItemKind::Const(..) => "associated constant",
3148+
TraitItemKind::Fn(..) => "function",
3149+
TraitItemKind::Type(..) => "associated type",
3150+
}
3151+
}
3152+
}
31443153

31453154
// The bodies for items are stored "out of line", in a separate
31463155
// hashmap in the `Crate`. Here we just record the hir-id of the item
@@ -3202,6 +3211,15 @@ pub enum ImplItemKind<'hir> {
32023211
/// An associated type.
32033212
Type(&'hir Ty<'hir>),
32043213
}
3214+
impl ImplItemKind<'_> {
3215+
pub fn descr(&self) -> &'static str {
3216+
match self {
3217+
ImplItemKind::Const(..) => "associated constant",
3218+
ImplItemKind::Fn(..) => "function",
3219+
ImplItemKind::Type(..) => "associated type",
3220+
}
3221+
}
3222+
}
32053223

32063224
/// A constraint on an associated item.
32073225
///
@@ -4527,6 +4545,16 @@ pub enum ForeignItemKind<'hir> {
45274545
Type,
45284546
}
45294547

4548+
impl ForeignItemKind<'_> {
4549+
pub fn descr(&self) -> &'static str {
4550+
match self {
4551+
ForeignItemKind::Fn(..) => "function",
4552+
ForeignItemKind::Static(..) => "static variable",
4553+
ForeignItemKind::Type => "type",
4554+
}
4555+
}
4556+
}
4557+
45304558
/// A variable captured by a closure.
45314559
#[derive(Debug, Copy, Clone, HashStable_Generic)]
45324560
pub struct Upvar {
@@ -4834,6 +4862,10 @@ impl<'hir> Node<'hir> {
48344862
ImplItemKind::Type(ty) => Some(ty),
48354863
_ => None,
48364864
},
4865+
Node::ForeignItem(it) => match it.kind {
4866+
ForeignItemKind::Static(ty, ..) => Some(ty),
4867+
_ => None,
4868+
},
48374869
_ => None,
48384870
}
48394871
}

compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 165 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rustc_errors::{EmissionGuarantee, MultiSpan};
1010
use rustc_hir::def::{CtorKind, DefKind};
1111
use rustc_hir::{LangItem, Node, intravisit};
1212
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
13-
use rustc_infer::traits::{Obligation, ObligationCauseCode};
13+
use rustc_infer::traits::{Obligation, ObligationCauseCode, WellFormedLoc};
1414
use rustc_lint_defs::builtin::{
1515
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS,
1616
};
@@ -36,6 +36,10 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir};
3636

3737
use super::compare_impl_item::check_type_bounds;
3838
use super::*;
39+
use crate::check::wfcheck::{
40+
check_associated_item, check_trait_item, check_variances_for_type_defn, check_where_clauses,
41+
enter_wf_checking_ctxt,
42+
};
3943

4044
fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) {
4145
if let ExternAbi::Cdecl { unwind } = abi {
@@ -729,7 +733,8 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
729733
}
730734
}
731735

732-
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
736+
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
737+
let mut res = Ok(());
733738
let generics = tcx.generics_of(def_id);
734739

735740
for param in &generics.own_params {
@@ -754,15 +759,35 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
754759
}
755760

756761
match tcx.def_kind(def_id) {
757-
DefKind::Static { .. } => {
758-
check_static_inhabited(tcx, def_id);
759-
check_static_linkage(tcx, def_id);
762+
def_kind @ (DefKind::Static { .. } | DefKind::Const) => {
763+
tcx.ensure_ok().generics_of(def_id);
764+
tcx.ensure_ok().type_of(def_id);
765+
tcx.ensure_ok().predicates_of(def_id);
766+
match def_kind {
767+
DefKind::Static { .. } => {
768+
check_static_inhabited(tcx, def_id);
769+
check_static_linkage(tcx, def_id);
770+
res = res.and(wfcheck::check_static_item(tcx, def_id));
771+
return res;
772+
}
773+
DefKind::Const => {}
774+
_ => unreachable!(),
775+
}
760776
}
761-
DefKind::Const => {}
762777
DefKind::Enum => {
778+
tcx.ensure_ok().generics_of(def_id);
779+
tcx.ensure_ok().type_of(def_id);
780+
tcx.ensure_ok().predicates_of(def_id);
781+
crate::collect::lower_enum_variant_types(tcx, def_id.to_def_id());
763782
check_enum(tcx, def_id);
783+
check_variances_for_type_defn(tcx, def_id);
764784
}
765785
DefKind::Fn => {
786+
tcx.ensure_ok().generics_of(def_id);
787+
tcx.ensure_ok().type_of(def_id);
788+
tcx.ensure_ok().predicates_of(def_id);
789+
tcx.ensure_ok().fn_sig(def_id);
790+
tcx.ensure_ok().codegen_fn_attrs(def_id);
766791
if let Some(i) = tcx.intrinsic(def_id) {
767792
intrinsic::check_intrinsic_type(
768793
tcx,
@@ -773,17 +798,31 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
773798
}
774799
}
775800
DefKind::Impl { of_trait } => {
801+
tcx.ensure_ok().generics_of(def_id);
802+
tcx.ensure_ok().type_of(def_id);
803+
tcx.ensure_ok().impl_trait_header(def_id);
804+
tcx.ensure_ok().predicates_of(def_id);
805+
tcx.ensure_ok().associated_items(def_id);
776806
if of_trait && let Some(impl_trait_header) = tcx.impl_trait_header(def_id) {
777-
if tcx
778-
.ensure_ok()
779-
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id)
780-
.is_ok()
781-
{
807+
res = res.and(
808+
tcx.ensure_ok()
809+
.coherent_trait(impl_trait_header.trait_ref.instantiate_identity().def_id),
810+
);
811+
812+
if res.is_ok() {
813+
// Checking this only makes sense if the all trait impls satisfy basic
814+
// requirements (see `coherent_trait` query), otherwise
815+
// we run into infinite recursions a lot.
782816
check_impl_items_against_trait(tcx, def_id, impl_trait_header);
783817
}
784818
}
785819
}
786820
DefKind::Trait => {
821+
tcx.ensure_ok().generics_of(def_id);
822+
tcx.ensure_ok().trait_def(def_id);
823+
tcx.ensure_ok().explicit_super_predicates_of(def_id);
824+
tcx.ensure_ok().predicates_of(def_id);
825+
tcx.ensure_ok().associated_items(def_id);
787826
let assoc_items = tcx.associated_items(def_id);
788827
check_on_unimplemented(tcx, def_id);
789828

@@ -802,11 +841,33 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
802841
}
803842
}
804843
}
805-
DefKind::Struct => {
806-
check_struct(tcx, def_id);
844+
DefKind::TraitAlias => {
845+
tcx.ensure_ok().generics_of(def_id);
846+
tcx.ensure_ok().explicit_implied_predicates_of(def_id);
847+
tcx.ensure_ok().explicit_super_predicates_of(def_id);
848+
tcx.ensure_ok().predicates_of(def_id);
807849
}
808-
DefKind::Union => {
809-
check_union(tcx, def_id);
850+
def_kind @ (DefKind::Struct | DefKind::Union) => {
851+
tcx.ensure_ok().generics_of(def_id);
852+
tcx.ensure_ok().type_of(def_id);
853+
tcx.ensure_ok().predicates_of(def_id);
854+
855+
let adt = tcx.adt_def(def_id).non_enum_variant();
856+
for f in adt.fields.iter() {
857+
tcx.ensure_ok().generics_of(f.did);
858+
tcx.ensure_ok().type_of(f.did);
859+
tcx.ensure_ok().predicates_of(f.did);
860+
}
861+
862+
if let Some((_, ctor_def_id)) = adt.ctor {
863+
crate::collect::lower_variant_ctor(tcx, ctor_def_id.expect_local());
864+
}
865+
match def_kind {
866+
DefKind::Struct => check_struct(tcx, def_id),
867+
DefKind::Union => check_union(tcx, def_id),
868+
_ => unreachable!(),
869+
}
870+
check_variances_for_type_defn(tcx, def_id);
810871
}
811872
DefKind::OpaqueTy => {
812873
check_opaque_precise_captures(tcx, def_id);
@@ -831,14 +892,33 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
831892
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
832893
tcx.ensure_ok().const_conditions(def_id);
833894
}
895+
return res;
834896
}
835897
DefKind::TyAlias => {
898+
tcx.ensure_ok().generics_of(def_id);
899+
tcx.ensure_ok().type_of(def_id);
900+
tcx.ensure_ok().predicates_of(def_id);
836901
check_type_alias_type_params_are_used(tcx, def_id);
902+
if tcx.type_alias_is_lazy(def_id) {
903+
res = res.and(enter_wf_checking_ctxt(tcx, def_id, |wfcx| {
904+
let ty = tcx.type_of(def_id).instantiate_identity();
905+
let span = tcx.def_span(def_id);
906+
let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(def_id)), ty);
907+
wfcx.register_wf_obligation(
908+
span,
909+
Some(WellFormedLoc::Ty(def_id)),
910+
item_ty.into(),
911+
);
912+
check_where_clauses(wfcx, def_id);
913+
Ok(())
914+
}));
915+
check_variances_for_type_defn(tcx, def_id);
916+
}
837917
}
838918
DefKind::ForeignMod => {
839919
let it = tcx.hir_expect_item(def_id);
840920
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
841-
return;
921+
return Ok(());
842922
};
843923

844924
check_abi(tcx, it.hir_id(), it.span, abi);
@@ -877,15 +957,23 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
877957
}
878958

879959
let item = tcx.hir_foreign_item(item.id);
880-
match &item.kind {
881-
hir::ForeignItemKind::Fn(sig, _, _) => {
960+
tcx.ensure_ok().generics_of(item.owner_id);
961+
tcx.ensure_ok().type_of(item.owner_id);
962+
tcx.ensure_ok().predicates_of(item.owner_id);
963+
if tcx.is_conditionally_const(def_id) {
964+
tcx.ensure_ok().explicit_implied_const_bounds(def_id);
965+
tcx.ensure_ok().const_conditions(def_id);
966+
}
967+
match item.kind {
968+
hir::ForeignItemKind::Fn(sig, ..) => {
969+
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
970+
tcx.ensure_ok().fn_sig(item.owner_id);
882971
require_c_abi_if_c_variadic(tcx, sig.decl, abi, item.span);
883972
}
884973
hir::ForeignItemKind::Static(..) => {
885-
check_static_inhabited(tcx, def_id);
886-
check_static_linkage(tcx, def_id);
974+
tcx.ensure_ok().codegen_fn_attrs(item.owner_id);
887975
}
888-
_ => {}
976+
_ => (),
889977
}
890978
}
891979
}
@@ -897,9 +985,65 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
897985
// We do not call `type_of` for closures here as that
898986
// depends on typecheck and would therefore hide
899987
// any further errors in case one typeck fails.
988+
return res;
989+
}
990+
DefKind::AssocFn => {
991+
tcx.ensure_ok().codegen_fn_attrs(def_id);
992+
tcx.ensure_ok().type_of(def_id);
993+
tcx.ensure_ok().fn_sig(def_id);
994+
tcx.ensure_ok().predicates_of(def_id);
995+
res = res.and(check_associated_item(tcx, def_id));
996+
let assoc_item = tcx.associated_item(def_id);
997+
match assoc_item.container {
998+
ty::AssocItemContainer::Impl => {}
999+
ty::AssocItemContainer::Trait => {
1000+
res = res.and(check_trait_item(tcx, def_id));
1001+
}
1002+
}
1003+
return res;
1004+
}
1005+
DefKind::AssocConst => {
1006+
tcx.ensure_ok().type_of(def_id);
1007+
tcx.ensure_ok().predicates_of(def_id);
1008+
res = res.and(check_associated_item(tcx, def_id));
1009+
let assoc_item = tcx.associated_item(def_id);
1010+
match assoc_item.container {
1011+
ty::AssocItemContainer::Impl => {}
1012+
ty::AssocItemContainer::Trait => {
1013+
res = res.and(check_trait_item(tcx, def_id));
1014+
}
1015+
}
1016+
return res;
1017+
}
1018+
DefKind::AssocTy => {
1019+
tcx.ensure_ok().predicates_of(def_id);
1020+
res = res.and(check_associated_item(tcx, def_id));
1021+
1022+
let assoc_item = tcx.associated_item(def_id);
1023+
let has_type = match assoc_item.container {
1024+
ty::AssocItemContainer::Impl => true,
1025+
ty::AssocItemContainer::Trait => {
1026+
tcx.ensure_ok().item_bounds(def_id);
1027+
tcx.ensure_ok().item_self_bounds(def_id);
1028+
res = res.and(check_trait_item(tcx, def_id));
1029+
assoc_item.defaultness(tcx).has_value()
1030+
}
1031+
};
1032+
if has_type {
1033+
tcx.ensure_ok().type_of(def_id);
1034+
}
1035+
return res;
9001036
}
1037+
DefKind::AnonConst | DefKind::InlineConst => return res,
9011038
_ => {}
9021039
}
1040+
let node = tcx.hir_node_by_def_id(def_id);
1041+
res.and(match node {
1042+
hir::Node::Crate(_) => bug!("check_well_formed cannot be applied to the crate root"),
1043+
hir::Node::Item(item) => wfcheck::check_item(tcx, item),
1044+
hir::Node::ForeignItem(item) => wfcheck::check_foreign_item(tcx, item),
1045+
_ => unreachable!("{node:?}"),
1046+
})
9031047
}
9041048

9051049
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {

0 commit comments

Comments
 (0)