1
Fork 0

Only compute specializes query if specialization is enabled in the crate of the specialized impl

This commit is contained in:
Michael Goulet 2024-06-07 15:58:05 -04:00
parent 1653a2d34a
commit 4b188d9d66
8 changed files with 39 additions and 37 deletions

View file

@ -623,6 +623,7 @@ pub fn provide(providers: &mut Providers) {
*providers = Providers {
specialization_graph_of: specialize::specialization_graph_provider,
specializes: specialize::specializes,
specialization_enabled_in: specialize::specialization_enabled_in,
instantiate_and_check_impossible_predicates,
is_impossible_associated_item,
..*providers

View file

@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{codes::*, Diag, EmissionGuarantee};
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::bug;
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{self, ImplSubject, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{GenericArgs, GenericArgsRef};
use rustc_session::lint::builtin::COHERENCE_LEAK_CHECK;
@ -136,6 +137,10 @@ pub fn translate_args_with_cause<'tcx>(
source_args.rebase_onto(infcx.tcx, source_impl, target_args)
}
pub(super) fn specialization_enabled_in(tcx: TyCtxt<'_>, _: LocalCrate) -> bool {
tcx.features().specialization || tcx.features().min_specialization
}
/// Is `impl1` a specialization of `impl2`?
///
/// Specialization is determined by the sets of types to which the impls apply;
@ -143,31 +148,18 @@ pub fn translate_args_with_cause<'tcx>(
/// to.
#[instrument(skip(tcx), level = "debug")]
pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, DefId)) -> bool {
// The feature gate should prevent introducing new specializations, but not
// taking advantage of upstream ones.
// If specialization is enabled for this crate then no extra checks are needed.
// If it's not, and either of the `impl`s is local to this crate, then this definitely
// isn't specializing - unless specialization is enabled for the `impl` span,
// e.g. if it comes from an `allow_internal_unstable` macro
let features = tcx.features();
let specialization_enabled = features.specialization || features.min_specialization;
if !specialization_enabled {
if impl1_def_id.is_local() {
let span = tcx.def_span(impl1_def_id);
if !span.allows_unstable(sym::specialization)
&& !span.allows_unstable(sym::min_specialization)
{
return false;
}
}
if impl2_def_id.is_local() {
let span = tcx.def_span(impl2_def_id);
if !span.allows_unstable(sym::specialization)
&& !span.allows_unstable(sym::min_specialization)
{
return false;
}
// We check that the specializing impl comes from a crate that has specialization enabled,
// or if the specializing impl is marked with `allow_internal_unstable`.
//
// We don't really care if the specialized impl (the parent) is in a crate that has
// specialization enabled, since it's not being specialized, and it's already been checked
// for coherence.
if !tcx.specialization_enabled_in(impl1_def_id.krate) {
let span = tcx.def_span(impl1_def_id);
if !span.allows_unstable(sym::specialization)
&& !span.allows_unstable(sym::min_specialization)
{
return false;
}
}