Skip to content

Commit 4b188d9

Browse files
Only compute specializes query if specialization is enabled in the crate of the specialized impl
1 parent 1653a2d commit 4b188d9

File tree

8 files changed

+39
-37
lines changed

8 files changed

+39
-37
lines changed

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

+1
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ provide! { tcx, def_id, other, cdata,
314314
extern_crate => { cdata.extern_crate.map(|c| &*tcx.arena.alloc(c)) }
315315
is_no_builtins => { cdata.root.no_builtins }
316316
symbol_mangling_version => { cdata.root.symbol_mangling_version }
317+
specialization_enabled_in => { cdata.root.specialization_enabled_in }
317318
reachable_non_generics => {
318319
let reachable_non_generics = tcx
319320
.exported_symbols(cdata.cnum)

compiler/rustc_metadata/src/rmeta/encoder.rs

+1
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
741741
expn_data,
742742
expn_hashes,
743743
def_path_hash_map,
744+
specialization_enabled_in: tcx.specialization_enabled_in(LOCAL_CRATE),
744745
})
745746
});
746747

compiler/rustc_metadata/src/rmeta/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,8 @@ pub(crate) struct CrateRoot {
290290
panic_runtime: bool,
291291
profiler_runtime: bool,
292292
symbol_mangling_version: SymbolManglingVersion,
293+
294+
specialization_enabled_in: bool,
293295
}
294296

295297
/// On-disk representation of `DefId`.

compiler/rustc_middle/src/query/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1494,6 +1494,11 @@ rustc_queries! {
14941494
separate_provide_extern
14951495
}
14961496

1497+
query specialization_enabled_in(cnum: CrateNum) -> bool {
1498+
desc { "checking whether the crate enabled `specialization`/`min_specialization`" }
1499+
separate_provide_extern
1500+
}
1501+
14971502
query specializes(_: (DefId, DefId)) -> bool {
14981503
desc { "computing whether impls specialize one another" }
14991504
}

compiler/rustc_trait_selection/src/traits/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ pub fn provide(providers: &mut Providers) {
623623
*providers = Providers {
624624
specialization_graph_of: specialize::specialization_graph_provider,
625625
specializes: specialize::specializes,
626+
specialization_enabled_in: specialize::specialization_enabled_in,
626627
instantiate_and_check_impossible_predicates,
627628
is_impossible_associated_item,
628629
..*providers

compiler/rustc_trait_selection/src/traits/specialize/mod.rs

+17-25
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
2424
use rustc_errors::{codes::*, Diag, EmissionGuarantee};
2525
use rustc_hir::def_id::{DefId, LocalDefId};
2626
use rustc_middle::bug;
27+
use rustc_middle::query::LocalCrate;
2728
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
2829
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
2930
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
@@ -136,38 +137,29 @@ pub fn translate_args_with_cause<'tcx>(
136137
source_args.rebase_onto(infcx.tcx, source_impl, target_args)
137138
}
138139

140+
pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
141+
tcx.features().specialization || tcx.features().min_specialization
142+
}
143+
139144
/// Is `impl1` a specialization of `impl2`?
140145
///
141146
/// Specialization is determined by the sets of types to which the impls apply;
142147
/// `impl1` specializes `impl2` if it applies to a subset of the types `impl2` applies
143148
/// to.
144149
#[instrument(skip(tcx), level = "debug")]
145150
pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
146-
// The feature gate should prevent introducing new specializations, but not
147-
// taking advantage of upstream ones.
148-
// If specialization is enabled for this crate then no extra checks are needed.
149-
// If it's not, and either of the `impl`s is local to this crate, then this definitely
150-
// isn't specializing - unless specialization is enabled for the `impl` span,
151-
// e.g. if it comes from an `allow_internal_unstable` macro
152-
let features = tcx.features();
153-
let specialization_enabled = features.specialization || features.min_specialization;
154-
if !specialization_enabled {
155-
if impl1_def_id.is_local() {
156-
let span = tcx.def_span(impl1_def_id);
157-
if !span.allows_unstable(sym::specialization)
158-
&& !span.allows_unstable(sym::min_specialization)
159-
{
160-
return false;
161-
}
162-
}
163-
164-
if impl2_def_id.is_local() {
165-
let span = tcx.def_span(impl2_def_id);
166-
if !span.allows_unstable(sym::specialization)
167-
&& !span.allows_unstable(sym::min_specialization)
168-
{
169-
return false;
170-
}
151+
// We check that the specializing impl comes from a crate that has specialization enabled,
152+
// or if the specializing impl is marked with `allow_internal_unstable`.
153+
//
154+
// We don't really care if the specialized impl (the parent) is in a crate that has
155+
// specialization enabled, since it's not being specialized, and it's already been checked
156+
// for coherence.
157+
if !tcx.specialization_enabled_in(impl1_def_id.krate) {
158+
let span = tcx.def_span(impl1_def_id);
159+
if !span.allows_unstable(sym::specialization)
160+
&& !span.allows_unstable(sym::min_specialization)
161+
{
162+
return false;
171163
}
172164
}
173165

tests/ui/coherence/coherence-impls-copy.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,3 @@
1-
error[E0117]: only traits defined in the current crate can be implemented for primitive types
2-
--> $DIR/coherence-impls-copy.rs:5:1
3-
|
4-
LL | impl Copy for i32 {}
5-
| ^^^^^^^^^^^^^^---
6-
| | |
7-
| | `i32` is not defined in the current crate
8-
| impl doesn't use only types from inside the current crate
9-
|
10-
= note: define and implement a trait or new type instead
11-
121
error[E0119]: conflicting implementations of trait `Copy` for type `&NotSync`
132
--> $DIR/coherence-impls-copy.rs:28:1
143
|
@@ -30,6 +19,17 @@ LL | impl Copy for &'static [NotSync] {}
3019
|
3120
= note: define and implement a trait or new type instead
3221

22+
error[E0117]: only traits defined in the current crate can be implemented for primitive types
23+
--> $DIR/coherence-impls-copy.rs:5:1
24+
|
25+
LL | impl Copy for i32 {}
26+
| ^^^^^^^^^^^^^^---
27+
| | |
28+
| | `i32` is not defined in the current crate
29+
| impl doesn't use only types from inside the current crate
30+
|
31+
= note: define and implement a trait or new type instead
32+
3333
error[E0206]: the trait `Copy` cannot be implemented for this type
3434
--> $DIR/coherence-impls-copy.rs:21:15
3535
|

tests/ui/specialization/anyid-repro-125197.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// actually participate in specialization. Since <https://github.com/rust-lang/rust/pull/122791>,
66
// we don't treat inductive cycles as errors -- so we may need to winnow more pairs of impls, and
77
// we try to winnow impls in favor of other impls. However, if we're *inside* the `specializes`
8-
// query, then may have a query cycle if we call `specializes` again!
8+
// query, then may have a query cycle if we call `specializes` again!
99

1010
extern crate anyid_repro_125197;
1111
use anyid_repro_125197::AnyId;

0 commit comments

Comments
 (0)