diff options
| author | bors <bors@rust-lang.org> | 2024-03-07 10:18:00 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-03-07 10:18:00 +0000 |
| commit | 8c9a75b3238b66592779d6b240dbf78eacefebb8 (patch) | |
| tree | dd28c4ae58120ef9323a862d0a2432a17a01f1af /compiler | |
| parent | 51f483944db3675eba6fd82e0c2cc2b57b04a4e0 (diff) | |
| parent | 8206cffc48b77886e18ecdf22e8762aaaa792eec (diff) | |
| download | rust-8c9a75b3238b66592779d6b240dbf78eacefebb8.tar.gz rust-8c9a75b3238b66592779d6b240dbf78eacefebb8.zip | |
Auto merge of #121154 - oli-obk:track_errors11, r=estebank
Merge `check_mod_impl_wf` and `check_mod_type_wf` This still causes some funny diagnostics, but I'm not sure they can be fixed without a larger change, which I'd like to avoid here. Reducing the number of times we iterate over the same items at this high level helps avoid parallel-compiler bottlenecks.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/wfcheck.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/impl_wf_check.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/lib.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/query/mod.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_traits/src/codegen.rs | 9 |
6 files changed, 34 insertions, 37 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index bec7b7bd974..8d457da89e8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -248,6 +248,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); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 9d7866fe3e0..caa85092415 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -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}; @@ -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( diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 7cb103626da..77c4ff382b9 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -153,7 +153,6 @@ 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); } @@ -171,9 +170,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { } 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); @@ -181,19 +180,12 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { // 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)?; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ebfdf8aa197..a8c0c3999f2 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -955,11 +955,6 @@ 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 diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 83ee1d8bdcb..18abc5d22b7 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2593,10 +2593,19 @@ 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, + }; + + // Taint the resolution in case of errors to prevent follow up errors in typeck + self.r.record_partial_res(param.id, PartialRes::new(Res::Err)); + rib.bindings.insert(ident, Res::Err); continue; } Entry::Vacant(entry) => { diff --git a/compiler/rustc_traits/src/codegen.rs b/compiler/rustc_traits/src/codegen.rs index f3fae63ecc7..b2b5c6cd909 100644 --- a/compiler/rustc_traits/src/codegen.rs +++ b/compiler/rustc_traits/src/codegen.rs @@ -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, @@ -72,6 +72,13 @@ 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() { + // Unused lifetimes on an impl get replaced with inference vars, but never resolved, + // causing the return value of a query to contain inference vars. We do not have a concept + // for this and will in fact ICE in stable hashing of the return value. So bail out instead. + infcx.tcx.dcx().has_errors().unwrap(); + return Err(CodegenObligationError::FulfillmentError); + } Ok(&*tcx.arena.alloc(impl_source)) } |
