Skip to content

Commit e345737

Browse files
committed
Deny more ~const trait bounds
1 parent 9ab0749 commit e345737

25 files changed

+500
-133
lines changed

compiler/rustc_ast_passes/messages.ftl

+4-1
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,12 @@ ast_passes_static_without_body =
214214
.suggestion = provide a definition for the static
215215
216216
ast_passes_tilde_const_disallowed = `~const` is not allowed here
217-
.trait = trait objects cannot have `~const` trait bounds
218217
.closure = closures cannot have `~const` trait bounds
219218
.function = this function is not `const`, so it cannot have `~const` trait bounds
219+
.trait = this trait is not a `#[const_trait]`, so it cannot have `~const` trait bounds
220+
.impl = this impl is not `const`, so it cannot have `~const` trait bounds
221+
.object = trait objects cannot have `~const` trait bounds
222+
.item = this item cannot have `~const` trait bounds
220223
221224
ast_passes_trait_fn_const =
222225
functions in traits cannot be declared const

compiler/rustc_ast_passes/src/ast_validation.rs

+86-44
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ enum SelfSemantic {
4040
enum DisallowTildeConstContext<'a> {
4141
TraitObject,
4242
Fn(FnKind<'a>),
43+
Trait(Span),
44+
Impl(Span),
45+
Item,
4346
}
4447

4548
struct AstValidator<'a> {
@@ -110,10 +113,6 @@ impl<'a> AstValidator<'a> {
110113
self.disallow_tilde_const = old;
111114
}
112115

113-
fn with_tilde_const_allowed(&mut self, f: impl FnOnce(&mut Self)) {
114-
self.with_tilde_const(None, f)
115-
}
116-
117116
fn with_banned_tilde_const(
118117
&mut self,
119118
ctx: DisallowTildeConstContext<'a>,
@@ -822,11 +821,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
822821

823822
this.visit_vis(&item.vis);
824823
this.visit_ident(item.ident);
825-
if let Const::Yes(_) = constness {
826-
this.with_tilde_const_allowed(|this| this.visit_generics(generics));
827-
} else {
828-
this.visit_generics(generics);
829-
}
824+
let disallowed = matches!(constness, Const::No)
825+
.then(|| DisallowTildeConstContext::Impl(item.span));
826+
this.with_tilde_const(disallowed, |this| this.visit_generics(generics));
830827
this.visit_trait_ref(t);
831828
this.visit_ty(self_ty);
832829

@@ -926,7 +923,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
926923
self.extern_mod = old_item;
927924
return; // Avoid visiting again.
928925
}
929-
ItemKind::Enum(def, _) => {
926+
ItemKind::Enum(def, generics) => {
927+
self.visit_vis(&item.vis);
928+
self.visit_ident(item.ident);
929+
930+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
931+
this.visit_generics(generics)
932+
});
933+
930934
for variant in &def.variants {
931935
self.visibility_not_permitted(
932936
&variant.vis,
@@ -939,6 +943,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
939943
);
940944
}
941945
}
946+
walk_list!(self, visit_variant, &def.variants);
947+
walk_list!(self, visit_attribute, &item.attrs);
948+
return; // Avoid visiting again
942949
}
943950
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
944951
let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
@@ -955,8 +962,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
955962
// context for the supertraits.
956963
this.visit_vis(&item.vis);
957964
this.visit_ident(item.ident);
958-
this.visit_generics(generics);
959-
this.with_tilde_const_allowed(|this| {
965+
let disallowed =
966+
(!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span));
967+
this.with_tilde_const(disallowed, |this| {
968+
this.visit_generics(generics);
960969
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
961970
});
962971
walk_list!(this, visit_assoc_item, items, AssocCtxt::Trait);
@@ -975,23 +984,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
975984
self.check_mod_file_item_asciionly(item.ident);
976985
}
977986
}
978-
ItemKind::Struct(vdata, generics) => match vdata {
979-
// Duplicating the `Visitor` logic allows catching all cases
980-
// of `Anonymous(Struct, Union)` outside of a field struct or union.
981-
//
982-
// Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
983-
// encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
984-
// it uses `visit_ty_common`, which doesn't contain that specific check.
985-
VariantData::Struct(fields, ..) => {
986-
self.visit_vis(&item.vis);
987-
self.visit_ident(item.ident);
988-
self.visit_generics(generics);
989-
walk_list!(self, visit_struct_field_def, fields);
990-
walk_list!(self, visit_attribute, &item.attrs);
991-
return;
987+
ItemKind::Struct(vdata, generics) => {
988+
self.visit_vis(&item.vis);
989+
self.visit_ident(item.ident);
990+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
991+
this.visit_generics(generics)
992+
});
993+
walk_list!(self, visit_attribute, &item.attrs);
994+
995+
match vdata {
996+
// Permit `Anon{Struct,Union}` as field type.
997+
VariantData::Struct(fields, ..) => {
998+
walk_list!(self, visit_struct_field_def, fields)
999+
}
1000+
_ => self.visit_variant_data(vdata),
9921001
}
993-
_ => {}
994-
},
1002+
return; // Avoid visiting again-
1003+
}
9951004
ItemKind::Union(vdata, generics) => {
9961005
if vdata.fields().is_empty() {
9971006
self.err_handler().emit_err(errors::FieldlessUnion { span: item.span });
@@ -1000,20 +1009,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10001009
VariantData::Struct(fields, ..) => {
10011010
self.visit_vis(&item.vis);
10021011
self.visit_ident(item.ident);
1003-
self.visit_generics(generics);
1012+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
1013+
this.visit_generics(generics)
1014+
});
1015+
// Permit `Anon{Struct,Union}` as field type.
10041016
walk_list!(self, visit_struct_field_def, fields);
10051017
walk_list!(self, visit_attribute, &item.attrs);
10061018
return;
10071019
}
10081020
_ => {}
10091021
}
10101022
}
1011-
ItemKind::Const(box ConstItem { defaultness, expr: None, .. }) => {
1012-
self.check_defaultness(item.span, *defaultness);
1013-
self.session.emit_err(errors::ConstWithoutBody {
1014-
span: item.span,
1015-
replace_span: self.ending_semi_or_hi(item.span),
1023+
ItemKind::Const(box ConstItem { defaultness, generics, ty, expr }) => {
1024+
self.visit_vis(&item.vis);
1025+
self.visit_ident(item.ident);
1026+
// FIXME(#117791): Also reject `default` if `expr` is `Some`.
1027+
if expr.is_none() {
1028+
self.check_defaultness(item.span, *defaultness);
1029+
}
1030+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
1031+
this.visit_generics(generics)
10161032
});
1033+
self.visit_ty(ty);
1034+
if let Some(expr) = expr {
1035+
self.visit_expr(expr);
1036+
} else {
1037+
self.session.emit_err(errors::ConstWithoutBody {
1038+
span: item.span,
1039+
replace_span: self.ending_semi_or_hi(item.span),
1040+
});
1041+
}
1042+
walk_list!(self, visit_attribute, &item.attrs);
1043+
return; // Avoid visiting again.
10171044
}
10181045
ItemKind::Static(box StaticItem { expr: None, .. }) => {
10191046
self.session.emit_err(errors::StaticWithoutBody {
@@ -1022,9 +1049,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10221049
});
10231050
}
10241051
ItemKind::TyAlias(
1025-
ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. },
1052+
ty_alias @ box TyAlias { defaultness, generics, bounds, where_clauses, ty, .. },
10261053
) => {
10271054
self.check_defaultness(item.span, *defaultness);
1055+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
1056+
this.visit_generics(generics)
1057+
});
10281058
if ty.is_none() {
10291059
self.session.emit_err(errors::TyAliasWithoutBody {
10301060
span: item.span,
@@ -1189,15 +1219,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11891219
if let Some(reason) = &self.disallow_tilde_const =>
11901220
{
11911221
let reason = match reason {
1192-
DisallowTildeConstContext::TraitObject => {
1193-
errors::TildeConstReason::TraitObject
1194-
}
11951222
DisallowTildeConstContext::Fn(FnKind::Closure(..)) => {
11961223
errors::TildeConstReason::Closure
11971224
}
11981225
DisallowTildeConstContext::Fn(FnKind::Fn(_, ident, ..)) => {
11991226
errors::TildeConstReason::Function { ident: ident.span }
12001227
}
1228+
&DisallowTildeConstContext::Trait(span) => errors::TildeConstReason::Trait { span },
1229+
&DisallowTildeConstContext::Impl(span) => errors::TildeConstReason::Impl { span },
1230+
DisallowTildeConstContext::TraitObject => {
1231+
errors::TildeConstReason::TraitObject
1232+
}
1233+
DisallowTildeConstContext::Item => errors::TildeConstReason::Item,
12011234
};
12021235
self.err_handler()
12031236
.emit_err(errors::TildeConstDisallowed { span: bound.span(), reason });
@@ -1305,7 +1338,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13051338
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
13061339

13071340
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
1308-
13091341
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
13101342
}
13111343

@@ -1374,15 +1406,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13741406
}
13751407

13761408
match &item.kind {
1377-
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. })
1378-
if ctxt == AssocCtxt::Trait =>
1379-
{
1409+
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. }) => {
13801410
self.visit_vis(&item.vis);
13811411
self.visit_ident(item.ident);
13821412
walk_list!(self, visit_attribute, &item.attrs);
1383-
self.with_tilde_const_allowed(|this| {
1413+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
13841414
this.visit_generics(generics);
1385-
walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
1415+
if ctxt == AssocCtxt::Trait {
1416+
walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
1417+
}
13861418
});
13871419
walk_list!(self, visit_ty, ty);
13881420
}
@@ -1403,6 +1435,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14031435
);
14041436
self.visit_fn(kind, item.span, item.id);
14051437
}
1438+
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
1439+
self.visit_vis(&item.vis);
1440+
self.visit_ident(item.ident);
1441+
walk_list!(self, visit_attribute, &item.attrs);
1442+
self.with_banned_tilde_const(DisallowTildeConstContext::Item, |this| {
1443+
this.visit_generics(generics);
1444+
});
1445+
self.visit_ty(ty);
1446+
walk_list!(self, visit_expr, expr);
1447+
}
14061448
_ => self
14071449
.with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
14081450
}

