Skip to content

Commit ee9c39a

Browse files
committed
Allow ~const on assoc ty bounds again
1 parent e927184 commit ee9c39a

13 files changed

+201
-65
lines changed

compiler/rustc_ast_passes/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,9 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here
232232
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
233233
.trait_impl = this impl is not `const`, so it cannot have `~const` trait bounds
234234
.impl = inherent impls cannot have `~const` trait bounds
235+
.trait_assoc_ty = associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
236+
.trait_impl_assoc_ty = associated types in non-const impls cannot have `~const` trait bounds
237+
.inherent_assoc_ty = inherent associated types cannot have `~const` trait bounds
235238
.object = trait objects cannot have `~const` trait bounds
236239
.item = this item cannot have `~const` trait bounds
237240

compiler/rustc_ast_passes/src/ast_validation.rs

+32-6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,17 @@ enum SelfSemantic {
3737
}
3838

3939
/// What is the context that prevents using `~const`?
40+
// FIXME(effects): Consider getting rid of this in favor of `errors::TildeConstReason`, they're
41+
// almost identical. This gets rid of an abstraction layer which might be considered bad.
4042
enum DisallowTildeConstContext<'a> {
4143
TraitObject,
4244
Fn(FnKind<'a>),
4345
Trait(Span),
4446
TraitImpl(Span),
4547
Impl(Span),
48+
TraitAssocTy(Span),
49+
TraitImplAssocTy(Span),
50+
InherentAssocTy(Span),
4651
Item,
4752
}
4853

@@ -316,6 +321,7 @@ impl<'a> AstValidator<'a> {
316321
constness: Const::No,
317322
polarity: ImplPolarity::Positive,
318323
trait_ref,
324+
..
319325
} = parent
320326
{
321327
Some(trait_ref.path.span.shrink_to_lo())
@@ -1286,6 +1292,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12861292
// suggestion for moving such bounds to the assoc const fns if available.
12871293
errors::TildeConstReason::Impl { span }
12881294
}
1295+
&DisallowTildeConstContext::TraitAssocTy(span) => {
1296+
errors::TildeConstReason::TraitAssocTy { span }
1297+
}
1298+
&DisallowTildeConstContext::TraitImplAssocTy(span) => {
1299+
errors::TildeConstReason::TraitImplAssocTy { span }
1300+
}
1301+
&DisallowTildeConstContext::InherentAssocTy(span) => {
1302+
errors::TildeConstReason::InherentAssocTy { span }
1303+
}
12891304
DisallowTildeConstContext::TraitObject => {
12901305
errors::TildeConstReason::TraitObject
12911306
}
@@ -1483,13 +1498,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14831498
self.check_item_named(item.ident, "const");
14841499
}
14851500

1501+
let parent_is_const =
1502+
self.outer_trait_or_trait_impl.as_ref().and_then(TraitOrTraitImpl::constness).is_some();
1503+
14861504
match &item.kind {
14871505
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
1488-
if self
1489-
.outer_trait_or_trait_impl
1490-
.as_ref()
1491-
.and_then(TraitOrTraitImpl::constness)
1492-
.is_some()
1506+
if parent_is_const
14931507
|| ctxt == AssocCtxt::Trait
14941508
|| matches!(sig.header.constness, Const::Yes(_)) =>
14951509
{
@@ -1505,7 +1519,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15051519
);
15061520
self.visit_fn(kind, item.span, item.id);
15071521
}
1508-
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
1522+
AssocItemKind::Type(_) => {
1523+
let disallowed = (!parent_is_const).then(|| match self.outer_trait_or_trait_impl {
1524+
Some(TraitOrTraitImpl::Trait { .. }) => {
1525+
DisallowTildeConstContext::TraitAssocTy(item.span)
1526+
}
1527+
Some(TraitOrTraitImpl::TraitImpl { .. }) => {
1528+
DisallowTildeConstContext::TraitImplAssocTy(item.span)
1529+
}
1530+
None => DisallowTildeConstContext::InherentAssocTy(item.span),
1531+
});
1532+
self.with_tilde_const(disallowed, |this| visit::walk_assoc_item(this, item, ctxt))
1533+
}
1534+
_ => visit::walk_assoc_item(self, item, ctxt),
15091535
}
15101536
}
15111537
}

compiler/rustc_ast_passes/src/errors.rs

+17
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@ pub struct ConstBoundTraitObject {
565565
pub span: Span,
566566
}
567567

