Skip to content

Commit

Permalink
Auto merge of #121500 - oli-obk:track_errors12, r=<try>
Browse files Browse the repository at this point in the history
Merge `collect_mod_item_types` query into `check_well_formed`

follow-up to #121154

r? `@ghost`
  • Loading branch information
bors committed Feb 23, 2024
2 parents 6dadb6e + 62bc4bd commit f7e3a77
Show file tree
Hide file tree
Showing 121 changed files with 1,737 additions and 1,283 deletions.
27 changes: 22 additions & 5 deletions compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use crate::autoderef::Autoderef;
use crate::collect::CollectItemTypesVisitor;
use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
use crate::errors;

use hir::intravisit::Visitor;
use rustc_ast as ast;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, ErrorGuaranteed};
Expand Down Expand Up @@ -225,6 +227,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
?item.owner_id,
item.name = ? tcx.def_path_str(def_id)
);
CollectItemTypesVisitor { tcx }.visit_item(item);

let res = match item.kind {
// Right now we check that every default trait implementation
Expand All @@ -248,6 +251,8 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
let header = tcx.impl_trait_header(def_id);
let is_auto = header
.is_some_and(|header| tcx.trait_is_auto(header.skip_binder().trait_ref.def_id));

crate::impl_wf_check::check_impl_wf(tcx, def_id)?;
let mut res = Ok(());
if let (hir::Defaultness::Default { .. }, true) = (impl_.defaultness, is_auto) {
let sp = impl_.of_trait.as_ref().map_or(item.span, |t| t.path.span);
Expand Down Expand Up @@ -334,9 +339,14 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<()
res
}

fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<(), ErrorGuaranteed> {
fn check_foreign_item<'tcx>(
tcx: TyCtxt<'tcx>,
item: &'tcx hir::ForeignItem<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let def_id = item.owner_id.def_id;

CollectItemTypesVisitor { tcx }.visit_foreign_item(item);

debug!(
?item.owner_id,
item.name = ? tcx.def_path_str(def_id)
Expand All @@ -353,12 +363,14 @@ fn check_foreign_item(tcx: TyCtxt<'_>, item: &hir::ForeignItem<'_>) -> Result<()
}
}

fn check_trait_item(
tcx: TyCtxt<'_>,
trait_item: &hir::TraitItem<'_>,
fn check_trait_item<'tcx>(
tcx: TyCtxt<'tcx>,
trait_item: &'tcx hir::TraitItem<'tcx>,
) -> Result<(), ErrorGuaranteed> {
let def_id = trait_item.owner_id.def_id;

CollectItemTypesVisitor { tcx }.visit_trait_item(trait_item);

let (method_sig, span) = match trait_item.kind {
hir::TraitItemKind::Fn(ref sig, _) => (Some(sig), trait_item.span),
hir::TraitItemKind::Type(_bounds, Some(ty)) => (None, ty.span),
Expand Down Expand Up @@ -895,7 +907,12 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem
}
}

fn check_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> Result<(), ErrorGuaranteed> {
fn check_impl_item<'tcx>(
tcx: TyCtxt<'tcx>,
impl_item: &'tcx hir::ImplItem<'tcx>,
) -> Result<(), ErrorGuaranteed> {
CollectItemTypesVisitor { tcx }.visit_impl_item(impl_item);

let (method_sig, span) = match impl_item.kind {
hir::ImplItemKind::Fn(ref sig, _) => (Some(sig), impl_item.span),
// Constrain binding and overflow error spans to `<Ty>` in `type foo = <Ty>`.
Expand Down
26 changes: 16 additions & 10 deletions compiler/rustc_hir_analysis/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_data_structures::unord::UnordMap;
use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{GenericParamKind, Node};
use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
Expand Down Expand Up @@ -52,11 +52,6 @@ mod resolve_bound_vars;
mod type_of;

///////////////////////////////////////////////////////////////////////////
// Main entry point

fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
tcx.hir().visit_item_likes_in_module(module_def_id, &mut CollectItemTypesVisitor { tcx });
}

pub fn provide(providers: &mut Providers) {
resolve_bound_vars::provide(providers);
Expand All @@ -82,7 +77,6 @@ pub fn provide(providers: &mut Providers) {
impl_trait_header,
coroutine_kind,
coroutine_for_closure,
collect_mod_item_types,
is_type_alias_impl_trait,
find_field,
..*providers
Expand Down Expand Up @@ -155,8 +149,8 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector {
}
}

struct CollectItemTypesVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
pub struct CollectItemTypesVisitor<'tcx> {
pub tcx: TyCtxt<'tcx>,
}

/// If there are any placeholder types (`_`), emit an error explaining that this is not allowed
Expand Down Expand Up @@ -1025,7 +1019,19 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {

let is_anonymous = item.ident.name == kw::Empty;
let repr = if is_anonymous {
tcx.adt_def(tcx.local_parent(def_id)).repr()
let mut def_id = def_id;
loop {
def_id = tcx.local_parent(def_id);
if let Node::Item(_) = tcx.hir_node_by_def_id(def_id) {
break;
} else {
tcx.dcx().span_delayed_bug(
tcx.def_span(def_id),
"invalid anonymous adt position, already got rejected in ast validation",
);
}
}
tcx.adt_def(def_id).repr()
} else {
tcx.repr_options_of_def(def_id)
};
Expand Down
22 changes: 7 additions & 15 deletions compiler/rustc_hir_analysis/src/impl_wf_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ use min_specialization::check_min_specialization;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::{codes::*, struct_span_code_err};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{LocalDefId, LocalModDefId};
use rustc_middle::query::Providers;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, Span, Symbol};

Expand Down Expand Up @@ -51,23 +50,16 @@ mod min_specialization;
/// impl<'a> Trait<Foo> for Bar { type X = &'a i32; }
/// // ^ 'a is unused and appears in assoc type, error
/// ```
fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) -> Result<(), ErrorGuaranteed> {
pub fn check_impl_wf(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
let min_specialization = tcx.features().min_specialization;
let module = tcx.hir_module_items(module_def_id);
let mut res = Ok(());
for id in module.items() {
if matches!(tcx.def_kind(id.owner_id), DefKind::Impl { .. }) {
res = res.and(enforce_impl_params_are_constrained(tcx, id.owner_id.def_id));
if min_specialization {
res = res.and(check_min_specialization(tcx, id.owner_id.def_id));
}
}
debug_assert!(matches!(tcx.def_kind(impl_def_id), DefKind::Impl { .. }));
res = res.and(enforce_impl_params_are_constrained(tcx, impl_def_id));
if min_specialization {
res = res.and(check_min_specialization(tcx, impl_def_id));
}
res
}

pub fn provide(providers: &mut Providers) {
*providers = Providers { check_mod_impl_wf, ..*providers };
res
}

fn enforce_impl_params_are_constrained(
Expand Down
22 changes: 4 additions & 18 deletions compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,47 +153,33 @@ pub fn provide(providers: &mut Providers) {
check_unused::provide(providers);
variance::provide(providers);
outlives::provide(providers);
impl_wf_check::provide(providers);
hir_wf_check::provide(providers);
}

pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
let _prof_timer = tcx.sess.timer("type_check_crate");

// this ensures that later parts of type checking can assume that items
// have valid types and not error
tcx.sess.time("type_collecting", || {
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
});

if tcx.features().rustc_attrs {
tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?;
}

tcx.sess.time("coherence_checking", || {
// Check impls constrain their parameters
let res =
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_impl_wf(module));
tcx.hir().par_for_each_module(|module| {
let _ = tcx.ensure().check_mod_type_wf(module);
});

for &trait_def_id in tcx.all_local_trait_impls(()).keys() {
let _ = tcx.ensure().coherent_trait(trait_def_id);
}
// these queries are executed for side-effects (error reporting):
let _ = tcx.ensure().crate_inherent_impls(());
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
res
})?;
});

if tcx.features().rustc_attrs {
tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?;
}

tcx.sess.time("wf_checking", || {
tcx.hir().par_for_each_module(|module| {
let _ = tcx.ensure().check_mod_type_wf(module);
})
});

if tcx.features().rustc_attrs {
collect::test_opaque_hidden_types(tcx)?;
}
Expand Down
10 changes: 1 addition & 9 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,7 @@ rustc_queries! {
desc { |tcx| "computing the variances of `{}`", tcx.def_path_str(def_id) }
cache_on_disk_if { def_id.is_local() }
separate_provide_extern
cycle_delay_bug
}

/// Maps from thee `DefId` of a type to its (inferred) outlives.
Expand Down Expand Up @@ -964,20 +965,11 @@ rustc_queries! {
desc { |tcx| "checking deathness of variables in {}", describe_as_module(key, tcx) }
}

query check_mod_impl_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking that impls are well-formed in {}", describe_as_module(key, tcx) }
ensure_forwards_result_if_red
}

