Skip to content

Commit

Permalink
Separate collection of crate-local inherent impls from error reporting
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 24, 2024
1 parent 11e760b commit cfb8419
Show file tree
Hide file tree
Showing 22 changed files with 127 additions and 125 deletions.
34 changes: 18 additions & 16 deletions compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,38 @@ use crate::errors;
pub(crate) fn crate_inherent_impls(
tcx: TyCtxt<'_>,
(): (),
) -> Result<&'_ CrateInherentImpls, ErrorGuaranteed> {
) -> (&'_ CrateInherentImpls, Result<(), ErrorGuaranteed>) {
let mut collect = InherentCollect { tcx, impls_map: Default::default() };

let mut res = Ok(());
for id in tcx.hir().items() {
res = res.and(collect.check_item(id));
}
res?;
Ok(tcx.arena.alloc(collect.impls_map))

(tcx.arena.alloc(collect.impls_map), res)
}

pub(crate) fn crate_incoherent_impls(
pub(crate) fn crate_inherent_impls_validity_check(
tcx: TyCtxt<'_>,
simp: SimplifiedType,
) -> Result<&[DefId], ErrorGuaranteed> {
let crate_map = tcx.crate_inherent_impls(())?;
Ok(tcx.arena.alloc_from_iter(
(): (),
) -> Result<(), ErrorGuaranteed> {
tcx.crate_inherent_impls(()).1
}

pub(crate) fn crate_incoherent_impls(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
let (crate_map, _) = tcx.crate_inherent_impls(());
tcx.arena.alloc_from_iter(
crate_map.incoherent_impls.get(&simp).unwrap_or(&Vec::new()).iter().map(|d| d.to_def_id()),
))
)
}

/// On-demand query: yields a vector of the inherent impls for a specific type.
pub(crate) fn inherent_impls(
tcx: TyCtxt<'_>,
ty_def_id: LocalDefId,
) -> Result<&[DefId], ErrorGuaranteed> {
let crate_map = tcx.crate_inherent_impls(())?;
Ok(match crate_map.inherent_impls.get(&ty_def_id) {
pub(crate) fn inherent_impls(tcx: TyCtxt<'_>, ty_def_id: LocalDefId) -> &[DefId] {
let (crate_map, _) = tcx.crate_inherent_impls(());
match crate_map.inherent_impls.get(&ty_def_id) {
Some(v) => &v[..],
None => &[],
})
}
}

struct InherentCollect<'tcx> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> {
return Ok(());
}

let impls = self.tcx.inherent_impls(id.owner_id)?;

let impls = self.tcx.inherent_impls(id.owner_id);
let overlap_mode = OverlapMode::get(self.tcx, id.owner_id.to_def_id());

let impls_items = impls
Expand Down
6 changes: 5 additions & 1 deletion compiler/rustc_hir_analysis/src/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,10 @@ fn enforce_empty_impls_for_marker_traits(

pub(crate) fn provide(providers: &mut Providers) {
use self::builtin::coerce_unsized_info;
use self::inherent_impls::{crate_incoherent_impls, crate_inherent_impls, inherent_impls};
use self::inherent_impls::{
crate_incoherent_impls, crate_inherent_impls, crate_inherent_impls_validity_check,
inherent_impls,
};
use self::inherent_impls_overlap::crate_inherent_impls_overlap_check;
use self::orphan::orphan_check_impl;

Expand All @@ -133,6 +136,7 @@ pub(crate) fn provide(providers: &mut Providers) {
crate_inherent_impls,
crate_incoherent_impls,
inherent_impls,
crate_inherent_impls_validity_check,
crate_inherent_impls_overlap_check,
coerce_unsized_info,
orphan_check_impl,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
..
}) = node
&& let Some(ty_def_id) = qself_ty.ty_def_id()
&& let Ok([inherent_impl]) = tcx.inherent_impls(ty_def_id)
&& let [inherent_impl] = tcx.inherent_impls(ty_def_id)
&& let name = format!("{ident2}_{ident3}")
&& let Some(ty::AssocItem { kind: ty::AssocKind::Fn, .. }) = tcx
.associated_items(inherent_impl)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}

let candidates: Vec<_> = tcx
.inherent_impls(adt_did)?
.inherent_impls(adt_did)
.iter()
.filter_map(|&impl_| {
let (item, scope) =
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) {
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_validity_check(());
let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
});

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2126,7 +2126,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.tcx
.inherent_impls(def_id)
.into_iter()
.flatten()
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
// Only assoc fn with no receivers.
.filter(|item| {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_typeck/src/method/probe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -728,13 +728,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
let Some(simp) = simplify_type(self.tcx, self_ty, TreatParams::InstantiateWithInfer) else {
bug!("unexpected incoherent type: {:?}", self_ty)
};
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter().flatten() {
for &impl_def_id in self.tcx.incoherent_impls(simp).into_iter() {
self.assemble_inherent_impl_probe(impl_def_id);
}
}

fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: DefId) {
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter().flatten();
let impl_def_ids = self.tcx.at(self.span).inherent_impls(def_id).into_iter();
for &impl_def_id in impl_def_ids {
self.assemble_inherent_impl_probe(impl_def_id);
}
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,7 +680,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx
.inherent_impls(adt_def.did())
.into_iter()
.flatten()
.any(|def_id| self.associated_value(*def_id, item_name).is_some())
} else {
false
Expand Down Expand Up @@ -1438,7 +1437,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.tcx
.inherent_impls(adt.did())
.into_iter()
.flatten()
.copied()
.filter(|def_id| {
if let Some(assoc) = self.associated_value(*def_id, item_name) {
Expand Down Expand Up @@ -1900,7 +1898,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
call_args: Option<Vec<Ty<'tcx>>>,
) -> Option<Symbol> {
if let ty::Adt(adt, adt_args) = rcvr_ty.kind() {
for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter().flatten() {
for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter() {
for inherent_method in
self.tcx.associated_items(inherent_impl_did).in_definition_order()
{
Expand Down Expand Up @@ -2114,9 +2112,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
return;
};
// FIXME(oli-obk): try out bubbling this error up one level and cancelling the other error in that case.
let Ok(impls) = self.tcx.inherent_impls(adt_def.did()) else { return };
let mut items = impls
let mut items = self
.tcx
.inherent_impls(adt_def.did())
.iter()
.flat_map(|i| self.tcx.associated_items(i).in_definition_order())
// Only assoc fn with no receivers and only if
Expand Down Expand Up @@ -2495,7 +2493,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
.and_then(|simp| {
tcx.incoherent_impls(simp)
.into_iter()
.flatten()
.find_map(|&id| self.associated_value(id, item_name))
})
.is_some()
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ provide! { tcx, def_id, other, cdata,
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
}
associated_item => { cdata.get_associated_item(def_id.index, tcx.sess) }
inherent_impls => { Ok(cdata.get_inherent_implementations_for_type(tcx, def_id.index)) }
inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) }
item_attrs => { tcx.arena.alloc_from_iter(cdata.get_item_attrs(def_id.index, tcx.sess)) }
is_mir_available => { cdata.is_item_mir_available(def_id.index) }
is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
Expand Down Expand Up @@ -393,7 +393,7 @@ provide! { tcx, def_id, other, cdata,
traits => { tcx.arena.alloc_from_iter(cdata.get_traits()) }
trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls()) }
implementations_of_trait => { cdata.get_implementations_of_trait(tcx, other) }
crate_incoherent_impls => { Ok(cdata.get_incoherent_impls(tcx, other)) }
crate_incoherent_impls => { cdata.get_incoherent_impls(tcx, other) }

dep_kind => { cdata.dep_kind }
module_children => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_metadata/src/rmeta/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1540,7 +1540,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}

for (def_id, impls) in &tcx.crate_inherent_impls(()).unwrap().inherent_impls {
for (def_id, impls) in &tcx.crate_inherent_impls(()).0.inherent_impls {
record_defaulted_array!(self.tables.inherent_impls[def_id.to_def_id()] <- impls.iter().map(|def_id| {
assert!(def_id.is_local());
def_id.index
Expand Down Expand Up @@ -2089,7 +2089,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {

let all_impls: Vec<_> = tcx
.crate_inherent_impls(())
.unwrap()
.0
.incoherent_impls
.iter()
.map(|(&simp, impls)| IncoherentImpls {
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/query/erase.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::intrinsics::transmute_unchecked;
use std::mem::MaybeUninit;

use rustc_span::ErrorGuaranteed;

use crate::query::CyclePlaceholder;
use crate::ty::adjustment::CoerceUnsizedInfo;
use crate::ty::{self, Ty};
Expand Down Expand Up @@ -216,6 +218,10 @@ impl<T0, T1> EraseType for (&'_ T0, &'_ [T1]) {
type Result = [u8; size_of::<(&'static (), &'static [()])>()];
}

impl<T0> EraseType for (&'_ T0, Result<(), ErrorGuaranteed>) {
type Result = [u8; size_of::<(&'static (), Result<(), ErrorGuaranteed>)>()];
}

macro_rules! trivial {
($($ty:ty),+ $(,)?) => {
$(
Expand Down
14 changes: 10 additions & 4 deletions compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,13 +881,13 @@ rustc_queries! {
/// Maps a `DefId` of a type to a list of its inherent impls.
/// Contains implementations of methods that are inherent to a type.
/// Methods in these implementations don't need to be exported.
query inherent_impls(key: DefId) -> Result<&'tcx [DefId], ErrorGuaranteed> {
query inherent_impls(key: DefId) -> &'tcx [DefId] {
desc { |tcx| "collecting inherent impls for `{}`", tcx.def_path_str(key) }
cache_on_disk_if { key.is_local() }
separate_provide_extern
}

query incoherent_impls(key: SimplifiedType) -> Result<&'tcx [DefId], ErrorGuaranteed> {
query incoherent_impls(key: SimplifiedType) -> &'tcx [DefId] {
desc { |tcx| "collecting all inherent impls for `{:?}`", key }
}

Expand Down Expand Up @@ -1017,8 +1017,14 @@ rustc_queries! {

/// Gets a complete map from all types to their inherent impls.
/// Not meant to be used directly outside of coherence.
query crate_inherent_impls(k: ()) -> Result<&'tcx CrateInherentImpls, ErrorGuaranteed> {
query crate_inherent_impls(k: ()) -> (&'tcx CrateInherentImpls, Result<(), ErrorGuaranteed>) {
desc { "finding all inherent impls defined in crate" }
}

/// Checks all types in the crate for overlap in their inherent impls. Reports errors.
/// Not meant to be used directly outside of coherence.
query crate_inherent_impls_validity_check(_: ()) -> Result<(), ErrorGuaranteed> {
desc { "check for inherent impls that should not be defined in crate" }
ensure_forwards_result_if_red
}

Expand Down Expand Up @@ -1715,7 +1721,7 @@ rustc_queries! {
///
/// Do not call this directly, but instead use the `incoherent_impls` query.
/// This query is only used to get the data necessary for that query.
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> Result<&'tcx [DefId], ErrorGuaranteed> {
query crate_incoherent_impls(key: (CrateNum, SimplifiedType)) -> &'tcx [DefId] {
desc { |tcx| "collecting all impls for a type in a crate" }
separate_provide_extern
}
Expand Down
20 changes: 3 additions & 17 deletions compiler/rustc_middle/src/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,30 +253,16 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
}

/// Query provider for `incoherent_impls`.
pub(super) fn incoherent_impls_provider(
tcx: TyCtxt<'_>,
simp: SimplifiedType,
) -> Result<&[DefId], ErrorGuaranteed> {
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
let mut impls = Vec::new();

let mut res = Ok(());
for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) {
Ok(impls) => impls,
Err(e) => {
res = Err(e);
continue;
}
};
for &impl_def_id in incoherent_impls {
for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
impls.push(impl_def_id)
}
}

debug!(?impls);
res?;

Ok(tcx.arena.alloc_slice(&impls))
tcx.arena.alloc_slice(&impls)
}

pub(super) fn traits_provider(tcx: TyCtxt<'_>, _: LocalCrate) -> &[DefId] {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_monomorphize/src/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1183,7 +1183,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
}

fn assoc_fn_of_type<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, fn_ident: Ident) -> Option<DefId> {
for impl_def_id in tcx.inherent_impls(def_id).ok()? {
for impl_def_id in tcx.inherent_impls(def_id) {
if let Some(new) = tcx.associated_items(impl_def_id).find_by_name_and_kind(
tcx,
fn_ident,
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1825,10 +1825,12 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
// Doing analysis on local `DefId`s would cause infinite recursion.
return;
}
let Ok(impls) = self.r.tcx.inherent_impls(def_id) else { return };
// Look at all the associated functions without receivers in the type's
// inherent impls to look for builders that return `Self`
let mut items = impls
let mut items = self
.r
.tcx
.inherent_impls(def_id)
.iter()
.flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
// Only assoc fn with no receivers.
Expand Down
1 change: 0 additions & 1 deletion tests/ui/const-generics/wrong-normalization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,5 @@ pub struct I8<const F: i8>;

impl <I8<{i8::MIN}> as Identity>::Identity {
//~^ ERROR no nominal type found for inherent implementation
//~| ERROR no associated item named `MIN` found for type `i8`
pub fn foo(&self) {}
}
16 changes: 2 additions & 14 deletions tests/ui/const-generics/wrong-normalization.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,6 @@ LL | impl <I8<{i8::MIN}> as Identity>::Identity {
|
= note: either implement a trait on it or create a newtype to wrap it instead

error[E0599]: no associated item named `MIN` found for type `i8` in the current scope
--> $DIR/wrong-normalization.rs:16:15
|
LL | impl <I8<{i8::MIN}> as Identity>::Identity {
| ^^^ associated item not found in `i8`
|
help: you are looking for the module in `std`, not the primitive type
|
LL | impl <I8<{std::i8::MIN}> as Identity>::Identity {
| +++++

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

Some errors have detailed explanations: E0118, E0599.
For more information about an error, try `rustc --explain E0118`.
For more information about this error, try `rustc --explain E0118`.
3 changes: 1 addition & 2 deletions tests/ui/impl-trait/where-allowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ fn in_dyn_Fn_return_in_parameters(_: &dyn Fn() -> impl Debug) { panic!() }
fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() }
//~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds

// Allowed
// Allowed (but it's still ambiguous; nothing constrains the RPIT in this body).
fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() }
//~^ ERROR: type annotations needed

Expand Down Expand Up @@ -79,7 +79,6 @@ fn in_impl_Trait_in_parameters(_: impl Iterator<Item = impl Iterator>) { panic!(
// Allowed
fn in_impl_Trait_in_return() -> impl IntoIterator<Item = impl IntoIterator> {
vec![vec![0; 10], vec![12; 7], vec![8; 3]]
//~^ ERROR: no function or associated item named `into_vec` found for slice `[_]`
}

// Disallowed
Expand Down
Loading

0 comments on commit cfb8419

Please sign in to comment.