568+
// FIXME(effects): Consider making the note/reason the message of the diagnostic.
569+
// FIXME(effects): Provide structured suggestions (e.g., add `const` / `#[const_trait]` here).
568570
#[derive(Diagnostic)]
569571
#[diag(ast_passes_tilde_const_disallowed)]
570572
pub struct TildeConstDisallowed {
@@ -598,6 +600,21 @@ pub enum TildeConstReason {
598600
#[primary_span]
599601
span: Span,
600602
},
603+
#[note(ast_passes_trait_assoc_ty)]
604+
TraitAssocTy {
605+
#[primary_span]
606+
span: Span,
607+
},
608+
#[note(ast_passes_trait_impl_assoc_ty)]
609+
TraitImplAssocTy {
610+
#[primary_span]
611+
span: Span,
612+
},
613+
#[note(ast_passes_inherent_assoc_ty)]
614+
InherentAssocTy {
615+
#[primary_span]
616+
span: Span,
617+
},
601618
#[note(ast_passes_object)]
602619
TraitObject,
603620
#[note(ast_passes_item)]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0277]: the trait bound `T: Trait` is not satisfied
2+
--> $DIR/assoc-type-const-bound-usage-0.rs:21:6
3+
|
4+
LL | <T as /* FIXME: ~const */ Trait>::Assoc::func()
5+
| ^ the trait `Trait` is not implemented for `T`
6+
|
7+
help: consider further restricting this bound
8+
|
9+
LL | const fn qualified<T: ~const Trait + Trait>() -> i32 {
10+
| +++++++
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// FIXME(effects): Collapse the revisions into one once we support `<Ty as ~const Trait>::Proj`.
2+
// revisions: unqualified qualified
3+
//[unqualified] check-pass
4+
//[qualified] known-bug: unknown
5+
6+
#![feature(const_trait_impl, effects)]
7+
8+
#[const_trait]
9+
trait Trait {
10+
type Assoc: ~const Trait;
11+
fn func() -> i32;
12+
}
13+
14+
#[cfg(unqualified)]
15+
const fn unqualified<T: ~const Trait>() -> i32 {
16+
T::Assoc::func()
17+
}
18+
19+
#[cfg(qualified)]
20+
const fn qualified<T: ~const Trait>() -> i32 {
21+
<T as /* FIXME: ~const */ Trait>::Assoc::func()
22+
}
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0277]: the trait bound `T: Trait` is not satisfied
2+
--> $DIR/assoc-type-const-bound-usage-1.rs:23:43
3+
|
4+
LL | fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
5+
| ^ the trait `Trait` is not implemented for `T`
6+
|
7+
help: consider further restricting this bound
8+
|
9+
LL | fn qualified<T: const Trait + Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
10+
| +++++++
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// FIXME(effects): Collapse the revisions into one once we support `<Ty as const Trait>::Proj`.
2+
// revisions: unqualified qualified
3+
//[unqualified] check-pass
4+
//[qualified] known-bug: unknown
5+
6+
#![feature(const_trait_impl, effects, generic_const_exprs)]
7+
#![allow(incomplete_features)]
8+
9+
#[const_trait]
10+
trait Trait {
11+
type Assoc: ~const Trait;
12+
fn func() -> i32;
13+
}
14+
15+
struct Type<const N: i32>;
16+
17+
#[cfg(unqualified)]
18+
fn unqualified<T: const Trait>() -> Type<{ T::Assoc::func() }> {
19+
Type
20+
}
21+
22+
#[cfg(qualified)]
23+
fn qualified<T: const Trait>() -> Type<{ <T as /* FIXME: const */ Trait>::Assoc::func() }> {
24+
Type
25+
}
26+
27+
fn main() {}

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.rs

-15
This file was deleted.

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type-const-bound-usage.stderr

-22
This file was deleted.

tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,43 @@
1-
// known-bug: #110395
1+
// FIXME(effects): Replace `Add` with `std::ops::Add` once the latter a `#[const_trait]` again.
2+
#![feature(const_trait_impl, effects)]
23

3-
#![feature(const_trait_impl)]
4+
#[const_trait]
5+
trait Add<Rhs = Self> {
6+
type Output;
7+
8+
fn add(self, other: Rhs) -> Self::Output;
9+
}
10+
11+
impl const Add for i32 {
12+
type Output = Self;
13+
14+
fn add(self, other: Self) -> Self::Output {
15+
self + other
16+
}
17+
}
418

519
struct NonConstAdd(i32);
620

7-
impl std::ops::Add for NonConstAdd {
21+
impl Add for NonConstAdd {
822
type Output = Self;
923

1024
fn add(self, rhs: Self) -> Self {
11-
NonConstAdd(self.0 + rhs.0)
25+
NonConstAdd(self.0.add(rhs.0))
1226
}
1327
}
1428

1529
#[const_trait]
1630
trait Foo {
17-
type Bar: ~const std::ops::Add;
31+
type Bar: ~const Add;
1832
}
1933

2034
impl const Foo for NonConstAdd {
21-
type Bar = NonConstAdd;
35+
type Bar = NonConstAdd; //~ ERROR the trait bound `NonConstAdd: ~const Add` is not satisfied
2236
}
2337

2438
#[const_trait]
2539
trait Baz {
26-
type Qux: std::ops::Add;
40+
type Qux: Add;
2741
}
2842

2943
impl const Baz for NonConstAdd {
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
error: `~const` is not allowed here
2-
--> $DIR/assoc-type.rs:17:15
1+
error[E0277]: the trait bound `NonConstAdd: ~const Add` is not satisfied
2+
--> $DIR/assoc-type.rs:35:16
33
|
4-
LL | type Bar: ~const std::ops::Add;
5-
| ^^^^^^
4+
LL | type Bar = NonConstAdd;
5+
| ^^^^^^^^^^^ the trait `~const Add` is not implemented for `NonConstAdd`
66
|
7-
= note: this item cannot have `~const` trait bounds
8-
9-
error: `~const` can only be applied to `#[const_trait]` traits
10-
--> $DIR/assoc-type.rs:17:22
7+
= help: the trait `Add` is implemented for `NonConstAdd`
8+
note: required by a bound in `Foo::Bar`
9+
--> $DIR/assoc-type.rs:31:15
1110
|
12-
LL | type Bar: ~const std::ops::Add;
13-
| ^^^^^^^^^^^^^
11+
LL | type Bar: ~const Add;
12+
| ^^^^^^^^^^ required by this bound in `Foo::Bar`
1413

15-
error: aborting due to 2 previous errors
14+
error: aborting due to 1 previous error
1615

16+
For more information about this error, try `rustc --explain E0277`.

tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-invalid-places.stderr

+20-4
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,23 @@ error: `~const` is not allowed here
7272
LL | type Type<T: ~const Trait>: ~const Trait;
7373
| ^^^^^^
7474
|
75-
= note: this item cannot have `~const` trait bounds
75+
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
76+
--> $DIR/tilde-const-invalid-places.rs:25:5
77+
|
78+
LL | type Type<T: ~const Trait>: ~const Trait;
79+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
7680

7781
error: `~const` is not allowed here
7882
--> $DIR/tilde-const-invalid-places.rs:25:33
7983
|
8084
LL | type Type<T: ~const Trait>: ~const Trait;
8185
| ^^^^^^
8286
|
83-
= note: this item cannot have `~const` trait bounds
87+
note: associated types in non-`#[const_trait]` traits cannot have `~const` trait bounds
88+
--> $DIR/tilde-const-invalid-places.rs:25:5
89+
|
90+
LL | type Type<T: ~const Trait>: ~const Trait;
91+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8492

8593
error: `~const` is not allowed here
8694
--> $DIR/tilde-const-invalid-places.rs:28:30
@@ -108,7 +116,11 @@ error: `~const` is not allowed here
108116
LL | type Type<T: ~const Trait> = ();
109117
| ^^^^^^
110118
|
111-
= note: this item cannot have `~const` trait bounds
119+
note: associated types in non-const impls cannot have `~const` trait bounds
120+
--> $DIR/tilde-const-invalid-places.rs:34:5
121+
|
122+
LL | type Type<T: ~const Trait> = ();
123+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
112124

113125
error: `~const` is not allowed here
114126
--> $DIR/tilde-const-invalid-places.rs:36:30
@@ -136,7 +148,11 @@ error: `~const` is not allowed here
136148
LL | type Type<T: ~const Trait> = ();
137149
| ^^^^^^
138150
|
139-
= note: this item cannot have `~const` trait bounds
151+
note: inherent associated types cannot have `~const` trait bounds
152+
--> $DIR/tilde-const-invalid-places.rs:44:5
153+
|
154+
LL | type Type<T: ~const Trait> = ();
155+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
140156

141157
error: `~const` is not allowed here
142158
--> $DIR/tilde-const-invalid-places.rs:46:30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// check-pass
2+
#![feature(const_trait_impl, effects)]
3+
4+
#[const_trait]
5+
trait Trait {
6+
// FIXME(effects): `~const` bounds in trait associated types (excluding associated type bounds)
7+
// don't look super useful. Should we forbid them again?
8+
type Assoc<T: ~const Bound>;
9+
}
10+
11+
impl const Trait for () {
12+
type Assoc<T: ~const Bound> = T;
13+
}
14+
15+
#[const_trait]
16+
trait Bound {}
17+
18+
fn main() {}

0 commit comments

Comments
 (0)