query check_mod_type_wf(key: LocalModDefId) -> Result<(), ErrorGuaranteed> {
desc { |tcx| "checking that types are well-formed in {}", describe_as_module(key, tcx) }
ensure_forwards_result_if_red
}

query collect_mod_item_types(key: LocalModDefId) {
desc { |tcx| "collecting item types in {}", describe_as_module(key, tcx) }
}

/// Caches `CoerceUnsized` kinds for impls on custom types.
query coerce_unsized_info(key: DefId) -> Result<ty::adjustment::CoerceUnsizedInfo, ErrorGuaranteed> {
desc { |tcx| "computing CoerceUnsized info for `{}`", tcx.def_path_str(key) }
Expand Down
21 changes: 21 additions & 0 deletions compiler/rustc_middle/src/values.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,27 @@ impl<'tcx> Value<TyCtxt<'tcx>> for ty::EarlyBinder<ty::Binder<'_, ty::FnSig<'_>>
}
}

impl<'tcx> Value<TyCtxt<'tcx>> for &[ty::Variance] {
fn from_cycle_error(
tcx: TyCtxt<'tcx>,
cycle_error: &CycleError,
_guar: ErrorGuaranteed,
) -> Self {
if let Some(frame) = cycle_error.cycle.get(0)
&& frame.query.dep_kind == dep_kinds::variances_of
&& let Some(def_id) = frame.query.def_id
{
let n = tcx.generics_of(def_id).params.len();
vec![ty::Variance::Bivariant; n].leak()
} else {
span_bug!(
cycle_error.usage.as_ref().unwrap().0,
"only `variances_of` returns `&[ty::Variance]`"
);
}
}
}

