Skip to content

Commit

Permalink
Auto merge of rust-lang#117213 - oli-obk:check_item_type_cleanup, r=<…
Browse files Browse the repository at this point in the history
…try>

 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.
  • Loading branch information
bors committed Oct 26, 2023
2 parents 056f5b0 + 3cd5671 commit 9eac8ba
Show file tree
Hide file tree
Showing 33 changed files with 358 additions and 277 deletions.
73 changes: 29 additions & 44 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::Node;
use rustc_infer::infer::outlives::env::OutlivesEnvironment;
use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
Expand Down Expand Up @@ -201,8 +201,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.sess.delay_span_bug(item.span, "expected opaque item");
return;
Expand Down Expand Up @@ -443,40 +443,35 @@ 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) {
if of_trait && let Some(impl_trait_ref) = tcx.impl_trait_ref(def_id) {
check_impl_items_against_trait(
tcx,
id.owner_id.def_id,
def_id,
impl_trait_ref.instantiate_identity(),
);
check_on_unimplemented(tcx, id);
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 {
Expand All @@ -485,43 +480,43 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
fn_maybe_err(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),
);
}
_ => {}
}
}
}
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().get_by_def_id(fn_def_id)
&& let (_, hir::TraitFn::Required(..)) = trait_item.expect_fn()
{
// 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;
};
Expand Down Expand Up @@ -592,19 +587,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>(
Expand Down Expand Up @@ -1314,16 +1309,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.sess, span, E0733, "recursion in an `async fn` requires boxing")
.span_label(span, "recursive `async fn`")
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::ops::Not;
use super::check_function_signature;
use crate::errors;

pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>) {
pub(crate) fn check_for_entry_fn(tcx: TyCtxt<'_>, (): ()) {
match tcx.entry_fn(()) {
Some((def_id, EntryFnType::Main { .. })) => check_main_fn_ty(tcx, def_id),
Some((def_id, EntryFnType::Start)) => check_start_fn_ty(tcx, def_id),
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub use check::check_abi;

use std::num::NonZeroU32;

use check::check_mod_item_types;
use entry::check_for_entry_fn;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{pluralize, struct_span_err, Diagnostic, DiagnosticBuilder};
use rustc_hir::def_id::{DefId, LocalDefId};
Expand Down Expand Up @@ -110,7 +110,7 @@ pub fn provide(providers: &mut Providers) {
wfcheck::provide(providers);
*providers = Providers {
adt_destructor,
check_mod_item_types,
check_for_entry_fn,
region_scope_tree,
collect_return_position_impl_trait_in_trait_tys,
compare_impl_const: compare_impl_item::compare_impl_const_raw,
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,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:
//
Expand Down Expand Up @@ -268,7 +268,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> {
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
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))
});
tcx.sess.time("entry_fn_checks", || tcx.ensure().check_for_entry_fn(()));

// HACK: `check_mod_type_wf` may spuriously emit errors due to `delay_span_bug`, even if those errors
// only actually get emitted in `check_mod_item_types`.
// HACK: `check_for_entry_fn` wants to report its errors even if `check_mod_type_wf` has errored.
errs?;

if tcx.features().rustc_attrs {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,8 +935,8 @@ rustc_queries! {
desc { |tcx| "checking naked functions in {}", describe_as_module(key, tcx) }
}

query check_mod_item_types(key: LocalModDefId) -> () {
desc { |tcx| "checking item types in {}", describe_as_module(key, tcx) }
query check_for_entry_fn(key: ()) -> () {
desc { |_tcx| "checking entry functions" }
}

query check_mod_privacy(key: LocalModDefId) -> () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
error[E0277]: the trait bound `(T, U): Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:22:5
|
LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
|
help: this trait has no implementations, consider adding one
--> $DIR/associated-types-no-suitable-supertrait.rs:12:1
|
LL | trait Get {
| ^^^^^^^^^

error[E0277]: the trait bound `(T, U): Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:22:40
|
Expand All @@ -21,18 +33,6 @@ help: consider further restricting `Self`
LL | fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) where Self: Get {}
| +++++++++++++++

error[E0277]: the trait bound `(T, U): Get` is not satisfied
--> $DIR/associated-types-no-suitable-supertrait.rs:22:5
|
LL | fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
|
help: this trait has no implementations, consider adding one
--> $DIR/associated-types-no-suitable-supertrait.rs:12:1
|
LL | trait Get {
| ^^^^^^^^^

error: aborting due to 3 previous errors

For more information about this error, try `rustc --explain E0277`.
4 changes: 2 additions & 2 deletions tests/ui/associated-types/defaults-cyclic-fail-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ impl Tr for u32 {
// ...but not in an impl that redefines one of the types.
impl Tr for bool {
type A = Box<Self::B>;
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::A == _`
}
// (the error is shown twice for some reason)

impl Tr for usize {
type B = &'static Self::A;
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::B == _`
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/defaults-cyclic-fail-1.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
error[E0275]: overflow evaluating the requirement `<bool as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-1.rs:26:14
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
error[E0275]: overflow evaluating the requirement `<usize as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-1.rs:32:14
|
LL | type B = &'static Self::A;
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/defaults-cyclic-fail-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ impl Tr for u32 {

impl Tr for bool {
type A = Box<Self::B>;
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::B == _`
//~^ ERROR overflow evaluating the requirement `<bool as Tr>::A == _`
}
// (the error is shown twice for some reason)

impl Tr for usize {
type B = &'static Self::A;
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::A == _`
//~^ ERROR overflow evaluating the requirement `<usize as Tr>::B == _`
}

fn main() {
Expand Down
4 changes: 2 additions & 2 deletions tests/ui/associated-types/defaults-cyclic-fail-2.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
error[E0275]: overflow evaluating the requirement `<bool as Tr>::B == _`
error[E0275]: overflow evaluating the requirement `<bool as Tr>::A == _`
--> $DIR/defaults-cyclic-fail-2.rs:27:14
|
LL | type A = Box<Self::B>;
| ^^^^^^^^^^^^

error[E0275]: overflow evaluating the requirement `<usize as Tr>::A == _`
error[E0275]: overflow evaluating the requirement `<usize as Tr>::B == _`
--> $DIR/defaults-cyclic-fail-2.rs:33:14
|
LL | type B = &'static Self::A;
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/async-await/issue-66312.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
error[E0308]: mismatched types
--> $DIR/issue-66312.rs:9:8
|
LL | if x.is_some() {
| ^^^^^^^^^^^ expected `bool`, found `()`

error[E0307]: invalid `self` parameter type: T
--> $DIR/issue-66312.rs:4:22
|
Expand All @@ -7,12 +13,6 @@ LL | fn is_some(self: T);
= note: type of `self` must be `Self` or a type that dereferences to it
= help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)

error[E0308]: mismatched types
--> $DIR/issue-66312.rs:9:8
|
LL | if x.is_some() {
| ^^^^^^^^^^^ expected `bool`, found `()`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0307, E0308.
Expand Down
3 changes: 3 additions & 0 deletions tests/ui/const-generics/issues/issue-83765.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
trait TensorDimension {
const DIM: usize;
//~^ ERROR cycle detected when resolving instance
//~| ERROR cycle detected when resolving instance
// FIXME Given the current state of the compiler its expected that we cycle here,
// but the cycle is still wrong.
const ISSCALAR: bool = Self::DIM == 0;
Expand Down Expand Up @@ -79,6 +80,7 @@ impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> TensorSi
for BMap<'a, R, T, F, DIM>
{
fn size(&self) -> [usize; DIM] {
//~^ ERROR: method not compatible with trait
self.reference.size()
}
}
Expand All @@ -88,6 +90,7 @@ impl<'a, R, T: Broadcastable, F: Fn(T::Element) -> R, const DIM: usize> Broadcas
{
type Element = R;
fn bget(&self, index: [usize; DIM]) -> Option<Self::Element> {
//~^ ERROR: method not compatible with trait
self.reference.bget(index).map(&self.closure)
}
}
Expand Down
Loading

0 comments on commit 9eac8ba

Please sign in to comment.