Auto merge of #117213 - oli-obk:check_item_type_cleanup, r=estebank
Reorder check_item_type diagnostics so they occur next to the corresponding `check_well_formed` diagnostics The first commit is just a cleanup. The second commit moves most checks from `check_mod_item_types` into `check_well_formed`, invoking the checks in lockstep per-item instead of iterating over all items twice.
This commit is contained in:
commit
791a53f380
35 changed files with 388 additions and 323 deletions
|
@ -8,7 +8,7 @@ use rustc_attr as attr;
|
|||
use rustc_errors::{ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_hir::Node;
|
||||
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
|
||||
use rustc_infer::traits::{Obligation, TraitEngineExt as _};
|
||||
|
@ -198,8 +198,8 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
|
||||
/// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
|
||||
/// projections that would result in "inheriting lifetimes".
|
||||
fn check_opaque(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
||||
let item = tcx.hir().item(id);
|
||||
fn check_opaque(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let item = tcx.hir().expect_item(def_id);
|
||||
let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
|
||||
tcx.dcx().span_delayed_bug(item.span, "expected opaque item");
|
||||
return;
|
||||
|
@ -440,40 +440,31 @@ fn check_static_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
||||
debug!(
|
||||
"check_item_type(it.def_id={:?}, it.name={})",
|
||||
id.owner_id,
|
||||
tcx.def_path_str(id.owner_id)
|
||||
);
|
||||
pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let _indenter = indenter();
|
||||
match tcx.def_kind(id.owner_id) {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Static(..) => {
|
||||
tcx.ensure().typeck(id.owner_id.def_id);
|
||||
maybe_check_static_with_link_section(tcx, id.owner_id.def_id);
|
||||
check_static_inhabited(tcx, id.owner_id.def_id);
|
||||
check_static_linkage(tcx, id.owner_id.def_id);
|
||||
tcx.ensure().typeck(def_id);
|
||||
maybe_check_static_with_link_section(tcx, def_id);
|
||||
check_static_inhabited(tcx, def_id);
|
||||
check_static_linkage(tcx, def_id);
|
||||
}
|
||||
DefKind::Const => {
|
||||
tcx.ensure().typeck(id.owner_id.def_id);
|
||||
tcx.ensure().typeck(def_id);
|
||||
}
|
||||
DefKind::Enum => {
|
||||
check_enum(tcx, id.owner_id.def_id);
|
||||
check_enum(tcx, def_id);
|
||||
}
|
||||
DefKind::Fn => {} // entirely within check_item_body
|
||||
DefKind::Impl { of_trait } => {
|
||||
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(id.owner_id) {
|
||||
check_impl_items_against_trait(
|
||||
tcx,
|
||||
id.owner_id.def_id,
|
||||
impl_trait_ref.instantiate_identity(),
|
||||
);
|
||||
check_on_unimplemented(tcx, id);
|
||||
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
|
||||
check_impl_items_against_trait(tcx, def_id, impl_trait_ref.instantiate_identity());
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
}
|
||||
}
|
||||
DefKind::Trait => {
|
||||
let assoc_items = tcx.associated_items(id.owner_id);
|
||||
check_on_unimplemented(tcx, id);
|
||||
let assoc_items = tcx.associated_items(def_id);
|
||||
check_on_unimplemented(tcx, def_id);
|
||||
|
||||
for &assoc_item in assoc_items.in_definition_order() {
|
||||
match assoc_item.kind {
|
||||
|
@ -482,12 +473,12 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
forbid_intrinsic_abi(tcx, assoc_item.ident(tcx).span, abi);
|
||||
}
|
||||
ty::AssocKind::Type if assoc_item.defaultness(tcx).has_value() => {
|
||||
let trait_args = GenericArgs::identity_for_item(tcx, id.owner_id);
|
||||
let trait_args = GenericArgs::identity_for_item(tcx, def_id);
|
||||
let _: Result<_, rustc_errors::ErrorGuaranteed> = check_type_bounds(
|
||||
tcx,
|
||||
assoc_item,
|
||||
assoc_item,
|
||||
ty::TraitRef::new(tcx, id.owner_id.to_def_id(), trait_args),
|
||||
ty::TraitRef::new(tcx, def_id.to_def_id(), trait_args),
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
|
@ -495,13 +486,13 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
}
|
||||
}
|
||||
DefKind::Struct => {
|
||||
check_struct(tcx, id.owner_id.def_id);
|
||||
check_struct(tcx, def_id);
|
||||
}
|
||||
DefKind::Union => {
|
||||
check_union(tcx, id.owner_id.def_id);
|
||||
check_union(tcx, def_id);
|
||||
}
|
||||
DefKind::OpaqueTy => {
|
||||
let origin = tcx.opaque_type_origin(id.owner_id.def_id);
|
||||
let origin = tcx.opaque_type_origin(def_id);
|
||||
if let hir::OpaqueTyOrigin::FnReturn(fn_def_id)
|
||||
| hir::OpaqueTyOrigin::AsyncFn(fn_def_id) = origin
|
||||
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)
|
||||
|
@ -509,16 +500,16 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
{
|
||||
// Skip opaques from RPIT in traits with no default body.
|
||||
} else {
|
||||
check_opaque(tcx, id);
|
||||
check_opaque(tcx, def_id);
|
||||
}
|
||||
}
|
||||
DefKind::TyAlias => {
|
||||
let pty_ty = tcx.type_of(id.owner_id).instantiate_identity();
|
||||
let generics = tcx.generics_of(id.owner_id);
|
||||
let pty_ty = tcx.type_of(def_id).instantiate_identity();
|
||||
let generics = tcx.generics_of(def_id);
|
||||
check_type_params_are_used(tcx, generics, pty_ty);
|
||||
}
|
||||
DefKind::ForeignMod => {
|
||||
let it = tcx.hir().item(id);
|
||||
let it = tcx.hir().expect_item(def_id);
|
||||
let hir::ItemKind::ForeignMod { abi, items } = it.kind else {
|
||||
return;
|
||||
};
|
||||
|
@ -589,19 +580,19 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
|
|||
}
|
||||
}
|
||||
DefKind::GlobalAsm => {
|
||||
let it = tcx.hir().item(id);
|
||||
let it = tcx.hir().expect_item(def_id);
|
||||
let hir::ItemKind::GlobalAsm(asm) = it.kind else {
|
||||
span_bug!(it.span, "DefKind::GlobalAsm but got {:#?}", it)
|
||||
};
|
||||
InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, id.owner_id.def_id);
|
||||
InlineAsmCtxt::new_global_asm(tcx).check_asm(asm, def_id);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, item: hir::ItemId) {
|
||||
pub(super) fn check_on_unimplemented(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
// an error would be reported if this fails.
|
||||
let _ = OnUnimplementedDirective::of_item(tcx, item.owner_id.to_def_id());
|
||||
let _ = OnUnimplementedDirective::of_item(tcx, def_id.to_def_id());
|
||||
}
|
||||
|
||||
pub(super) fn check_specialization_validity<'tcx>(
|
||||
|
@ -1309,16 +1300,6 @@ pub(super) fn check_type_params_are_used<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
let module = tcx.hir_module_items(module_def_id);
|
||||
for id in module.items() {
|
||||
check_item_type(tcx, id);
|
||||
}
|
||||
if module_def_id == LocalModDefId::CRATE_DEF_ID {
|
||||
super::entry::check_for_entry_fn(tcx);
|
||||
}
|
||||
}
|
||||
|
||||
fn async_opaque_type_cycle_error(tcx: TyCtxt<'_>, span: Span) -> ErrorGuaranteed {
|
||||
struct_span_err!(tcx.dcx(), span, E0733, "recursion in an `async fn` requires boxing")
|
||||
.span_label(span, "recursive `async fn`")
|
||||
|
|
|
@ -75,7 +75,6 @@ pub use check::check_abi;
|
|||
|
||||
use std::num::NonZeroU32;
|
||||
|
||||
use check::check_mod_item_types;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::ErrorGuaranteed;
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
|
||||
|
@ -110,7 +109,6 @@ pub fn provide(providers: &mut Providers) {
|
|||
wfcheck::provide(providers);
|
||||
*providers = Providers {
|
||||
adt_destructor,
|
||||
check_mod_item_types,
|
||||
region_scope_tree,
|
||||
collect_return_position_impl_trait_in_trait_tys,
|
||||
compare_impl_const: compare_impl_item::compare_impl_const_raw,
|
||||
|
|
|
@ -172,7 +172,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
|||
item.name = ? tcx.def_path_str(def_id)
|
||||
);
|
||||
|
||||
match item.kind {
|
||||
let res = match item.kind {
|
||||
// Right now we check that every default trait implementation
|
||||
// has an implementation of itself. Basically, a case like:
|
||||
//
|
||||
|
@ -271,7 +271,11 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
|
|||
}
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
};
|
||||
|
||||
crate::check::check::check_item_type(tcx, def_id);
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<(), ErrorGuaranteed> {
|
||||
|
@ -1909,7 +1913,11 @@ fn check_mod_type_wf(tcx: TyCtxt<'_>, module: LocalModDefId) -> Result<(), Error
|
|||
let mut res = items.par_items(|item| tcx.ensure().check_well_formed(item.owner_id));
|
||||
res = res.and(items.par_impl_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
|
||||
res = res.and(items.par_trait_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
|
||||
res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)))
|
||||
res = res.and(items.par_foreign_items(|item| tcx.ensure().check_well_formed(item.owner_id)));
|
||||
if module == LocalModDefId::CRATE_DEF_ID {
|
||||
super::entry::check_for_entry_fn(tcx);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn error_392(tcx: TyCtxt<'_>, span: Span, param_name: Symbol) -> DiagnosticBuilder<'_> {
|
||||
|
|
|
@ -200,18 +200,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
|
|||
})?;
|
||||
}
|
||||
|
||||
let errs = tcx.sess.time("wf_checking", || {
|
||||
tcx.sess.time("wf_checking", || {
|
||||
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
|
||||
});
|
||||
|
||||
// NOTE: This is copy/pasted in librustdoc/core.rs and should be kept in sync.
|
||||
tcx.sess.time("item_types_checking", || {
|
||||
tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module))
|
||||
});
|
||||
|
||||
// HACK: `check_mod_type_wf` may spuriously emit errors due to `span_delayed_bug`, even if
|
||||
// those errors only actually get emitted in `check_mod_item_types`.
|
||||
errs?;
|
||||
})?;
|
||||
|
||||
if tcx.features().rustc_attrs {
|
||||
tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue