specialization: use clause

This commit is contained in:
lcnr 2023-09-29 11:47:42 +02:00
parent a4f6770d83
commit aac29a0fc3

View file

@ -376,9 +376,9 @@ fn check_predicates<'tcx>(
let always_applicable_traits = impl1_predicates let always_applicable_traits = impl1_predicates
.iter() .iter()
.copied() .copied()
.filter(|(clause, _span)| { .filter(|&(clause, _span)| {
matches!( matches!(
trait_predicate_kind(tcx, clause.as_predicate()), trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::AlwaysApplicable) Some(TraitSpecializationKind::AlwaysApplicable)
) )
}) })
@ -402,7 +402,7 @@ fn check_predicates<'tcx>(
.iter() .iter()
.any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span))
{ {
check_specialization_on(tcx, clause.as_predicate(), span) check_specialization_on(tcx, clause, span)
} }
} }
} }
@ -441,19 +441,16 @@ fn trait_predicates_eq<'tcx>(
} }
#[instrument(level = "debug", skip(tcx))] #[instrument(level = "debug", skip(tcx))]
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) { fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
match predicate.kind().skip_binder() { match clause.kind().skip_binder() {
// Global predicates are either always true or always false, so we // Global predicates are either always true or always false, so we
// are fine to specialize on. // are fine to specialize on.
_ if predicate.is_global() => (), _ if clause.is_global() => (),
// We allow specializing on explicitly marked traits with no associated // We allow specializing on explicitly marked traits with no associated
// items. // items.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
trait_ref,
polarity: _,
})) => {
if !matches!( if !matches!(
trait_predicate_kind(tcx, predicate), trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::Marker) Some(TraitSpecializationKind::Marker)
) { ) {
tcx.sess tcx.sess
@ -467,10 +464,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit(); .emit();
} }
} }
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
projection_ty,
term,
})) => {
tcx.sess tcx.sess
.struct_span_err( .struct_span_err(
span, span,
@ -478,7 +472,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
) )
.emit(); .emit();
} }
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => { ty::ClauseKind::ConstArgHasType(..) => {
// FIXME(min_specialization), FIXME(const_generics): // FIXME(min_specialization), FIXME(const_generics):
// It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure
// about the actual rules that would be sound. Can't just always error here because otherwise // about the actual rules that would be sound. Can't just always error here because otherwise
@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
} }
_ => { _ => {
tcx.sess tcx.sess
.struct_span_err(span, format!("cannot specialize on predicate `{predicate}`")) .struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
.emit(); .emit();
} }
} }
} }
fn trait_predicate_kind<'tcx>( fn trait_specialization_kind<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>, clause: ty::Clause<'tcx>,
) -> Option<TraitSpecializationKind> { ) -> Option<TraitSpecializationKind> {
match predicate.kind().skip_binder() { match clause.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
trait_ref, Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
polarity: _, }
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind), ty::ClauseKind::RegionOutlives(_)
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) | ty::ClauseKind::TypeOutlives(_)
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_)) | ty::ClauseKind::Projection(_)
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) | ty::ClauseKind::ConstArgHasType(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) | ty::ClauseKind::WellFormed(_)
| ty::PredicateKind::AliasRelate(..) | ty::ClauseKind::ConstEvaluatable(..) => None,
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
| ty::PredicateKind::Subtype(_)
| ty::PredicateKind::Coerce(_)
| ty::PredicateKind::ObjectSafe(_)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::Ambiguous => None,
} }
} }