Allow ~const
on assoc ty bounds again
This commit is contained in:
parent
e927184629
commit
f28373978e
@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
|
|||||||
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
|
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
|
||||||
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
|
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
|
||||||
.impl = inherent impls cannot have `~const` trait bounds
|
.impl = inherent impls cannot have `~const` trait bounds
|
||||||
|
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
|
||||||
|
.trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
|
||||||
|
.inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
|
||||||
.object = trait objects cannot have `~const` trait bounds
|
.object = trait objects cannot have `~const` trait bounds
|
||||||
.item = this item cannot have `~const` trait bounds
|
.item = this item cannot have `~const` trait bounds
|
||||||
|
|
||||||
|
@ -37,12 +37,17 @@ enum SelfSemantic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// What is the context that prevents using `~const`?
|
/// What is the context that prevents using `~const`?
|
||||||
|
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
|
||||||
|
// almost identical. This gets rid of an abstraction layer which might be considered bad.
|
||||||
enum DisallowTildeConstContext<'a> {
|
enum DisallowTildeConstContext<'a> {
|
||||||
TraitObject,
|
TraitObject,
|
||||||
Fn(FnKind<'a>),
|
Fn(FnKind<'a>),
|
||||||
Trait(Span),
|
Trait(Span),
|
||||||
TraitImpl(Span),
|
TraitImpl(Span),
|
||||||
Impl(Span),
|
Impl(Span),
|
||||||
|
TraitAssocTy(Span),
|
||||||
|
TraitImplAssocTy(Span),
|
||||||
|
InherentAssocTy(Span),
|
||||||
Item,
|
Item,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
constness: Const::No,
|
constness: Const::No,
|
||||||
polarity: ImplPolarity::Positive,
|
polarity: ImplPolarity::Positive,
|
||||||
trait_ref,
|
trait_ref,
|
||||||
|
..
|
||||||
} = parent
|
} = parent
|
||||||
{
|
{
|
||||||
Some(trait_ref.path.span.shrink_to_lo())
|
Some(trait_ref.path.span.shrink_to_lo())
|
||||||
@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
// suggestion for moving such bounds to the assoc const fns if available.
|
// suggestion for moving such bounds to the assoc const fns if available.
|
||||||
errors::TildeConstReason::Impl { span }
|
errors::TildeConstReason::Impl { span }
|
||||||
}
|
}
|
||||||
|
&DisallowTildeConstContext::TraitAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::TraitAssocTy { span }
|
||||||
|
}
|
||||||
|
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::TraitImplAssocTy { span }
|
||||||
|
}
|
||||||
|
&DisallowTildeConstContext::InherentAssocTy(span) => {
|
||||||
|
errors::TildeConstReason::InherentAssocTy { span }
|
||||||
|
}
|
||||||
DisallowTildeConstContext::TraitObject => {
|
DisallowTildeConstContext::TraitObject => {
|
||||||
errors::TildeConstReason::TraitObject
|
errors::TildeConstReason::TraitObject
|
||||||
}
|
}
|
||||||
@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
self.check_item_named(item.ident, "const");
|
self.check_item_named(item.ident, "const");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let parent_is_const =
|
||||||
|
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
|
||||||
|
|
||||||
match &item.kind {
|
match &item.kind {
|
||||||
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
|
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
|
||||||
if self
|
if parent_is_const
|
||||||
.outer_trait_or_trait_impl
|
|
||||||
.as_ref()
|
|
||||||
.and_then(TraitOrTraitImpl::constness)
|
|
||||||
.is_some()
|
|
||||||
|| ctxt == AssocCtxt::Trait
|
|| ctxt == AssocCtxt::Trait
|
||||||
|| matches!(sig.header.constness, Const::Yes(_)) =>
|
|| matches!(sig.header.constness, Const::Yes(_)) =>
|
||||||
{
|
{
|
||||||
@ -1505,6 +1519,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
);
|
);
|
||||||
self.visit_fn(kind, item.span, item.id);
|
self.visit_fn(kind, item.span, item.id);
|
||||||
}
|
}
|
||||||
|
AssocItemKind::Type(_) => {
|
||||||
|
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
|
||||||
|
Some(TraitOrTraitImpl::Trait { .. }) => {
|
||||||
|
DisallowTildeConstContext::TraitAssocTy(item.span)
|
||||||
|
}
|
||||||
|
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
|
||||||
|
DisallowTildeConstContext::TraitImplAssocTy(item.span)
|
||||||
|
}
|
||||||
|
None => DisallowTildeConstContext::InherentAssocTy(item.span),
|
||||||
|
});
|
||||||
|
self.with_tilde_const(disallowed, |this| {
|
||||||
|
this.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt))
|
||||||
|
})
|
||||||
|
}
|
||||||
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
|
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(effects): Consider making the note/reason the message of the diagnostic.
|
||||||
|
// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(ast_passes_tilde_const_disallowed)]
|
#[diag(ast_passes_tilde_const_disallowed)]
|
||||||
pub struct TildeConstDisallowed {
|
pub struct TildeConstDisallowed {
|
||||||
@ -598,6 +600,21 @@ pub enum TildeConstReason {
|
|||||||
#[primary_span]
|
#[primary_span]
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
|
#[note(ast_passes_trait_assoc_ty)]
|
||||||
|
TraitAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[note(ast_passes_trait_impl_assoc_ty)]
|
||||||
|
TraitImplAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[note(ast_passes_inherent_assoc_ty)]
|
||||||
|
InherentAssocTy {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
#[note(ast_passes_object)]
|
#[note(ast_passes_object)]
|
||||||
TraitObject,
|
TraitObject,
|
||||||
#[note(ast_passes_item)]
|
#[note(ast_passes_item)]
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
error[E0277]: the trait bound `T: Trait` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-0.rs:21:6
|
||||||
|
|
|
||||||
|
LL | <T as /* FIXME: ~const */ Trait>::Assoc::func()
|
||||||
|
| ^ the trait `Trait` is not implemented for `T`
|
||||||
|
|
|
||||||
|
help: consider further restricting this bound
|
||||||
|
|
|
||||||
|
LL | const fn qualified<T: ~const Trait + Trait>() -> i32 {
|
||||||
|
| +++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,24 @@
|
|||||||
|
// FIXME(effects): Collapse the revisions into one once we support `<Ty as ~const Trait>::Proj`.
|
||||||
|
// revisions: unqualified qualified
|
||||||
|
//[unqualified] check-pass
|
||||||
|
//[qualified] known-bug: unknown
|
||||||
|
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
trait Trait {
|
||||||
|
type Assoc: ~const Trait;
|
||||||
|
fn func() -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unqualified)]
|
||||||
|
const fn unqualified<T: ~const Trait>() -> i32 {
|
||||||
|
T::Assoc::func()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(qualified)]
|
||||||
|
const fn qualified<T: ~const Trait>() -> i32 {
|
||||||
|
<T as /* FIXME: ~const */ Trait>::Assoc::func()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -0,0 +1,14 @@
|
|||||||
|
error[E0277]: the trait bound `T: Trait` is not satisfied
|
||||||
|
--> $DIR/assoc-type-const-bound-usage-1.rs:23:43
|
||||||
|
|
|
||||||
|
LL | fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
||||||
|
| ^ the trait `Trait` is not implemented for `T`
|
||||||
|
|
|
||||||
|
help: consider further restricting this bound
|
||||||
|
|
|
||||||
|
LL | fn qualified<T: const Trait + Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
||||||
|
| +++++++
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
@ -0,0 +1,27 @@
|
|||||||
|
// FIXME(effects): Collapse the revisions into one once we support `<Ty as const Trait>::Proj`.
|
||||||
|
// revisions: unqualified qualified
|
||||||
|
//[unqualified] check-pass
|
||||||
|
//[qualified] known-bug: unknown
|
||||||
|
|
||||||
|
#![feature(const_trait_impl, effects, generic_const_exprs)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
trait Trait {
|
||||||
|
type Assoc: ~const Trait;
|
||||||
|
fn func() -> i32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Type<const N: i32>;
|
||||||
|
|
||||||
|
#[cfg(unqualified)]
|
||||||
|
fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
|
||||||
|
Type
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(qualified)]
|
||||||
|
fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
|
||||||
|
Type
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
@ -1,15 +0,0 @@
|
|||||||
// known-bug: #110395
|
|
||||||
// FIXME check-pass
|
|
||||||
#![feature(const_trait_impl, effects)]
|
|
||||||
|
|
||||||
#[const_trait]
|
|
||||||
trait Foo {
|
|
||||||
type Assoc: ~const Foo;
|
|
||||||
fn foo() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
const fn foo<T: ~const Foo>() {
|
|
||||||
<T as /* FIXME: ~const */ Foo>::Assoc::foo();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
@ -1,22 +0,0 @@
|
|||||||
error: `~const` is not allowed here
|
|
||||||
--> $DIR/assoc-type-const-bound-usage.rs:7:17
|
|
||||||
|
|
|
||||||
LL | type Assoc: ~const Foo;
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `T: Foo` is not satisfied
|
|
||||||
--> $DIR/assoc-type-const-bound-usage.rs:12:6
|
|
||||||
|
|
|
||||||
LL | <T as /* FIXME: ~const */ Foo>::Assoc::foo();
|
|
||||||
| ^ the trait `Foo` is not implemented for `T`
|
|
||||||
|
|
|
||||||
help: consider further restricting this bound
|
|
||||||
|
|
|
||||||
LL | const fn foo<T: ~const Foo + Foo>() {
|
|
||||||
| +++++
|
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,29 +1,43 @@
|
|||||||
// known-bug: #110395
|
// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again.
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
#![feature(const_trait_impl)]
|
#[const_trait]
|
||||||
|
trait Add<Rhs = Self> {
|
||||||
|
type Output;
|
||||||
|
|
||||||
|
fn add(self, other: Rhs) -> Self::Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Add for i32 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn add(self, other: Self) -> Self::Output {
|
||||||
|
self + other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct NonConstAdd(i32);
|
struct NonConstAdd(i32);
|
||||||
|
|
||||||
impl std::ops::Add for NonConstAdd {
|
impl Add for NonConstAdd {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, rhs: Self) -> Self {
|
fn add(self, rhs: Self) -> Self {
|
||||||
NonConstAdd(self.0 + rhs.0)
|
NonConstAdd(self.0.add(rhs.0))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Foo {
|
trait Foo {
|
||||||
type Bar: ~const std::ops::Add;
|
type Bar: ~const Add;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const Foo for NonConstAdd {
|
impl const Foo for NonConstAdd {
|
||||||
type Bar = NonConstAdd;
|
type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
|
||||||
}
|
}
|
||||||
|
|
||||||
#[const_trait]
|
#[const_trait]
|
||||||
trait Baz {
|
trait Baz {
|
||||||
type Qux: std::ops::Add;
|
type Qux: Add;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl const Baz for NonConstAdd {
|
impl const Baz for NonConstAdd {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
error: `~const` is not allowed here
|
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
|
||||||
--> $DIR/assoc-type.rs:17:15
|
--> $DIR/assoc-type.rs:35:16
|
||||||
|
|
|
|
||||||
LL | type Bar: ~const std::ops::Add;
|
LL | type Bar = NonConstAdd;
|
||||||
| ^^^^^^
|
| ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd`
|
||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
= help: the trait `Add` is implemented for `NonConstAdd`
|
||||||
|
note: required by a bound in `Foo::Bar`
|
||||||
error: `~const` can only be applied to `#[const_trait]` traits
|
--> $DIR/assoc-type.rs:31:15
|
||||||
--> $DIR/assoc-type.rs:17:22
|
|
||||||
|
|
|
|
||||||
LL | type Bar: ~const std::ops::Add;
|
LL | type Bar: ~const Add;
|
||||||
| ^^^^^^^^^^^^^
|
| ^^^^^^^^^^ required by this bound in `Foo::Bar`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
@ -72,7 +72,11 @@ error: `~const` is not allowed here
|
|||||||
LL | type Type<T: ~const Trait>: ~const Trait;
|
LL | type Type<T: ~const Trait>: ~const Trait;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
|
||||||
|
--> $DIR/tilde-const-invalid-places.rs:25:5
|
||||||
|
|
|
||||||
|
LL | type Type<T: ~const Trait>: ~const Trait;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:25:33
|
--> $DIR/tilde-const-invalid-places.rs:25:33
|
||||||
@ -80,7 +84,11 @@ error: `~const` is not allowed here
|
|||||||
LL | type Type<T: ~const Trait>: ~const Trait;
|
LL | type Type<T: ~const Trait>: ~const Trait;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
|
||||||
|
--> $DIR/tilde-const-invalid-places.rs:25:5
|
||||||
|
|
|
||||||
|
LL | type Type<T: ~const Trait>: ~const Trait;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:28:30
|
--> $DIR/tilde-const-invalid-places.rs:28:30
|
||||||
@ -108,7 +116,11 @@ error: `~const` is not allowed here
|
|||||||
LL | type Type<T: ~const Trait> = ();
|
LL | type Type<T: ~const Trait> = ();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
note: associated types in non-const impls cannot have `~const` trait bounds
|
||||||
|
--> $DIR/tilde-const-invalid-places.rs:34:5
|
||||||
|
|
|
||||||
|
LL | type Type<T: ~const Trait> = ();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:36:30
|
--> $DIR/tilde-const-invalid-places.rs:36:30
|
||||||
@ -136,7 +148,11 @@ error: `~const` is not allowed here
|
|||||||
LL | type Type<T: ~const Trait> = ();
|
LL | type Type<T: ~const Trait> = ();
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
= note: this item cannot have `~const` trait bounds
|
note: inherent associated types cannot have `~const` trait bounds
|
||||||
|
--> $DIR/tilde-const-invalid-places.rs:44:5
|
||||||
|
|
|
||||||
|
LL | type Type<T: ~const Trait> = ();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: `~const` is not allowed here
|
error: `~const` is not allowed here
|
||||||
--> $DIR/tilde-const-invalid-places.rs:46:30
|
--> $DIR/tilde-const-invalid-places.rs:46:30
|
||||||
|
@ -0,0 +1,18 @@
|
|||||||
|
// check-pass
|
||||||
|
#![feature(const_trait_impl, effects)]
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
trait Trait {
|
||||||
|
// FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds)
|
||||||
|
// don't look super useful. Should we forbid them again?
|
||||||
|
type Assoc<T: ~const Bound>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl const Trait for () {
|
||||||
|
type Assoc<T: ~const Bound> = T;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[const_trait]
|
||||||
|
trait Bound {}
|
||||||
|
|
||||||
|
fn main() {}
|
Loading…
x
Reference in New Issue
Block a user