Skip to content

Commit e4a69c1

Browse files
committed
Auto merge of #116210 - Raekye:master, r=fee1-dead
Ensure that `~const` trait bounds on associated functions are in const traits or impls Zulip discussion: https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/topic/How.20to.2Fshould.20I.20try.20to.20pinpoint.20ICEs.20related.20to.20effects.3F
2 parents 7c3eeb9 + 884af36 commit e4a69c1

7 files changed

+139
-34
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+34-22
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ struct AstValidator<'a> {
5252
/// Are we inside a trait impl?
5353
in_trait_impl: bool,
5454

55-
in_const_trait_impl: bool,
55+
/// Are we inside a const trait defn or impl?
56+
in_const_trait_or_impl: bool,
5657

5758
has_proc_macro_decls: bool,
5859

@@ -78,11 +79,19 @@ impl<'a> AstValidator<'a> {
7879
f: impl FnOnce(&mut Self),
7980
) {
8081
let old = mem::replace(&mut self.in_trait_impl, is_in);
81-
let old_const =
82-
mem::replace(&mut self.in_const_trait_impl, matches!(constness, Some(Const::Yes(_))));
82+
let old_const = mem::replace(
83+
&mut self.in_const_trait_or_impl,
84+
matches!(constness, Some(Const::Yes(_))),
85+
);
8386
f(self);
8487
self.in_trait_impl = old;
85-
self.in_const_trait_impl = old_const;
88+
self.in_const_trait_or_impl = old_const;
89+
}
90+
91+
fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) {
92+
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
93+
f(self);
94+
self.in_const_trait_or_impl = old;
8695
}
8796

8897
fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
@@ -933,23 +942,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
933942
}
934943
}
935944
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
936-
if *is_auto == IsAuto::Yes {
937-
// Auto traits cannot have generics, super traits nor contain items.
938-
self.deny_generic_params(generics, item.ident.span);
939-
self.deny_super_traits(bounds, item.ident.span);
940-
self.deny_where_clause(&generics.where_clause, item.ident.span);
941-
self.deny_items(items, item.ident.span);
942-
}
945+
let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
946+
self.with_in_trait(is_const_trait, |this| {
947+
if *is_auto == IsAuto::Yes {
948+
// Auto traits cannot have generics, super traits nor contain items.
949+
this.deny_generic_params(generics, item.ident.span);
950+
this.deny_super_traits(bounds, item.ident.span);
951+
this.deny_where_clause(&generics.where_clause, item.ident.span);
952+
this.deny_items(items, item.ident.span);
953+
}
943954

944-
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
945-
// context for the supertraits.
946-
self.visit_vis(&item.vis);
947-
self.visit_ident(item.ident);
948-
self.visit_generics(generics);
949-
self.with_tilde_const_allowed(|this| {
950-
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
955+
// Equivalent of `visit::walk_item` for `ItemKind::Trait` that inserts a bound
956+
// context for the supertraits.
957+
this.visit_vis(&item.vis);
958+
this.visit_ident(item.ident);
959+
this.visit_generics(generics);
960+
this.with_tilde_const_allowed(|this| {
961+
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
962+
});
963+
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
951964
});
952-
walk_list!(self, visit_assoc_item, items, AssocCtxt::Trait);
953965
walk_list!(self, visit_attribute, &item.attrs);
954966
return; // Avoid visiting again
955967
}
@@ -1278,7 +1290,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12781290

12791291
let tilde_const_allowed =
12801292
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
1281-
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)));
1293+
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
12821294

12831295
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
12841296

