1
Fork 0

Rollup merge of #110791 - compiler-errors:negative-bounds, r=oli-obk

Implement negative bounds for internal testing purposes

Implements partial support the `!` negative polarity on trait bounds. This is incomplete, but should allow us to at least be able to play with the feature.

Not even gonna consider them as a public-facing feature, but I'm implementing them because would've been nice to have in UI tests, for example in #110671.
This commit is contained in:
Dylan DPC 2023-05-04 00:17:23 +05:30 committed by GitHub
commit 80df4ab403
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 481 additions and 188 deletions

View file

@ -530,6 +530,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
associated_ty: Option<(&'static str, Ty<'tcx>)>,
mut body_id: LocalDefId,
) {
if trait_pred.skip_binder().polarity == ty::ImplPolarity::Negative {
return;
}
let trait_pred = self.resolve_numeric_literals_with_default(trait_pred);
let self_ty = trait_pred.skip_binder().self_ty();

View file

@ -57,6 +57,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
if obligation.polarity() == ty::ImplPolarity::Negative {
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
self.assemble_candidates_from_impls(obligation, &mut candidates);
self.assemble_candidates_from_caller_bounds(stack, &mut candidates)?;
} else {
self.assemble_candidates_for_trait_alias(obligation, &mut candidates);
@ -187,6 +188,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in matching_bounds {
if bound.skip_binder().polarity != stack.obligation.predicate.skip_binder().polarity {
continue;
}
// FIXME(oli-obk): it is suspicious that we are dropping the constness and
// polarity here.
let wc = self.where_clause_may_apply(stack, bound.map_bound(|t| t.trait_ref))?;

View file

@ -328,6 +328,13 @@ impl<'tcx> WfPredicates<'tcx> {
let tcx = self.tcx;
let trait_ref = &trait_pred.trait_ref;
// Negative trait predicates don't require supertraits to hold, just
// that their substs are WF.
if trait_pred.polarity == ty::ImplPolarity::Negative {
self.compute_negative_trait_pred(trait_ref);
return;
}
// if the trait predicate is not const, the wf obligations should not be const as well.
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
@ -393,6 +400,14 @@ impl<'tcx> WfPredicates<'tcx> {
);
}
// Compute the obligations that are required for `trait_ref` to be WF,
// given that it is a *negative* trait predicate.
fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
for arg in trait_ref.substs {
self.compute(arg);
}
}
/// Pushes the obligations required for `trait_ref::Item` to be WF
/// into `self.out`.
fn compute_projection(&mut self, data: ty::AliasTy<'tcx>) {