// Take a cycle of `Q` and try `try_cycle` on every permutation, falling back to `otherwise`.
fn search_for_cycle_permutation<Q, T>(
cycle: &[Q],
Expand Down
16 changes: 12 additions & 4 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2597,10 +2597,18 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
let span = *entry.get();
let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
self.report_error(param.ident.span, err);
if let GenericParamKind::Lifetime = param.kind {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
}
let rib = match param.kind {
GenericParamKind::Lifetime => {
// Record lifetime res, so lowering knows there is something fishy.
self.record_lifetime_param(param.id, LifetimeRes::Error);
continue;
}
GenericParamKind::Type { .. } => &mut function_type_rib,
GenericParamKind::Const { .. } => &mut function_value_rib,
};

self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
rib.bindings.insert(ident, Res::Err);
continue;
}
Entry::Vacant(entry) => {
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_traits/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{FulfillmentErrorCode, TraitEngineExt as _};
use rustc_middle::traits::CodegenObligationError;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
use rustc_trait_selection::traits::{
ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
Expand Down Expand Up @@ -72,6 +72,10 @@ pub fn codegen_select_candidate<'tcx>(

let impl_source = infcx.resolve_vars_if_possible(impl_source);
let impl_source = infcx.tcx.erase_regions(impl_source);
if impl_source.has_infer() {
infcx.tcx.dcx().has_errors().unwrap();
return Err(CodegenObligationError::FulfillmentError);
}

Ok(&*tcx.arena.alloc(impl_source))
}
11 changes: 0 additions & 11 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,21 +315,10 @@ pub(crate) fn run_global_ctxt(
// typeck function bodies or run the default rustc lints.
// (see `override_queries` in the `config`)

// HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
// and might break if queries change their assumptions in the future.
tcx.sess.time("type_collecting", || {
tcx.hir().for_each_module(|module| tcx.ensure().collect_mod_item_types(module))
});

// NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes.
let _ = tcx.sess.time("wf_checking", || {
tcx.hir().try_par_for_each_module(|module| tcx.ensure().check_mod_type_wf(module))
});
tcx.sess.time("item_types_checking", || {
tcx.hir().for_each_module(|module| {
let _ = tcx.ensure().check_mod_type_wf(module);
});
});

if let Some(guar) = tcx.dcx().has_errors() {
return Err(guar);
Expand Down
2 changes: 1 addition & 1 deletion tests/rustdoc-ui/not-wf-ambiguous-normalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ struct DefaultAllocator;
// `<DefaultAllocator as Allocator>::Buffer` to be ambiguous,
// which caused an ICE with `-Znormalize-docs`.
impl<T> Allocator for DefaultAllocator {
//~^ ERROR: type annotations needed
//~^ ERROR: the type parameter `T` is not constrained
type Buffer = ();
}

Expand Down
8 changes: 4 additions & 4 deletions tests/rustdoc-ui/not-wf-ambiguous-normalization.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
error[E0282]: type annotations needed
--> $DIR/not-wf-ambiguous-normalization.rs:14:23
error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
--> $DIR/not-wf-ambiguous-normalization.rs:14:6
|
LL | impl<T> Allocator for DefaultAllocator {
| ^^^^^^^^^^^^^^^^ cannot infer type for type parameter `T`
| ^ unconstrained type parameter

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0282`.
For more information about this error, try `rustc --explain E0207`.
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,11 @@ note: ...which requires computing normalized predicates of `Foo`...
LL | struct Foo {
| ^^^^^^^^^^
= note: ...which again requires computing predicates of `Foo`, completing the cycle
note: cycle used when collecting item types in top-level module
--> $DIR/cycle-iat-inside-of-adt.rs:3:1
note: cycle used when checking that `Foo` is well-formed
--> $DIR/cycle-iat-inside-of-adt.rs:7:1
|
LL | / #![feature(inherent_associated_types)]
LL | | #![allow(incomplete_features)]
LL | | // FIXME(inherent_associated_types): This should pass.
LL | |
... |
LL | |
LL | | fn main() {}
| |____________^
LL | struct Foo {
| ^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information

error: aborting due to 1 previous error
Expand Down
Loading

0 comments on commit f7e3a77

Please sign in to comment.