@@ -1363,7 +1375,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13631375
walk_list!(self, visit_ty, ty);
13641376
}
13651377
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
1366-
if self.in_const_trait_impl
1378+
if self.in_const_trait_or_impl
13671379
|| ctxt == AssocCtxt::Trait
13681380
|| matches!(sig.header.constness, Const::Yes(_)) =>
13691381
{
@@ -1510,7 +1522,7 @@ pub fn check_crate(
15101522
features,
15111523
extern_mod: None,
15121524
in_trait_impl: false,
1513-
in_const_trait_impl: false,
1525+
in_const_trait_or_impl: false,
15141526
has_proc_macro_decls: false,
15151527
outer_impl_trait: None,
15161528
disallow_tilde_const: None,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![feature(const_trait_impl, effects)]
2+
3+
#[const_trait]
4+
trait MyTrait {
5+
fn do_something(&self);
6+
}
7+
8+
trait OtherTrait {
9+
fn do_something_else() where Self: ~const MyTrait;
10+
//~^ ERROR `~const` is not allowed here
11+
}
12+
13+
struct MyStruct<T>(T);
14+
15+
impl const MyTrait for u32 {
16+
fn do_something(&self) {}
17+
}
18+
19+
impl<T> MyStruct<T> {
20+
pub fn foo(&self) where T: ~const MyTrait {
21+
//~^ ERROR `~const` is not allowed here
22+
self.0.do_something();
23+
}
24+
}
25+
26+
fn main() {
27+
MyStruct(0u32).foo();
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: `~const` is not allowed here
2+
--> $DIR/const-bound-on-not-const-associated-fn.rs:9:40
3+
|
4+
LL | fn do_something_else() where Self: ~const MyTrait;
5+
| ^^^^^^^^^^^^^^
6+
|
7+
note: this function is not `const`, so it cannot have `~const` trait bounds
8+
--> $DIR/const-bound-on-not-const-associated-fn.rs:9:8
9+
|
10+
LL | fn do_something_else() where Self: ~const MyTrait;
11+
| ^^^^^^^^^^^^^^^^^
12+
13+
error: `~const` is not allowed here
14+
--> $DIR/const-bound-on-not-const-associated-fn.rs:20:32
15+
|
16+
LL | pub fn foo(&self) where T: ~const MyTrait {
17+
| ^^^^^^^^^^^^^^
18+
|
19+
note: this function is not `const`, so it cannot have `~const` trait bounds
20+
--> $DIR/const-bound-on-not-const-associated-fn.rs:20:12
21+
|
22+
LL | pub fn foo(&self) where T: ~const MyTrait {
23+
| ^^^
24+
25+
error: aborting due to 2 previous errors
26+

tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ struct Foo<const N: usize>;
77

88
impl<const N: usize> Foo<N> {
99
fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
10-
//~^ ERROR mismatched types
10+
//~^ ERROR `~const` is not allowed here
11+
//~| ERROR mismatched types
1112
Foo
1213
}
1314
}
@@ -30,7 +31,7 @@ fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
3031
}
3132

3233
fn main() {
33-
let foo = Foo::<0>;
34-
let foo = bar::<(), _>(foo);
35-
let _foo = bar::<(), _>(foo);
34+
let foo = Foo::<0>;
35+
let foo = bar::<(), _>(foo);
36+
let _foo = bar::<(), _>(foo);
3637
}

tests/ui/rfcs/rfc-2632-const-trait-impl/tilde-const-and-const-params.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,29 @@
11
error: `~const` is not allowed here
2-
--> $DIR/tilde-const-and-const-params.rs:26:11
2+
--> $DIR/tilde-const-and-const-params.rs:9:15
3+
|
4+
LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
5+
| ^^^^^^^^^^^^
6+
|
7+
note: this function is not `const`, so it cannot have `~const` trait bounds
8+
--> $DIR/tilde-const-and-const-params.rs:9:8
9+
|
10+
LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
11+
| ^^^
12+
13+
error: `~const` is not allowed here
14+
--> $DIR/tilde-const-and-const-params.rs:27:11
315
|
416
LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
517
| ^^^^^^^^^^^^
618
|
719
note: this function is not `const`, so it cannot have `~const` trait bounds
8-
--> $DIR/tilde-const-and-const-params.rs:26:4
20+
--> $DIR/tilde-const-and-const-params.rs:27:4
921
|
1022
LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
1123
| ^^^
1224

1325
error[E0308]: mismatched types
14-
--> $DIR/tilde-const-and-const-params.rs:26:61
26+
--> $DIR/tilde-const-and-const-params.rs:27:61
1527
|
1628
LL | fn bar<A: ~const Add42, const N: usize>(_: Foo<N>) -> Foo<{ A::add(N) }> {
1729
| ^^^^^^^^^ expected `false`, found `true`
@@ -28,6 +40,6 @@ LL | fn add<A: ~const Add42>(self) -> Foo<{ A::add(N) }> {
2840
= note: expected constant `false`
2941
found constant `true`
3042

31-
error: aborting due to 3 previous errors
43+
error: aborting due to 4 previous errors
3244

3345
For more information about this error, try `rustc --explain E0308`.

tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ trait Bar {}
66
trait Foo {
77
fn a();
88
fn b() where Self: ~const Bar;
9+
//~^ ERROR `~const` is not allowed here
910
fn c<T: ~const Bar>();
11+
//~^ ERROR `~const` is not allowed here
1012
}
1113

1214
fn test1<T: Foo>() {

tests/ui/rfcs/rfc-2632-const-trait-impl/trait-where-clause.stderr

+28-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
1+
error: `~const` is not allowed here
2+
--> $DIR/trait-where-clause.rs:8:24
3+
|
4+
LL | fn b() where Self: ~const Bar;
5+
| ^^^^^^^^^^
6+
|
7+
note: this function is not `const`, so it cannot have `~const` trait bounds
8+
--> $DIR/trait-where-clause.rs:8:8
9+
|
10+
LL | fn b() where Self: ~const Bar;
11+
| ^
12+
13+
error: `~const` is not allowed here
14+
--> $DIR/trait-where-clause.rs:10:13
15+
|
16+
LL | fn c<T: ~const Bar>();
17+
| ^^^^^^^^^^
18+
|
19+
note: this function is not `const`, so it cannot have `~const` trait bounds
20+
--> $DIR/trait-where-clause.rs:10:8
21+
|
22+
LL | fn c<T: ~const Bar>();
23+
| ^
24+
125
error[E0277]: the trait bound `T: Bar` is not satisfied
2-
--> $DIR/trait-where-clause.rs:14:5
26+
--> $DIR/trait-where-clause.rs:16:5
327
|
428
LL | T::b();
529
| ^ the trait `Bar` is not implemented for `T`
@@ -15,13 +39,13 @@ LL | fn test1<T: Foo + Bar>() {
1539
| +++++
1640

1741
error[E0277]: the trait bound `T: Bar` is not satisfied
18-
--> $DIR/trait-where-clause.rs:16:12
42+
--> $DIR/trait-where-clause.rs:18:12
1943
|
2044
LL | T::c::<T>();
2145
| ^ the trait `Bar` is not implemented for `T`
2246
|
2347
note: required by a bound in `Foo::c`
24-
--> $DIR/trait-where-clause.rs:9:13
48+
--> $DIR/trait-where-clause.rs:10:13
2549
|
2650
LL | fn c<T: ~const Bar>();
2751
| ^^^^^^^^^^ required by this bound in `Foo::c`
@@ -30,6 +54,6 @@ help: consider further restricting this bound
3054
LL | fn test1<T: Foo + Bar>() {
3155
| +++++
3256

33-
error: aborting due to 2 previous errors
57+
error: aborting due to 4 previous errors
3458

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

0 commit comments

Comments
 (0)