Skip to content

Commit f55fef1

Browse files
authored
Rollup merge of #102647 - oli-obk:tilde_const_bounds, r=fee1-dead
Only allow ~const bounds for traits with #[const_trait] r? `@fee1-dead`
2 parents 5d58451 + c72c6e0 commit f55fef1

35 files changed

+216
-118
lines changed

compiler/rustc_passes/src/check_const.rs

-26
Original file line numberDiff line numberDiff line change
@@ -191,32 +191,6 @@ impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> {
191191
self.tcx.hir()
192192
}
193193

194-
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
195-
let tcx = self.tcx;
196-
if let hir::ItemKind::Impl(hir::Impl {
197-
constness: hir::Constness::Const,
198-
of_trait: Some(trait_ref),
199-
..
200-
}) = item.kind
201-
&& let Some(def_id) = trait_ref.trait_def_id()
202-
{
203-
let source_map = tcx.sess.source_map();
204-
if !tcx.has_attr(def_id, sym::const_trait) {
205-
tcx.sess
206-
.struct_span_err(
207-
source_map.guess_head_span(item.span),
208-
"const `impl`s must be for traits marked with `#[const_trait]`",
209-
)
210-
.span_note(
211-
source_map.guess_head_span(tcx.def_span(def_id)),
212-
"this trait must be annotated with `#[const_trait]`",
213-
)
214-
.emit();
215-
}
216-
}
217-
intravisit::walk_item(self, item);
218-
}
219-
220194
fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) {
221195
let kind = Some(hir::ConstContext::Const);
222196
self.recurse_into(kind, None, |this| intravisit::walk_anon_const(this, anon));

compiler/rustc_trait_selection/src/traits/wf.rs

+26
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,32 @@ impl<'tcx> WfPredicates<'tcx> {
308308
let obligations = if trait_pred.constness == ty::BoundConstness::NotConst {
309309
self.nominal_obligations_without_const(trait_ref.def_id, trait_ref.substs)
310310
} else {
311+
if !tcx.has_attr(trait_ref.def_id, rustc_span::sym::const_trait) {
312+
if let Some(item) = self.item &&
313+
let hir::ItemKind::Impl(impl_) = item.kind &&
314+
let Some(trait_) = &impl_.of_trait &&
315+
let Some(def_id) = trait_.trait_def_id() &&
316+
def_id == trait_ref.def_id
317+
{
318+
let trait_name = tcx.item_name(def_id);
319+
let mut err = tcx.sess.struct_span_err(
320+
self.span,
321+
&format!("const `impl` for trait `{trait_name}` which is not marked with `#[const_trait]`"),
322+
);
323+
if def_id.is_local() {
324+
let sp = tcx.def_span(def_id).shrink_to_lo();
325+
err.span_suggestion(sp, &format!("mark `{trait_name}` as const"), "#[const_trait]", rustc_errors::Applicability::MachineApplicable);
326+
}
327+
err.note("marking a trait with `#[const_trait]` ensures all default method bodies are `const`");
328+
err.note("adding a non-const method body in the future would be a breaking change");
329+
err.emit();
330+
} else {
331+
tcx.sess.span_err(
332+
self.span,
333+
"~const can only be applied to `#[const_trait]` traits",
334+
);
335+
}
336+
}
311337
self.nominal_obligations(trait_ref.def_id, trait_ref.substs)
312338
};
313339

library/core/src/iter/traits/collect.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ pub trait IntoIterator {
264264

265265
#[rustc_const_unstable(feature = "const_intoiterator_identity", issue = "90603")]
266266
#[stable(feature = "rust1", since = "1.0.0")]
267-
impl<I: ~const Iterator> const IntoIterator for I {
267+
impl<I: Iterator> const IntoIterator for I {
268268
type Item = I::Item;
269269
type IntoIter = I;
270270

library/core/src/marker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ impl<T: ?Sized> Unpin for *mut T {}
799799
#[unstable(feature = "const_trait_impl", issue = "67792")]
800800
#[lang = "destruct"]
801801
#[rustc_on_unimplemented(message = "can't drop `{Self}`", append_const_msg)]
802+
#[const_trait]
802803
pub trait Destruct {}
803804

804805
/// A marker for tuple types.

src/test/ui/consts/const-fn-error.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ LL | for i in 0..x {
2222
note: impl defined here, but it is not `const`
2323
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
2424
|
25-
LL | impl<I: ~const Iterator> const IntoIterator for I {
26-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
LL | impl<I: Iterator> const IntoIterator for I {
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2727
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
2828

2929
error[E0658]: mutable references are not allowed in constant functions

src/test/ui/consts/const-for.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ LL | for _ in 0..5 {}
77
note: impl defined here, but it is not `const`
88
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
99
|
10-
LL | impl<I: ~const Iterator> const IntoIterator for I {
11-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
10+
LL | impl<I: Iterator> const IntoIterator for I {
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1212
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
1313

1414
error[E0015]: cannot call non-const fn `<std::ops::Range<i32> as Iterator>::next` in constants

src/test/ui/consts/constifconst-call-in-const-position.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![feature(const_trait_impl, generic_const_exprs)]
44

5+
#[const_trait]
56
pub trait Tr {
67
fn a() -> usize;
78
}

src/test/ui/consts/constifconst-call-in-const-position.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ LL | #![feature(const_trait_impl, generic_const_exprs)]
88
= note: `#[warn(incomplete_features)]` on by default
99

1010
error[E0080]: evaluation of `foo::<()>::{constant#0}` failed
11-
--> $DIR/constifconst-call-in-const-position.rs:15:38
11+
--> $DIR/constifconst-call-in-const-position.rs:16:38
1212
|
1313
LL | const fn foo<T: ~const Tr>() -> [u8; T::a()] {
1414
| ^^^^^^ calling non-const function `<() as Tr>::a`

src/test/ui/never_type/issue-52443.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ LL | [(); { for _ in 0usize.. {}; 0}];
4747
note: impl defined here, but it is not `const`
4848
--> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
4949
|
50-
LL | impl<I: ~const Iterator> const IntoIterator for I {
51-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50+
LL | impl<I: Iterator> const IntoIterator for I {
51+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5252
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
5353

5454
error[E0658]: mutable references are not allowed in constants

src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@
22

33
struct S;
44

5-
impl PartialEq for S {
5+
#[const_trait]
6+
trait Foo {
7+
fn eq(&self, _: &Self) -> bool;
8+
}
9+
10+
impl Foo for S {
611
fn eq(&self, _: &S) -> bool {
712
true
813
}
914
}
1015

11-
const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
16+
const fn equals_self<T: ~const Foo>(t: &T) -> bool {
1217
true
1318
}
1419

src/test/ui/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr

+8-13
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
1-
error[E0277]: can't compare `S` with `S` in const contexts
2-
--> $DIR/call-generic-method-nonconst.rs:18:34
1+
error[E0277]: the trait bound `S: ~const Foo` is not satisfied
2+
--> $DIR/call-generic-method-nonconst.rs:23:34
33
|
44
LL | pub const EQ: bool = equals_self(&S);
5-
| ----------- ^^ no implementation for `S == S`
5+
| ----------- ^^ the trait `~const Foo` is not implemented for `S`
66
| |
77
| required by a bound introduced by this call
88
|
9-
= help: the trait `~const PartialEq` is not implemented for `S`
10-
note: the trait `PartialEq` is implemented for `S`, but that implementation is not `const`
11-
--> $DIR/call-generic-method-nonconst.rs:18:34
9+
note: the trait `Foo` is implemented for `S`, but that implementation is not `const`
10+
--> $DIR/call-generic-method-nonconst.rs:23:34
1211
|
1312
LL | pub const EQ: bool = equals_self(&S);
1413
| ^^
1514
note: required by a bound in `equals_self`
16-
--> $DIR/call-generic-method-nonconst.rs:11:25
17-
|
18-
LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
19-
| ^^^^^^^^^^^^^^^^ required by this bound in `equals_self`
20-
help: consider annotating `S` with `#[derive(PartialEq)]`
21-
|
22-
LL | #[derive(PartialEq)]
15+
--> $DIR/call-generic-method-nonconst.rs:16:25
2316
|
17+
LL | const fn equals_self<T: ~const Foo>(t: &T) -> bool {
18+
| ^^^^^^^^^^ required by this bound in `equals_self`
2419

2520
error: aborting due to previous error
2621

src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: can't drop `NonTrivialDrop` in const contexts
2-
--> $DIR/const-drop-fail.rs:43:5
2+
--> $DIR/const-drop-fail.rs:44:5
33
|
44
LL | const _: () = check($exp);
55
| ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL | NonTrivialDrop,
99
|
1010
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
1111
note: required by a bound in `check`
12-
--> $DIR/const-drop-fail.rs:34:19
12+
--> $DIR/const-drop-fail.rs:35:19
1313
|
1414
LL | const fn check<T: ~const Destruct>(_: T) {}
1515
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
2121
| ++++
2222

2323
error[E0277]: can't drop `NonTrivialDrop` in const contexts
24-
--> $DIR/const-drop-fail.rs:45:5
24+
--> $DIR/const-drop-fail.rs:46:5
2525
|
2626
LL | const _: () = check($exp);
2727
| ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
3030
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
3131
|
3232
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
33-
--> $DIR/const-drop-fail.rs:45:5
33+
--> $DIR/const-drop-fail.rs:46:5
3434
|
3535
LL | ConstImplWithDropGlue(NonTrivialDrop),
3636
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
4040
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
4141
| ^^^^^^^^^^^^^^^^^^^^^
4242
note: required by a bound in `check`
43-
--> $DIR/const-drop-fail.rs:34:19
43+
--> $DIR/const-drop-fail.rs:35:19
4444
|
4545
LL | const fn check<T: ~const Destruct>(_: T) {}
4646
| ^^^^^^^^^^^^^^^ required by this bound in `check`
4747

4848
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
49-
--> $DIR/const-drop-fail.rs:47:5
49+
--> $DIR/const-drop-fail.rs:48:5
5050
|
5151
LL | const _: () = check($exp);
5252
| ----- required by a bound introduced by this call
@@ -55,14 +55,14 @@ LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
5555
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
5656
|
5757
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
58-
--> $DIR/const-drop-fail.rs:28:25
58+
--> $DIR/const-drop-fail.rs:29:25
5959
|
6060
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
6161
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
6262
= note: 1 redundant requirement hidden
6363
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
6464
note: required by a bound in `check`
65-
--> $DIR/const-drop-fail.rs:34:19
65+
--> $DIR/const-drop-fail.rs:35:19
6666
|
6767
LL | const fn check<T: ~const Destruct>(_: T) {}
6868
| ^^^^^^^^^^^^^^^ required by this bound in `check`

src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ impl const Drop for ConstImplWithDropGlue {
1919
fn drop(&mut self) {}
2020
}
2121

22-
trait A { fn a() { println!("A"); } }
22+
#[const_trait]
23+
trait A { fn a() { } }
2324

2425
impl A for NonTrivialDrop {}
2526

src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0277]: can't drop `NonTrivialDrop` in const contexts
2-
--> $DIR/const-drop-fail.rs:43:5
2+
--> $DIR/const-drop-fail.rs:44:5
33
|
44
LL | const _: () = check($exp);
55
| ----- required by a bound introduced by this call
@@ -9,7 +9,7 @@ LL | NonTrivialDrop,
99
|
1010
= note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
1111
note: required by a bound in `check`
12-
--> $DIR/const-drop-fail.rs:34:19
12+
--> $DIR/const-drop-fail.rs:35:19
1313
|
1414
LL | const fn check<T: ~const Destruct>(_: T) {}
1515
| ^^^^^^^^^^^^^^^ required by this bound in `check`
@@ -21,7 +21,7 @@ LL | &mut NonTrivialDrop,
2121
| ++++
2222

2323
error[E0277]: can't drop `NonTrivialDrop` in const contexts
24-
--> $DIR/const-drop-fail.rs:45:5
24+
--> $DIR/const-drop-fail.rs:46:5
2525
|
2626
LL | const _: () = check($exp);
2727
| ----- required by a bound introduced by this call
@@ -30,7 +30,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop),
3030
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `ConstImplWithDropGlue`, the trait `~const Destruct` is not implemented for `NonTrivialDrop`
3131
|
3232
note: the trait `Destruct` is implemented for `NonTrivialDrop`, but that implementation is not `const`
33-
--> $DIR/const-drop-fail.rs:45:5
33+
--> $DIR/const-drop-fail.rs:46:5
3434
|
3535
LL | ConstImplWithDropGlue(NonTrivialDrop),
3636
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,13 +40,13 @@ note: required because it appears within the type `ConstImplWithDropGlue`
4040
LL | struct ConstImplWithDropGlue(NonTrivialDrop);
4141
| ^^^^^^^^^^^^^^^^^^^^^
4242
note: required by a bound in `check`
43-
--> $DIR/const-drop-fail.rs:34:19
43+
--> $DIR/const-drop-fail.rs:35:19
4444
|
4545
LL | const fn check<T: ~const Destruct>(_: T) {}
4646
| ^^^^^^^^^^^^^^^ required by this bound in `check`
4747

4848
error[E0277]: the trait bound `ConstDropImplWithBounds<NonTrivialDrop>: ~const Destruct` is not satisfied
49-
--> $DIR/const-drop-fail.rs:47:5
49+
--> $DIR/const-drop-fail.rs:48:5
5050
|
5151
LL | const _: () = check($exp);
5252
| ----- required by a bound introduced by this call
@@ -55,14 +55,14 @@ LL | ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
5555
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
5656
|
5757
note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
58-
--> $DIR/const-drop-fail.rs:28:25
58+
--> $DIR/const-drop-fail.rs:29:25
5959
|
6060
LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
6161
| ^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^
6262
= note: 1 redundant requirement hidden
6363
= note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
6464
note: required by a bound in `check`
65-
--> $DIR/const-drop-fail.rs:34:19
65+
--> $DIR/const-drop-fail.rs:35:19
6666
|
6767
LL | const fn check<T: ~const Destruct>(_: T) {}
6868
| ^^^^^^^^^^^^^^^ required by this bound in `check`
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![feature(const_trait_impl)]
22

33
pub trait A {}
4-
//~^ NOTE: this trait must be annotated with `#[const_trait]`
4+
//~^ HELP: mark `A` as const
55

66
impl const A for () {}
7-
//~^ ERROR: const `impl`s must be for traits marked with `#[const_trait]`
7+
//~^ ERROR: const `impl` for trait `A` which is not marked with `#[const_trait]`
88

99
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
error: const `impl`s must be for traits marked with `#[const_trait]`
2-
--> $DIR/const-impl-requires-const-trait.rs:6:1
1+
error: const `impl` for trait `A` which is not marked with `#[const_trait]`
2+
--> $DIR/const-impl-requires-const-trait.rs:6:12
33
|
4+
LL | pub trait A {}
5+
| - help: mark `A` as const: `#[const_trait]`
6+
...
47
LL | impl const A for () {}
5-
| ^^^^^^^^^^^^^^^^^^^
6-
|
7-
note: this trait must be annotated with `#[const_trait]`
8-
--> $DIR/const-impl-requires-const-trait.rs:3:1
8+
| ^
99
|
10-
LL | pub trait A {}
11-
| ^^^^^^^^^^^
10+
= note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
11+
= note: adding a non-const method body in the future would be a breaking change
1212

1313
error: aborting due to previous error
1414

src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![feature(const_trait_impl)]
22

3+
#[const_trait]
34
trait Tr {}
45
impl Tr for () {}
56

src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-body-checking.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0277]: the trait bound `(): ~const Tr` is not satisfied
2-
--> $DIR/default-method-body-is-const-body-checking.rs:11:15
2+
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
33
|
44
LL | foo::<()>();
55
| ^^ the trait `~const Tr` is not implemented for `()`
66
|
77
note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
8-
--> $DIR/default-method-body-is-const-body-checking.rs:11:15
8+
--> $DIR/default-method-body-is-const-body-checking.rs:12:15
99
|
1010
LL | foo::<()>();
1111
| ^^
1212
note: required by a bound in `foo`
13-
--> $DIR/default-method-body-is-const-body-checking.rs:6:28
13+
--> $DIR/default-method-body-is-const-body-checking.rs:7:28
1414
|
1515
LL | const fn foo<T>() where T: ~const Tr {}
1616
| ^^^^^^^^^ required by this bound in `foo`

0 commit comments

Comments
 (0)