Rollup merge of #130764 - compiler-errors:inherent, r=estebank

Separate collection of crate-local inherent impls from error tracking

#119895 changed the return type of the `crate_inherent_impls` query from `CrateInherentImpls` to `Result<CrateInherentImpls, ErrorGuaranteed>` to avoid needing to use the non-parallel-friendly `track_errors()` to track if an error was reporting from within the query... This was mostly fine until #121113, which stopped halting compilation when we hit an `Err(ErrorGuaranteed)` in the `crate_inherent_impls` query.

Thus we proceed onwards to typeck, and since a return type of `Result<CrateInherentImpls, ErrorGuaranteed>` means that the query can *either* return one of "the list inherent impls" or "error has been reported", later on when we want to assemble method or associated item candidates for inherent impls, we were just treating any `Err(ErrorGuaranteed)` return value as if Rust had no inherent impls defined anywhere at all! This leads to basically every inherent method call failing with an error, lol, which was reported in #127798.

This PR changes the `crate_inherent_impls` query to return `(CrateInherentImpls, Result<(), ErrorGuaranteed>)`, i.e. returning the inherent impls collected *and* whether an error was reported in the query itself. It firewalls the latter part of that query into a new `crate_inherent_impls_validity_check` just for the `ensure()` call.

This fixes #127798.
This commit is contained in:
Trevor Gross 2024-09-24 19:47:50 -04:00 committed by GitHub
commit e691743119
6 changed files with 5 additions and 14 deletions

View File

@ -386,7 +386,6 @@ fn has_unsafe<'tcx>(cx: &LateContext<'tcx>, item: &'tcx Item<'_>) -> bool {
.tcx .tcx
.inherent_impls(def.did()) .inherent_impls(def.did())
.into_iter() .into_iter()
.flatten()
.map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local())) .map(|imp_did| cx.tcx.hir().expect_item(imp_did.expect_local()))
.any(|imp| has_unsafe(cx, imp)) .any(|imp| has_unsafe(cx, imp))
{ {

View File

@ -51,9 +51,7 @@ fn check_crate_post(&mut self, cx: &LateContext<'tcx>) {
// List of spans to lint. (lint_span, first_span) // List of spans to lint. (lint_span, first_span)
let mut lint_spans = Vec::new(); let mut lint_spans = Vec::new();
let Ok(impls) = cx.tcx.crate_inherent_impls(()) else { let (impls, _) = cx.tcx.crate_inherent_impls(());
return;
};
for (&id, impl_ids) in &impls.inherent_impls { for (&id, impl_ids) in &impls.inherent_impls {
if impl_ids.len() < 2 if impl_ids.len() < 2

View File

@ -448,7 +448,6 @@ fn check_for_is_empty(
.tcx .tcx
.inherent_impls(impl_ty) .inherent_impls(impl_ty)
.into_iter() .into_iter()
.flatten()
.flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty)) .flat_map(|&id| cx.tcx.associated_items(id).filter_by_name_unhygienic(is_empty))
.find(|item| item.kind == AssocKind::Fn); .find(|item| item.kind == AssocKind::Fn);
@ -616,7 +615,7 @@ fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
/// Checks the inherent impl's items for an `is_empty(self)` method. /// Checks the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool { fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
let is_empty = sym!(is_empty); let is_empty = sym!(is_empty);
cx.tcx.inherent_impls(id).into_iter().flatten().any(|imp| { cx.tcx.inherent_impls(id).into_iter().any(|imp| {
cx.tcx cx.tcx
.associated_items(*imp) .associated_items(*imp)
.filter_by_name_unhygienic(is_empty) .filter_by_name_unhygienic(is_empty)

View File

@ -78,7 +78,6 @@ fn check_unwrap_or_default(
cx.tcx cx.tcx
.inherent_impls(adt_def.did()) .inherent_impls(adt_def.did())
.into_iter() .into_iter()
.flatten()
.flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg)) .flat_map(|impl_id| cx.tcx.associated_items(impl_id).filter_by_name_unhygienic(sugg))
.find_map(|assoc| { .find_map(|assoc| {
if assoc.fn_has_self_parameter if assoc.fn_has_self_parameter

View File

@ -589,14 +589,11 @@ fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<It
"f32" => SimplifiedType::Float(FloatTy::F32), "f32" => SimplifiedType::Float(FloatTy::F32),
"f64" => SimplifiedType::Float(FloatTy::F64), "f64" => SimplifiedType::Float(FloatTy::F64),
_ => { _ => {
return Result::<&[_], rustc_errors::ErrorGuaranteed>::Ok(&[]) return [].iter().copied();
.into_iter()
.flatten()
.copied();
}, },
}; };
tcx.incoherent_impls(ty).into_iter().flatten().copied() tcx.incoherent_impls(ty).into_iter().copied()
} }
fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> { fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
@ -721,7 +718,6 @@ fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '
let inherent_impl_children = tcx let inherent_impl_children = tcx
.inherent_impls(def_id) .inherent_impls(def_id)
.into_iter() .into_iter()
.flatten()
.flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment)); .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
let direct_children = item_children_by_name(tcx, def_id, segment); let direct_children = item_children_by_name(tcx, def_id, segment);

View File

@ -1316,7 +1316,7 @@ pub fn deref_chain<'cx, 'tcx>(cx: &'cx LateContext<'tcx>, ty: Ty<'tcx>) -> impl
/// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`. /// If you need this, you should wrap this call in `clippy_utils::ty::deref_chain().any(...)`.
pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> { pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_name: Symbol) -> Option<&'a AssocItem> {
if let Some(ty_did) = ty.ty_adt_def().map(AdtDef::did) { if let Some(ty_did) = ty.ty_adt_def().map(AdtDef::did) {
cx.tcx.inherent_impls(ty_did).into_iter().flatten().find_map(|&did| { cx.tcx.inherent_impls(ty_did).into_iter().find_map(|&did| {
cx.tcx cx.tcx
.associated_items(did) .associated_items(did)
.filter_by_name_unhygienic(method_name) .filter_by_name_unhygienic(method_name)