compiler/rustc_ast_passes/src/errors.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -551,15 +551,27 @@ pub struct TildeConstDisallowed {
551551

552552
#[derive(Subdiagnostic)]
553553
pub enum TildeConstReason {
554-
#[note(ast_passes_trait)]
555-
TraitObject,
556554
#[note(ast_passes_closure)]
557555
Closure,
558556
#[note(ast_passes_function)]
559557
Function {
560558
#[primary_span]
561559
ident: Span,
562560
},
561+
#[note(ast_passes_trait)]
562+
Trait {
563+
#[primary_span]
564+
span: Span,
565+
},
566+
#[note(ast_passes_impl)]
567+
Impl {
568+
#[primary_span]
569+
span: Span,
570+
},
571+
#[note(ast_passes_object)]
572+
TraitObject,
573+
#[note(ast_passes_item)]
574+
Item,
563575
}
564576

565577
#[derive(Diagnostic)]

tests/ui/generic-const-items/const-trait-impl.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
#![allow(incomplete_features)]
88
#![crate_type = "lib"]
99

10-
// FIXME(generic_const_items): Interpret `~const` as always-const.
11-
const CREATE<T: ~const Create>: T = T::create();
10+
// FIXME(generic_const_items, effects): Introduce `const` bounds to make this work.
11+
const CREATE<T: Create>: T = T::create();
1212

1313
pub const K0: i32 = CREATE::<i32>;
1414
pub const K1: i32 = CREATE; // arg inferred

tests/ui/generic-const-items/const-trait-impl.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0015]: cannot call non-const fn `<T as Create>::create` in constants
2-
--> $DIR/const-trait-impl.rs:11:37
2+
--> $DIR/const-trait-impl.rs:11:30
33
|
4-
LL | const CREATE<T: ~const Create>: T = T::create();
5-
| ^^^^^^^^^^^
4+
LL | const CREATE<T: Create>: T = T::create();
5+
| ^^^^^^^^^^^
66
|
77
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
88

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

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
error: `~const` is not allowed here
2+
--> $DIR/assoc-type-const-bound-usage.rs:7:17
3+
|
4+
LL | type Assoc: ~const Foo;
5+
| ^^^^^^^^^^
6+
|
7+
= note: this item cannot have `~const` trait bounds
8+
19
error[E0308]: mismatched types
210
--> $DIR/assoc-type-const-bound-usage.rs:12:5
311
|
@@ -7,6 +15,6 @@ LL | <T as Foo>::Assoc::foo();
715
= note: expected constant `host`
816
found constant `true`
917

