properly elaborate effects implied bounds for super traits
This commit is contained in:
parent
4428a05167
commit
7c2a24b50c
@ -91,12 +91,46 @@ pub(crate) fn push_trait_bound(
|
|||||||
}
|
}
|
||||||
tcx.consts.true_
|
tcx.consts.true_
|
||||||
}
|
}
|
||||||
|
(DefKind::Trait, ty::BoundConstness::ConstIfConst) => {
|
||||||
|
// we are in a trait, where `bound_trait_ref` could be:
|
||||||
|
// (1) a super trait `trait Foo: ~const Bar`.
|
||||||
|
// - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
|
||||||
|
//
|
||||||
|
// (2) a where clause `where for<..> Something: ~const Bar`.
|
||||||
|
// - This generates `for<..> <Self as Foo>::Effects: TyCompat<<Something as Bar>::Effects>`
|
||||||
|
let Some(own_fx) = tcx.associated_type_for_effects(defining_def_id) else {
|
||||||
|
tcx.dcx().span_delayed_bug(span, "should not have allowed `~const` on a trait that doesn't have `#[const_trait]`");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let own_fx_ty = Ty::new_projection(
|
||||||
|
tcx,
|
||||||
|
own_fx,
|
||||||
|
ty::GenericArgs::identity_for_item(tcx, own_fx),
|
||||||
|
);
|
||||||
|
let Some(their_fx) = tcx.associated_type_for_effects(bound_trait_ref.def_id())
|
||||||
|
else {
|
||||||
|
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
let their_fx_ty =
|
||||||
|
Ty::new_projection(tcx, their_fx, bound_trait_ref.skip_binder().args);
|
||||||
|
let compat = tcx.require_lang_item(LangItem::EffectsTyCompat, Some(span));
|
||||||
|
let clause = bound_trait_ref
|
||||||
|
.map_bound(|_| {
|
||||||
|
let trait_ref = ty::TraitRef::new(tcx, compat, [own_fx_ty, their_fx_ty]);
|
||||||
|
ty::ClauseKind::Trait(ty::TraitPredicate {
|
||||||
|
trait_ref,
|
||||||
|
polarity: ty::PredicatePolarity::Positive,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.upcast(tcx);
|
||||||
|
|
||||||
(
|
self.clauses.push((clause, span));
|
||||||
DefKind::Trait | DefKind::Impl { of_trait: true },
|
return;
|
||||||
ty::BoundConstness::ConstIfConst,
|
}
|
||||||
) => {
|
|
||||||
// this is either a where clause on an impl/trait header or on a trait.
|
(DefKind::Impl { of_trait: true }, ty::BoundConstness::ConstIfConst) => {
|
||||||
|
// this is a where clause on an impl header.
|
||||||
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
// push `<T as Tr>::Effects` into the set for the `Min` bound.
|
||||||
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
|
||||||
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
|
||||||
|
@ -360,33 +360,10 @@ pub(super) fn explicit_item_bounds_with_filter(
|
|||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) {
|
|
||||||
let mut predicates = Vec::new();
|
|
||||||
|
|
||||||
let parent = tcx.local_parent(def_id);
|
|
||||||
|
|
||||||
let preds = tcx.explicit_predicates_of(parent);
|
|
||||||
|
|
||||||
if let ty::AssocItemContainer::TraitContainer = tcx.associated_item(def_id).container {
|
|
||||||
// for traits, emit `type Effects: TyCompat<<(T1::Effects, ..) as Min>::Output>`
|
|
||||||
let tup = Ty::new(tcx, ty::Tuple(preds.effects_min_tys));
|
|
||||||
// FIXME(effects) span
|
|
||||||
let span = tcx.def_span(def_id);
|
|
||||||
let assoc = tcx.require_lang_item(hir::LangItem::EffectsIntersectionOutput, Some(span));
|
|
||||||
let proj = Ty::new_projection(tcx, assoc, [tup]);
|
|
||||||
let self_proj = Ty::new_projection(
|
|
||||||
tcx,
|
|
||||||
def_id.to_def_id(),
|
|
||||||
ty::GenericArgs::identity_for_item(tcx, def_id),
|
|
||||||
);
|
|
||||||
let trait_ = tcx.require_lang_item(hir::LangItem::EffectsTyCompat, Some(span));
|
|
||||||
let trait_ref = ty::TraitRef::new(tcx, trait_, [self_proj, proj]);
|
|
||||||
predicates.push((ty::Binder::dummy(trait_ref).upcast(tcx), span));
|
|
||||||
}
|
|
||||||
return ty::EarlyBinder::bind(tcx.arena.alloc_from_iter(predicates));
|
|
||||||
}
|
|
||||||
|
|
||||||
let bounds = match tcx.hir_node_by_def_id(def_id) {
|
let bounds = match tcx.hir_node_by_def_id(def_id) {
|
||||||
|
_ if tcx.is_effects_desugared_assoc_ty(def_id.to_def_id()) => {
|
||||||
|
associated_type_bounds(tcx, def_id, &[], tcx.def_span(def_id), filter)
|
||||||
|
}
|
||||||
hir::Node::TraitItem(hir::TraitItem {
|
hir::Node::TraitItem(hir::TraitItem {
|
||||||
kind: hir::TraitItemKind::Type(bounds, _),
|
kind: hir::TraitItemKind::Type(bounds, _),
|
||||||
span,
|
span,
|
||||||
|
@ -622,11 +622,13 @@ fn lang_item_to_trait_lang_item(lang_item: LangItem) -> Option<TraitSolverLangIt
|
|||||||
Destruct,
|
Destruct,
|
||||||
DiscriminantKind,
|
DiscriminantKind,
|
||||||
DynMetadata,
|
DynMetadata,
|
||||||
|
EffectsCompat,
|
||||||
EffectsIntersection,
|
EffectsIntersection,
|
||||||
EffectsIntersectionOutput,
|
EffectsIntersectionOutput,
|
||||||
EffectsMaybe,
|
EffectsMaybe,
|
||||||
EffectsNoRuntime,
|
EffectsNoRuntime,
|
||||||
EffectsRuntime,
|
EffectsRuntime,
|
||||||
|
EffectsTyCompat,
|
||||||
Fn,
|
Fn,
|
||||||
FnMut,
|
FnMut,
|
||||||
FnOnce,
|
FnOnce,
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
use crate::data_structures::HashSet;
|
use crate::data_structures::HashSet;
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
|
use crate::lang_items::TraitSolverLangItem;
|
||||||
use crate::outlives::{Component, push_outlives_components};
|
use crate::outlives::{Component, push_outlives_components};
|
||||||
use crate::{self as ty, Interner, Upcast as _};
|
use crate::{self as ty, Interner, Upcast as _};
|
||||||
|
|
||||||
@ -89,6 +90,70 @@ fn elaborate(&mut self, elaboratable: &O) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK(effects): The following code is required to get implied bounds for effects associated
|
||||||
|
// types to work with super traits.
|
||||||
|
//
|
||||||
|
// Suppose `data` is a trait predicate with the form `<T as Tr>::Fx: EffectsCompat<somebool>`
|
||||||
|
// and we know that `trait Tr: ~const SuperTr`, we need to elaborate this predicate into
|
||||||
|
// `<T as SuperTr>::Fx: EffectsCompat<somebool>`.
|
||||||
|
//
|
||||||
|
// Since the semantics for elaborating bounds about effects is equivalent to elaborating
|
||||||
|
// bounds about super traits (elaborate `T: Tr` into `T: SuperTr`), we place effects elaboration
|
||||||
|
// next to super trait elaboration.
|
||||||
|
if cx.is_lang_item(data.def_id(), TraitSolverLangItem::EffectsCompat)
|
||||||
|
&& matches!(self.mode, Filter::All)
|
||||||
|
{
|
||||||
|
// first, ensure that the predicate we've got looks like a `<T as Tr>::Fx: EffectsCompat<somebool>`.
|
||||||
|
if let ty::Alias(ty::AliasTyKind::Projection, alias_ty) = data.self_ty().kind()
|
||||||
|
{
|
||||||
|
// look for effects-level bounds that look like `<Self as Tr>::Fx: TyCompat<<Self as SuperTr>::Fx>`
|
||||||
|
// on the trait, which is proof to us that `Tr: ~const SuperTr`. We're looking for bounds on the
|
||||||
|
// associated trait, so we use `explicit_implied_predicates_of` since it gives us more than just
|
||||||
|
// `Self: SuperTr` bounds.
|
||||||
|
let bounds = cx.explicit_implied_predicates_of(cx.parent(alias_ty.def_id));
|
||||||
|
|
||||||
|
// instantiate the implied bounds, so we get `<T as Tr>::Fx` and not `<Self as Tr>::Fx`.
|
||||||
|
let elaborated = bounds.iter_instantiated(cx, alias_ty.args).filter_map(
|
||||||
|
|(clause, _)| {
|
||||||
|
let ty::ClauseKind::Trait(tycompat_bound) =
|
||||||
|
clause.kind().skip_binder()
|
||||||
|
else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
if !cx.is_lang_item(
|
||||||
|
tycompat_bound.def_id(),
|
||||||
|
TraitSolverLangItem::EffectsTyCompat,
|
||||||
|
) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract `<T as SuperTr>::Fx` from the `TyCompat` bound.
|
||||||
|
let supertrait_effects_ty =
|
||||||
|
tycompat_bound.trait_ref.args.type_at(1);
|
||||||
|
let ty::Alias(ty::AliasTyKind::Projection, supertrait_alias_ty) =
|
||||||
|
supertrait_effects_ty.kind()
|
||||||
|
else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The self types (`T`) must be equal for `<T as Tr>::Fx` and `<T as SuperTr>::Fx`.
|
||||||
|
if supertrait_alias_ty.self_ty() != alias_ty.self_ty() {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
// replace the self type in the original bound `<T as Tr>::Fx: EffectsCompat<somebool>`
|
||||||
|
// to the effects type of the super trait. (`<T as SuperTr>::Fx`)
|
||||||
|
let elaborated_bound = data.with_self_ty(cx, supertrait_effects_ty);
|
||||||
|
Some(
|
||||||
|
elaboratable
|
||||||
|
.child(bound_clause.rebind(elaborated_bound).upcast(cx)),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
self.extend_deduped(elaborated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let map_to_child_clause =
|
let map_to_child_clause =
|
||||||
|(index, (clause, span)): (usize, (I::Clause, I::Span))| {
|
|(index, (clause, span)): (usize, (I::Clause, I::Span))| {
|
||||||
elaboratable.child_with_derived_cause(
|
elaboratable.child_with_derived_cause(
|
||||||
|
@ -20,11 +20,13 @@ pub enum TraitSolverLangItem {
|
|||||||
Destruct,
|
Destruct,
|
||||||
DiscriminantKind,
|
DiscriminantKind,
|
||||||
DynMetadata,
|
DynMetadata,
|
||||||
|
EffectsCompat,
|
||||||
EffectsIntersection,
|
EffectsIntersection,
|
||||||
EffectsIntersectionOutput,
|
EffectsIntersectionOutput,
|
||||||
EffectsMaybe,
|
EffectsMaybe,
|
||||||
EffectsNoRuntime,
|
EffectsNoRuntime,
|
||||||
EffectsRuntime,
|
EffectsRuntime,
|
||||||
|
EffectsTyCompat,
|
||||||
Fn,
|
Fn,
|
||||||
FnMut,
|
FnMut,
|
||||||
FnOnce,
|
FnOnce,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
//@ revisions: yy yn ny nn
|
//@ revisions: yy yn ny nn
|
||||||
//@[yy] known-bug: #110395
|
//@[yy] check-pass
|
||||||
|
|
||||||
#[cfg_attr(any(yy, yn), const_trait)]
|
#[cfg_attr(any(yy, yn), const_trait)]
|
||||||
trait Foo {
|
trait Foo {
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied
|
|
||||||
--> $DIR/super-traits-fail-3.rs:22:7
|
|
||||||
|
|
|
||||||
LL | x.a();
|
|
||||||
| ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}`
|
|
||||||
|
|
|
||||||
note: required by a bound in `Foo::a`
|
|
||||||
--> $DIR/super-traits-fail-3.rs:8:25
|
|
||||||
|
|
|
||||||
LL | #[cfg_attr(any(yy, yn), const_trait)]
|
|
||||||
| ^^^^^^^^^^^ required by this bound in `Foo::a`
|
|
||||||
LL | trait Foo {
|
|
||||||
LL | fn a(&self);
|
|
||||||
| - required by a bound in this associated function
|
|
||||||
help: consider further restricting the associated type
|
|
||||||
|
|
|
||||||
LL | const fn foo<T: ~const Bar>(x: &T) where Foo::{synthetic#0}: ~const Compat {
|
|
||||||
| +++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -17,6 +17,6 @@ fn a(&self) {}
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl const Bar for S {}
|
impl const Bar for S {}
|
||||||
// FIXME(effects) bad span
|
//~^ ERROR the trait bound
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -1,11 +1,24 @@
|
|||||||
error[E0277]: the trait bound `Maybe: TyCompat<<(Foo::{synthetic#0},) as std::marker::effects::Intersection>::Output>` is not satisfied
|
error[E0277]: the trait bound `Bar::{synthetic#0}: TyCompat<Foo::{synthetic#0}>` is not satisfied
|
||||||
|
--> $DIR/super-traits-fail.rs:19:12
|
||||||
|
|
|
||||||
|
LL | impl const Bar for S {}
|
||||||
|
| ^^^ the trait `TyCompat<Foo::{synthetic#0}>` is not implemented for `Bar::{synthetic#0}`, which is required by `S: Bar`
|
||||||
|
|
|
||||||
|
= help: the trait `Bar` is implemented for `S`
|
||||||
|
note: required for `S` to implement `Bar`
|
||||||
|
--> $DIR/super-traits-fail.rs:12:7
|
||||||
|
|
|
||||||
|
LL | trait Bar: ~const Foo {}
|
||||||
|
| ^^^
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Maybe: TyCompat<Foo::{synthetic#0}>` is not satisfied
|
||||||
|
|
|
|
||||||
note: required by a bound in `Bar::{synthetic#0}`
|
note: required by a bound in `Bar::{synthetic#0}`
|
||||||
--> $DIR/super-traits-fail.rs:11:1
|
--> $DIR/super-traits-fail.rs:12:12
|
||||||
|
|
|
|
||||||
LL | #[const_trait]
|
LL | trait Bar: ~const Foo {}
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}`
|
| ^^^^^^^^^^ required by this bound in `Bar::{synthetic#0}`
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// FIXME(effects) check-pass
|
//@ check-pass
|
||||||
//@ known-bug: #110395
|
|
||||||
//@ compile-flags: -Znext-solver
|
//@ compile-flags: -Znext-solver
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![feature(const_trait_impl, effects)]
|
#![feature(const_trait_impl, effects)]
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
error[E0277]: the trait bound `Foo::{synthetic#0}: ~const Compat` is not satisfied
|
|
||||||
--> $DIR/super-traits.rs:23:7
|
|
||||||
|
|
|
||||||
LL | t.a();
|
|
||||||
| ^ the trait `~const Compat` is not implemented for `Foo::{synthetic#0}`
|
|
||||||
|
|
|
||||||
note: required by a bound in `Foo::a`
|
|
||||||
--> $DIR/super-traits.rs:7:1
|
|
||||||
|
|
|
||||||
LL | #[const_trait]
|
|
||||||
| ^^^^^^^^^^^^^^ required by this bound in `Foo::a`
|
|
||||||
LL | trait Foo {
|
|
||||||
LL | fn a(&self);
|
|
||||||
| - required by a bound in this associated function
|
|
||||||
help: consider further restricting the associated type
|
|
||||||
|
|
|
||||||
LL | const fn foo<T: ~const Bar>(t: &T) where Foo::{synthetic#0}: ~const Compat {
|
|
||||||
| +++++++++++++++++++++++++++++++++++++++
|
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
Loading…
Reference in New Issue
Block a user