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

Lines changed: 0 additions & 26 deletions
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

Lines changed: 26 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 7 additions & 2 deletions
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

0 commit comments

Comments
 (0)