Skip to content

Commit ae9173d

Browse files
committed
Auto merge of #139018 - oli-obk:incremental-trait-impls, r=compiler-errors
Various local trait item iteration cleanups Adding a trait impl for `Foo` unconditionally affected all queries that are interested in a completely independent trait `Bar`. Perf has no effect on this. We probably don't have a good perf test for this tho. r? `@compiler-errors` I am unsure about 9d05efb as it doesn't improve anything wrt incremental, because we still do all the checks for valid `Drop` impls, which subsequently will still invoke many queries and basically keep the depgraph the same. I want to do https://github.com/rust-lang/rust/blob/9549077a47099dc826039c051b528d1013740e6f/compiler/rustc_middle/src/ty/trait_def.rs#L141 but would leave that to a follow-up PR, this one changes enough things as it is
2 parents 79de6c0 + 49c74d2 commit ae9173d

File tree

26 files changed

+97
-94
lines changed

26 files changed

+97
-94
lines changed

compiler/rustc_hir_analysis/src/check/always_applicable.rs

+3-5
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,8 @@ use crate::hir::def_id::{DefId, LocalDefId};
3636
/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
3737
pub(crate) fn check_drop_impl(
3838
tcx: TyCtxt<'_>,
39-
drop_impl_did: DefId,
39+
drop_impl_did: LocalDefId,
4040
) -> Result<(), ErrorGuaranteed> {
41-
let drop_impl_did = drop_impl_did.expect_local();
42-
4341
match tcx.impl_polarity(drop_impl_did) {
4442
ty::ImplPolarity::Positive => {}
4543
ty::ImplPolarity::Negative => {
@@ -56,9 +54,9 @@ pub(crate) fn check_drop_impl(
5654

5755
tcx.ensure_ok().orphan_check_impl(drop_impl_did)?;
5856

59-
let dtor_impl_trait_ref = tcx.impl_trait_ref(drop_impl_did).unwrap().instantiate_identity();
57+
let self_ty = tcx.type_of(drop_impl_did).instantiate_identity();
6058

61-
match dtor_impl_trait_ref.self_ty().kind() {
59+
match self_ty.kind() {
6260
ty::Adt(adt_def, adt_to_impl_args) => {
6361
ensure_impl_params_and_item_params_correspond(
6462
tcx,

compiler/rustc_hir_analysis/src/check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,11 @@ pub fn provide(providers: &mut Providers) {
114114
}
115115

116116
fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::Destructor> {
117-
tcx.calculate_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
117+
tcx.calculate_dtor(def_id, always_applicable::check_drop_impl)
118118
}
119119

120120
fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<ty::AsyncDestructor> {
121-
tcx.calculate_async_dtor(def_id.to_def_id(), always_applicable::check_drop_impl)
121+
tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl)
122122
}
123123

124124
/// Given a `DefId` for an opaque type in return position, find its parent item's return

compiler/rustc_hir_analysis/src/coherence/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,12 @@ pub(crate) fn provide(providers: &mut Providers) {
153153
}
154154

155155
fn coherent_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Result<(), ErrorGuaranteed> {
156+
let impls = tcx.local_trait_impls(def_id);
156157
// If there are no impls for the trait, then "all impls" are trivially coherent and we won't check anything
157158
// anyway. Thus we bail out even before the specialization graph, avoiding the dep_graph edge.
158-
let Some(impls) = tcx.all_local_trait_impls(()).get(&def_id) else { return Ok(()) };
159+
if impls.is_empty() {
160+
return Ok(());
161+
}
159162
// Trigger building the specialization graph for the trait. This will detect and report any
160163
// overlap errors.
161164
let mut res = tcx.ensure_ok().specialization_graph_of(def_id);

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

+17-19
Original file line numberDiff line numberDiff line change
@@ -1730,25 +1730,23 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
17301730
.is_accessible_from(self.item_def_id(), tcx)
17311731
&& tcx.all_impls(*trait_def_id)
17321732
.any(|impl_def_id| {
1733-
let impl_header = tcx.impl_trait_header(impl_def_id);
1734-
impl_header.is_some_and(|header| {
1735-
let trait_ref = header.trait_ref.instantiate(
1736-
tcx,
1737-
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
1738-
);
1739-
1740-
let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
1741-
// FIXME: Don't bother dealing with non-lifetime binders here...
1742-
if value.has_escaping_bound_vars() {
1743-
return false;
1744-
}
1745-
infcx
1746-
.can_eq(
1747-
ty::ParamEnv::empty(),
1748-
trait_ref.self_ty(),
1749-
value,
1750-
) && header.polarity != ty::ImplPolarity::Negative
1751-
})
1733+
let header = tcx.impl_trait_header(impl_def_id).unwrap();
1734+
let trait_ref = header.trait_ref.instantiate(
1735+
tcx,
1736+
infcx.fresh_args_for_item(DUMMY_SP, impl_def_id),
1737+
);
1738+
1739+
let value = fold_regions(tcx, qself_ty, |_, _| tcx.lifetimes.re_erased);
1740+
// FIXME: Don't bother dealing with non-lifetime binders here...
1741+
if value.has_escaping_bound_vars() {
1742+
return false;
1743+
}
1744+
infcx
1745+
.can_eq(
1746+
ty::ParamEnv::empty(),
1747+
trait_ref.self_ty(),
1748+
value,
1749+
) && header.polarity != ty::ImplPolarity::Negative
17521750
})
17531751
})
17541752
.map(|trait_def_id| tcx.def_path_str(trait_def_id))

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -330,14 +330,8 @@ provide! { tcx, def_id, other, cdata,
330330

331331
visibility => { cdata.get_visibility(def_id.index) }
332332
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
333-
adt_destructor => {
334-
let _ = cdata;
335-
tcx.calculate_dtor(def_id, |_,_| Ok(()))
336-
}
337-
adt_async_destructor => {
338-
let _ = cdata;
339-
tcx.calculate_async_dtor(def_id, |_,_| Ok(()))
340-
}
333+
adt_destructor => { table }
334+
adt_async_destructor => { table }
341335
associated_item_def_ids => {
342336
tcx.arena.alloc_from_iter(cdata.get_associated_item_or_field_def_ids(def_id.index))
343337
}

compiler/rustc_metadata/src/rmeta/encoder.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
16341634
record!(self.tables.fn_sig[variant.def_id] <- fn_sig);
16351635
}
16361636
}
1637+
1638+
if let Some(destructor) = tcx.adt_destructor(local_def_id) {
1639+
record!(self.tables.adt_destructor[def_id] <- destructor);
1640+
}
1641+
1642+
if let Some(destructor) = tcx.adt_async_destructor(local_def_id) {
1643+
record!(self.tables.adt_async_destructor[def_id] <- destructor);
1644+
}
16371645
}
16381646

16391647
#[instrument(level = "debug", skip(self))]

compiler/rustc_metadata/src/rmeta/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,8 @@ define_tables! {
452452
fn_arg_names: Table<DefIndex, LazyArray<Option<Ident>>>,
453453
coroutine_kind: Table<DefIndex, hir::CoroutineKind>,
454454
coroutine_for_closure: Table<DefIndex, RawDefId>,
455+
adt_destructor: Table<DefIndex, LazyValue<ty::Destructor>>,
456+
adt_async_destructor: Table<DefIndex, LazyValue<ty::AsyncDestructor>>,
455457
coroutine_by_move_body_def_id: Table<DefIndex, RawDefId>,
456458
eval_static_initializer: Table<DefIndex, LazyValue<mir::interpret::ConstAllocation<'static>>>,
457459
trait_def: Table<DefIndex, LazyValue<ty::TraitDef>>,

compiler/rustc_middle/src/hir/map.rs

-4
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,6 @@ impl<'tcx> TyCtxt<'tcx> {
367367
}
368368
}
369369

370-
pub fn hir_trait_impls(self, trait_did: DefId) -> &'tcx [LocalDefId] {
371-
self.all_local_trait_impls(()).get(&trait_did).map_or(&[], |xs| &xs[..])
372-
}
373-
374370
/// Gets the attributes on the crate. This is preferable to
375371
/// invoking `krate.attrs` because it registers a tighter
376372
/// dep-graph access.

compiler/rustc_middle/src/hir/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,8 @@ pub fn provide(providers: &mut Providers) {
238238
}
239239
};
240240
providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
241+
providers.local_trait_impls =
242+
|tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
241243
providers.expn_that_defined =
242244
|tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
243245
providers.in_scope_traits_map = |tcx, id| {

compiler/rustc_middle/src/query/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,11 @@ rustc_queries! {
15021502
desc { "finding local trait impls" }
15031503
}
15041504

1505+
/// Return all `impl` blocks of the given trait in the current crate.
1506+
query local_trait_impls(trait_id: DefId) -> &'tcx [LocalDefId] {
1507+
desc { "finding local trait impls of `{}`", tcx.def_path_str(trait_id) }
1508+
}
1509+
15051510
/// Given a trait `trait_id`, return all known `impl` blocks.
15061511
query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls {
15071512
arena_cache

compiler/rustc_middle/src/ty/adt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ impl<'tcx> rustc_type_ir::inherent::AdtDef<TyCtxt<'tcx>> for AdtDef<'tcx> {
236236
}
237237

238238
fn destructor(self, tcx: TyCtxt<'tcx>) -> Option<AdtDestructorKind> {
239-
Some(match self.destructor(tcx)?.constness {
239+
Some(match tcx.constness(self.destructor(tcx)?.did) {
240240
hir::Constness::Const => AdtDestructorKind::Const,
241241
hir::Constness::NotConst => AdtDestructorKind::NotConst,
242242
})

compiler/rustc_middle/src/ty/mod.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1119,8 +1119,6 @@ pub struct PseudoCanonicalInput<'tcx, T> {
11191119
pub struct Destructor {
11201120
/// The `DefId` of the destructor method
11211121
pub did: DefId,
1122-
/// The constness of the destructor method
1123-
pub constness: hir::Constness,
11241122
}
11251123

11261124
// FIXME: consider combining this definition with regular `Destructor`

compiler/rustc_middle/src/ty/parameterized.rs

+2
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,11 @@ trivially_parameterized_over_tcx! {
6565
crate::middle::lib_features::FeatureStability,
6666
crate::middle::resolve_bound_vars::ObjectLifetimeDefault,
6767
crate::mir::ConstQualifs,
68+
ty::AsyncDestructor,
6869
ty::AssocItemContainer,
6970
ty::Asyncness,
7071
ty::DeducedParamAttrs,
72+
ty::Destructor,
7173
ty::Generics,
7274
ty::ImplPolarity,
7375
ty::ImplTraitInTraitData,

compiler/rustc_middle/src/ty/trait_def.rs

+1-16
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,6 @@ impl<'tcx> TraitDef {
129129
}
130130

131131
impl<'tcx> TyCtxt<'tcx> {
132-
/// `trait_def_id` MUST BE the `DefId` of a trait.
133-
pub fn for_each_impl<F: FnMut(DefId)>(self, trait_def_id: DefId, mut f: F) {
134-
let impls = self.trait_impls_of(trait_def_id);
135-
136-
for &impl_def_id in impls.blanket_impls.iter() {
137-
f(impl_def_id);
138-
}
139-
140-
for v in impls.non_blanket_impls.values() {
141-
for &impl_def_id in v {
142-
f(impl_def_id);
143-
}
144-
}
145-
}
146-
147132
/// Iterate over every impl that could possibly match the self type `self_ty`.
148133
///
149134
/// `trait_def_id` MUST BE the `DefId` of a trait.
@@ -235,7 +220,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
235220
}
236221
}
237222

238-
for &impl_def_id in tcx.hir_trait_impls(trait_id) {
223+
for &impl_def_id in tcx.local_trait_impls(trait_id) {
239224
let impl_def_id = impl_def_id.to_def_id();
240225

241226
let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity();

compiler/rustc_middle/src/ty/util.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -389,63 +389,73 @@ impl<'tcx> TyCtxt<'tcx> {
389389
/// Calculate the destructor of a given type.
390390
pub fn calculate_dtor(
391391
self,
392-
adt_did: DefId,
393-
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
392+
adt_did: LocalDefId,
393+
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
394394
) -> Option<ty::Destructor> {
395395
let drop_trait = self.lang_items().drop_trait()?;
396396
self.ensure_ok().coherent_trait(drop_trait).ok()?;
397397

398-
let ty = self.type_of(adt_did).instantiate_identity();
399398
let mut dtor_candidate = None;
400-
self.for_each_relevant_impl(drop_trait, ty, |impl_did| {
399+
// `Drop` impls can only be written in the same crate as the adt, and cannot be blanket impls
400+
for &impl_did in self.local_trait_impls(drop_trait) {
401+
let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
402+
if adt_def.did() != adt_did.to_def_id() {
403+
continue;
404+
}
405+
401406
if validate(self, impl_did).is_err() {
402407
// Already `ErrorGuaranteed`, no need to delay a span bug here.
403-
return;
408+
continue;
404409
}
405410

406411
let Some(item_id) = self.associated_item_def_ids(impl_did).first() else {
407412
self.dcx()
408413
.span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function");
409-
return;
414+
continue;
410415
};
411416

412-
if let Some((old_item_id, _)) = dtor_candidate {
417+
if let Some(old_item_id) = dtor_candidate {
413418
self.dcx()
414419
.struct_span_err(self.def_span(item_id), "multiple drop impls found")
415420
.with_span_note(self.def_span(old_item_id), "other impl here")
416421
.delay_as_bug();
417422
}
418423

419-
dtor_candidate = Some((*item_id, self.impl_trait_header(impl_did).unwrap().constness));
420-
});
424+
dtor_candidate = Some(*item_id);
425+
}
421426

422-
let (did, constness) = dtor_candidate?;
423-
Some(ty::Destructor { did, constness })
427+
let did = dtor_candidate?;
428+
Some(ty::Destructor { did })
424429
}
425430

426431
/// Calculate the async destructor of a given type.
427432
pub fn calculate_async_dtor(
428433
self,
429-
adt_did: DefId,
430-
validate: impl Fn(Self, DefId) -> Result<(), ErrorGuaranteed>,
434+
adt_did: LocalDefId,
435+
validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>,
431436
) -> Option<ty::AsyncDestructor> {
432437
let async_drop_trait = self.lang_items().async_drop_trait()?;
433438
self.ensure_ok().coherent_trait(async_drop_trait).ok()?;
434439

435-
let ty = self.type_of(adt_did).instantiate_identity();
436440
let mut dtor_candidate = None;
437-
self.for_each_relevant_impl(async_drop_trait, ty, |impl_did| {
441+
// `AsyncDrop` impls can only be written in the same crate as the adt, and cannot be blanket impls
442+
for &impl_did in self.local_trait_impls(async_drop_trait) {
443+
let Some(adt_def) = self.type_of(impl_did).skip_binder().ty_adt_def() else { continue };
444+
if adt_def.did() != adt_did.to_def_id() {
445+
continue;
446+
}
447+
438448
if validate(self, impl_did).is_err() {
439449
// Already `ErrorGuaranteed`, no need to delay a span bug here.
440-
return;
450+
continue;
441451
}
442452

443453
let [future, ctor] = self.associated_item_def_ids(impl_did) else {
444454
self.dcx().span_delayed_bug(
445455
self.def_span(impl_did),
446456
"AsyncDrop impl without async_drop function or Dropper type",
447457
);
448-
return;
458+
continue;
449459
};
450460

451461
if let Some((_, _, old_impl_did)) = dtor_candidate {
@@ -456,7 +466,7 @@ impl<'tcx> TyCtxt<'tcx> {
456466
}
457467

458468
dtor_candidate = Some((*future, *ctor, impl_did));
459-
});
469+
}
460470

461471
let (future, ctor, _) = dtor_candidate?;
462472
Some(ty::AsyncDestructor { future, ctor })

compiler/rustc_mir_transform/src/check_const_item_mutation.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,13 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> {
5353
//
5454
// #[const_mutation_allowed]
5555
// pub const LOG: Log = Log { msg: "" };
56-
match self.tcx.calculate_dtor(def_id, |_, _| Ok(())) {
57-
Some(_) => None,
58-
None => Some(def_id),
56+
// FIXME: this should not be checking for `Drop` impls,
57+
// but whether it or any field has a Drop impl (`needs_drop`)
58+
// as fields' Drop impls may make this observable, too.
59+
match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt| adt.has_dtor(self.tcx))
60+
{
61+
Some(true) => None,
62+
Some(false) | None => Some(def_id),
5963
}
6064
}
6165

compiler/rustc_monomorphize/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ monomorphize_large_assignments =
4848
.note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
4949
5050
monomorphize_no_optimized_mir =
51-
missing optimized MIR for an item in the crate `{$crate_name}`
51+
missing optimized MIR for `{$instance}` in the crate `{$crate_name}`
5252
.note = missing optimized MIR for this item (was the crate `{$crate_name}` compiled with `--emit=metadata`?)
5353
5454
monomorphize_recursion_limit =

compiler/rustc_monomorphize/src/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,7 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) ->
989989
tcx.dcx().emit_fatal(NoOptimizedMir {
990990
span: tcx.def_span(def_id),
991991
crate_name: tcx.crate_name(def_id.krate),
992+
instance: instance.to_string(),
992993
});
993994
}
994995

compiler/rustc_monomorphize/src/errors.rs

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub(crate) struct NoOptimizedMir {
2424
#[note]
2525
pub span: Span,
2626
pub crate_name: Symbol,
27+
pub instance: String,
2728
}
2829

2930
#[derive(LintDiagnostic)]

compiler/rustc_passes/src/dead.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -421,10 +421,8 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
421421
}
422422
hir::ItemKind::ForeignMod { .. } => {}
423423
hir::ItemKind::Trait(..) => {
424-
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
425-
if let Some(local_def_id) = impl_def_id.as_local()
426-
&& let ItemKind::Impl(impl_ref) =
427-
self.tcx.hir_expect_item(local_def_id).kind
424+
for &impl_def_id in self.tcx.local_trait_impls(item.owner_id.def_id) {
425+
if let ItemKind::Impl(impl_ref) = self.tcx.hir_expect_item(impl_def_id).kind
428426
{
429427
// skip items
430428
// mark dependent traits live

compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
365365
// obligation comes from the `impl`. Find that `impl` so that we can point
366366
// at it in the suggestion.
367367
let trait_did = trait_id.to_def_id();
368-
tcx.hir_trait_impls(trait_did).iter().find_map(|&impl_did| {
368+
tcx.local_trait_impls(trait_did).iter().find_map(|&impl_did| {
369369
if let Node::Item(Item {
370370
kind: ItemKind::Impl(hir::Impl { self_ty, .. }), ..
371371
}) = tcx.hir_node_by_def_id(impl_did)

0 commit comments

Comments
 (0)