10-
error: aborting due to previous error
18+
error: aborting due to 2 previous errors
1119

1220
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
error: `~const` is not allowed here
2+
--> $DIR/assoc-type.rs:17:15
3+
|
4+
LL | type Bar: ~const std::ops::Add;
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: this item cannot have `~const` trait bounds
8+
19
error: ~const can only be applied to `#[const_trait]` traits
210
--> $DIR/assoc-type.rs:17:22
311
|
412
LL | type Bar: ~const std::ops::Add;
513
| ^^^^^^^^^^^^^
614

7-
error: aborting due to previous error
15+
error: aborting due to 2 previous errors
816

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/const-bound-on-not-const-associated-fn.rs renamed to tests/ui/rfcs/rfc-2632-const-trait-impl/const-bound-on-not-const-associated-fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(const_trait_impl, effects)]
1+
#![feature(const_trait_impl)]
22

33
#[const_trait]
44
trait MyTrait {
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,10 @@
1-
error[E0493]: destructor of `T` cannot be evaluated at compile-time
2-
--> $DIR/const-drop.rs:19:32
1+
error: `~const` is not allowed here
2+
--> $DIR/const-drop.rs:67:38
33
|
4-
LL | const fn a<T: ~const Destruct>(_: T) {}
5-
| ^ - value is dropped here
6-
| |
7-
| the destructor for this type cannot be evaluated in constant functions
8-
9-
error[E0493]: destructor of `S<'_>` cannot be evaluated at compile-time
10-
--> $DIR/const-drop.rs:24:13
4+
LL | pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
5+
| ^^^^^^^^^^^^^^^^
116
|
12-
LL | let _ = S(&mut c);
13-
| ^^^^^^^^^- value is dropped here
14-
| |
15-
| the destructor for this type cannot be evaluated in constant functions
7+
= note: this item cannot have `~const` trait bounds
168

17-
error: aborting due to 2 previous errors
9+
error: aborting due to previous error
1810

19-
For more information about this error, try `rustc --explain E0493`.

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

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ mod t {
6363
fn foo() {}
6464
}
6565

66+
// FIXME(effects): This should be a `const` bound instead of a `~const` one.
6667
pub struct ConstDropWithBound<T: ~const SomeTrait>(pub core::marker::PhantomData<T>);
6768

6869
impl<T: ~const SomeTrait> const Drop for ConstDropWithBound<T> {

0 commit comments

Comments
 (0)