1
Fork 0

Rollup merge of #116261 - lcnr:wf-only-clause, r=davidtwco

a small wf and clause cleanup

- remove `Clause::from_projection_clause`, instead use `ToPredicate`
- change `predicate_obligations` to directly take a `Clause`
- remove some unnecessary `&`
- use clause in `min_specialization` checks where easily applicable
This commit is contained in:
Matthias Krüger 2023-10-03 16:24:15 +02:00 committed by GitHub
commit 8efbc2cbae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 81 additions and 101 deletions

View file

@ -16,6 +16,7 @@ use rustc_infer::traits::util;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::BottomUpFolder;
use rustc_middle::ty::util::ExplicitSelf;
use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::{
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
};
@ -2279,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>(
//
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
}
_ => predicates.push(ty::Clause::from_projection_clause(
tcx,
_ => predicates.push(
ty::Binder::bind_with_vars(
ty::ProjectionPredicate {
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
term: normalize_impl_ty.into(),
},
bound_vars,
),
)),
)
.to_predicate(tcx),
),
};
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
};

View file

@ -1130,11 +1130,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
let wf_obligations =
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
let normalized_bound = wfcx.normalize(span, None, bound);
traits::wf::predicate_obligations(
traits::wf::clause_obligations(
wfcx.infcx,
wfcx.param_env,
wfcx.body_def_id,
normalized_bound.as_predicate(),
normalized_bound,
bound_span,
)
});
@ -1234,7 +1234,7 @@ fn check_impl<'tcx>(
wfcx.infcx,
wfcx.param_env,
wfcx.body_def_id,
&trait_pred,
trait_pred,
ast_trait_ref.path.span,
item,
);
@ -1443,13 +1443,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
debug!(?predicates.predicates);
assert_eq!(predicates.predicates.len(), predicates.spans.len());
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
traits::wf::predicate_obligations(
infcx,
wfcx.param_env,
wfcx.body_def_id,
p.as_predicate(),
sp,
)
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
});
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
wfcx.register_obligations(obligations);

View file

@ -376,9 +376,9 @@ fn check_predicates<'tcx>(
let always_applicable_traits = impl1_predicates
.iter()
.copied()
.filter(|(clause, _span)| {
.filter(|&(clause, _span)| {
matches!(
trait_predicate_kind(tcx, clause.as_predicate()),
trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::AlwaysApplicable)
)
})
@ -402,7 +402,7 @@ fn check_predicates<'tcx>(
.iter()
.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))]
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
match predicate.kind().skip_binder() {
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, clause: ty::Clause<'tcx>, span: Span) {
match clause.kind().skip_binder() {
// Global predicates are either always true or always false, so we
// are fine to specialize on.
_ if predicate.is_global() => (),
_ if clause.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: _,
})) => {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
if !matches!(
trait_predicate_kind(tcx, predicate),
trait_specialization_kind(tcx, clause),
Some(TraitSpecializationKind::Marker)
) {
tcx.sess
@ -467,10 +464,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
.emit();
}
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate {
projection_ty,
term,
})) => {
ty::ClauseKind::Projection(ty::ProjectionPredicate { projection_ty, term }) => {
tcx.sess
.struct_span_err(
span,
@ -478,7 +472,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
)
.emit();
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..)) => {
ty::ClauseKind::ConstArgHasType(..) => {
// FIXME(min_specialization), FIXME(const_generics):
// 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
@ -490,33 +484,25 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
}
_ => {
tcx.sess
.struct_span_err(span, format!("cannot specialize on predicate `{predicate}`"))
.struct_span_err(span, format!("cannot specialize on predicate `{clause}`"))
.emit();
}
}
}
fn trait_predicate_kind<'tcx>(
fn trait_specialization_kind<'tcx>(
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
clause: ty::Clause<'tcx>,
) -> Option<TraitSpecializationKind> {
match predicate.kind().skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(ty::TraitPredicate {
trait_ref,
polarity: _,
})) => Some(tcx.trait_def(trait_ref.def_id).specialization_kind),
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
| ty::PredicateKind::Clause(ty::ClauseKind::Projection(_))
| ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::AliasRelate(..)
| 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,
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
Some(tcx.trait_def(trait_ref.def_id).specialization_kind)
}
ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::TypeOutlives(_)
| ty::ClauseKind::Projection(_)
| ty::ClauseKind::ConstArgHasType(..)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(..) => None,
}
}