Skip to content

Commit 18ec1c4

Browse files
authored
Rollup merge of rust-lang#136688 - fee1-dead-contrib:push-nppsusmpokqo, r=compiler-errors
require trait impls to have matching const stabilities as the traits This resolves rust-lang/project-const-traits#5 by implementing the suggested solution in the given thread r? `@RalfJung` cc `@rust-lang/project-const-traits`
2 parents 2ab38b2 + ef66cbb commit 18ec1c4

File tree

8 files changed

+200
-15
lines changed

8 files changed

+200
-15
lines changed

compiler/rustc_const_eval/src/check_consts/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ pub fn rustc_allow_const_fn_unstable(
9494
/// world into two functions: those that are safe to expose on stable (and hence may not use
9595
/// unstable features, not even recursively), and those that are not.
9696
pub fn is_fn_or_trait_safe_to_expose_on_stable(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
97+
// A default body in a `#[const_trait]` is const-stable when the trait is const-stable.
98+
if tcx.is_const_default_method(def_id) {
99+
return is_fn_or_trait_safe_to_expose_on_stable(tcx, tcx.parent(def_id));
100+
}
101+
97102
match tcx.lookup_const_stability(def_id) {
98103
None => {
99104
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked

compiler/rustc_passes/messages.ftl

+6
Original file line numberDiff line numberDiff line change
@@ -725,6 +725,12 @@ passes_target_feature_on_statement =
725725
.warn = {-passes_previously_accepted}
726726
.label = {passes_should_be_applied_to_fn.label}
727727
728+
passes_trait_impl_const_stability_mismatch = const stability on the impl does not match the const stability on the trait
729+
passes_trait_impl_const_stability_mismatch_impl_stable = this impl is (implicitly) stable...
730+
passes_trait_impl_const_stability_mismatch_impl_unstable = this impl is unstable...
731+
passes_trait_impl_const_stability_mismatch_trait_stable = ...but the trait is stable
732+
passes_trait_impl_const_stability_mismatch_trait_unstable = ...but the trait is unstable
733+
728734
passes_trait_impl_const_stable =
729735
trait implementations cannot be const stable yet
730736
.note = see issue #67792 <https://github.com./rust-lang/rust/issues/67792> for more information

compiler/rustc_passes/src/errors.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1552,6 +1552,45 @@ pub(crate) struct TraitImplConstStable {
15521552
pub span: Span,
15531553
}
15541554

1555+
#[derive(Diagnostic)]
1556+
#[diag(passes_trait_impl_const_stability_mismatch)]
1557+
pub(crate) struct TraitImplConstStabilityMismatch {
1558+
#[primary_span]
1559+
pub span: Span,
1560+
#[subdiagnostic]
1561+
pub impl_stability: ImplConstStability,
1562+
#[subdiagnostic]
1563+
pub trait_stability: TraitConstStability,
1564+
}
1565+
1566+
#[derive(Subdiagnostic)]
1567+
pub(crate) enum TraitConstStability {
1568+
#[note(passes_trait_impl_const_stability_mismatch_trait_stable)]
1569+
Stable {
1570+
#[primary_span]
1571+
span: Span,
1572+
},
1573+
#[note(passes_trait_impl_const_stability_mismatch_trait_unstable)]
1574+
Unstable {
1575+
#[primary_span]
1576+
span: Span,
1577+
},
1578+
}
1579+
1580+
#[derive(Subdiagnostic)]
1581+
pub(crate) enum ImplConstStability {
1582+
#[note(passes_trait_impl_const_stability_mismatch_impl_stable)]
1583+
Stable {
1584+
#[primary_span]
1585+
span: Span,
1586+
},
1587+
#[note(passes_trait_impl_const_stability_mismatch_impl_unstable)]
1588+
Unstable {
1589+
#[primary_span]
1590+
span: Span,
1591+
},
1592+
}
1593+
15551594
#[derive(Diagnostic)]
15561595
#[diag(passes_unknown_feature, code = E0635)]
15571596
pub(crate) struct UnknownFeature {

compiler/rustc_passes/src/stability.rs

+46-14
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
313313
.map(|(stab, _span)| ConstStability::from_partial(stab, const_stability_indirect));
314314

315315
// If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
316-
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
316+
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
317317
// We only ever inherit unstable features.
318318
let Some(inherit_regular_stab) =
319319
final_stab.filter(|s| s.is_unstable())
@@ -826,24 +826,56 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
826826
}
827827
}
828828

829-
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
830-
// needs to have an error emitted.
831829
if features.const_trait_impl()
832-
&& self.tcx.is_const_trait_impl(item.owner_id.to_def_id())
833-
&& const_stab.is_some_and(|stab| stab.is_const_stable())
830+
&& let hir::Constness::Const = constness
834831
{
835-
self.tcx.dcx().emit_err(errors::TraitImplConstStable { span: item.span });
832+
let stable_or_implied_stable = match const_stab {
833+
None => true,
834+
Some(stab) if stab.is_const_stable() => {
835+
// `#![feature(const_trait_impl)]` is unstable, so any impl declared stable
836+
// needs to have an error emitted.
837+
// Note: Remove this error once `const_trait_impl` is stabilized
838+
self.tcx
839+
.dcx()
840+
.emit_err(errors::TraitImplConstStable { span: item.span });
841+
true
842+
}
843+
Some(_) => false,
844+
};
845+
846+
if let Some(trait_id) = t.trait_def_id()
847+
&& let Some(const_stab) = self.tcx.lookup_const_stability(trait_id)
848+
{
849+
// the const stability of a trait impl must match the const stability on the trait.
850+
if const_stab.is_const_stable() != stable_or_implied_stable {
851+
let trait_span = self.tcx.def_ident_span(trait_id).unwrap();
852+
853+
let impl_stability = if stable_or_implied_stable {
854+
errors::ImplConstStability::Stable { span: item.span }
855+
} else {
856+
errors::ImplConstStability::Unstable { span: item.span }
857+
};
858+
let trait_stability = if const_stab.is_const_stable() {
859+
errors::TraitConstStability::Stable { span: trait_span }
860+
} else {
861+
errors::TraitConstStability::Unstable { span: trait_span }
862+
};
863+
864+
self.tcx.dcx().emit_err(errors::TraitImplConstStabilityMismatch {
865+
span: item.span,
866+
impl_stability,
867+
trait_stability,
868+
});
869+
}
870+
}
836871
}
837872
}
838873

839-
match constness {
840-
rustc_hir::Constness::Const => {
841-
if let Some(def_id) = t.trait_def_id() {
842-
// FIXME(const_trait_impl): Improve the span here.
843-
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
844-
}
845-
}
846-
rustc_hir::Constness::NotConst => {}
874+
if let hir::Constness::Const = constness
875+
&& let Some(def_id) = t.trait_def_id()
876+
{
877+
// FIXME(const_trait_impl): Improve the span here.
878+
self.tcx.check_const_stability(def_id, t.path.span, t.path.span);
847879
}
848880

849881
for impl_item_ref in *items {

library/core/src/ops/arith.rs

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub trait Add<Rhs = Self> {
9696
macro_rules! add_impl {
9797
($($t:ty)*) => ($(
9898
#[stable(feature = "rust1", since = "1.0.0")]
99+
#[rustc_const_unstable(feature = "const_ops", issue = "90080")]
99100
impl const Add for $t {
100101
type Output = $t;
101102

library/core/src/ops/deref.rs

+3
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ pub trait Deref {
150150
}
151151

152152
#[stable(feature = "rust1", since = "1.0.0")]
153+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
153154
impl<T: ?Sized> const Deref for &T {
154155
type Target = T;
155156

@@ -163,6 +164,7 @@ impl<T: ?Sized> const Deref for &T {
163164
impl<T: ?Sized> !DerefMut for &T {}
164165

165166
#[stable(feature = "rust1", since = "1.0.0")]
167+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
166168
impl<T: ?Sized> const Deref for &mut T {
167169
type Target = T;
168170

@@ -273,6 +275,7 @@ pub trait DerefMut: ~const Deref {
273275
}
274276

275277
#[stable(feature = "rust1", since = "1.0.0")]
278+
#[rustc_const_unstable(feature = "const_deref", issue = "88955")]
276279
impl<T: ?Sized> const DerefMut for &mut T {
277280
fn deref_mut(&mut self) -> &mut T {
278281
*self

tests/ui/traits/const-traits/staged-api.rs

+32
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,36 @@ const fn implicitly_stable_const_context() {
8585
//~^ ERROR cannot use `#[feature(const_trait_impl)]`
8686
}
8787

88+
// check that const stability of impls and traits must match
89+
#[const_trait]
90+
#[rustc_const_unstable(feature = "beef", issue = "none")]
91+
trait U {}
92+
93+
#[const_trait]
94+
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
95+
trait S {}
96+
97+
// implied stable
98+
impl const U for u8 {}
99+
//~^ const stability on the impl does not match the const stability on the trait
100+
101+
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
102+
impl const U for u16 {}
103+
//~^ const stability on the impl does not match the const stability on the trait
104+
//~| trait implementations cannot be const stable yet
105+
106+
#[rustc_const_unstable(feature = "beef", issue = "none")]
107+
impl const U for u32 {}
108+
109+
// implied stable
110+
impl const S for u8 {}
111+
112+
#[rustc_const_stable(since = "0.0.0", feature = "beef2")]
113+
impl const S for u16 {}
114+
//~^ trait implementations cannot be const stable yet
115+
116+
#[rustc_const_unstable(feature = "beef", issue = "none")]
117+
impl const S for u32 {}
118+
//~^ const stability on the impl does not match the const stability on the trait
119+
88120
fn main() {}

tests/ui/traits/const-traits/staged-api.stderr

+68-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,70 @@
1+
error: const stability on the impl does not match the const stability on the trait
2+
--> $DIR/staged-api.rs:98:1
3+
|
4+
LL | impl const U for u8 {}
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: this impl is (implicitly) stable...
8+
--> $DIR/staged-api.rs:98:1
9+
|
10+
LL | impl const U for u8 {}
11+
| ^^^^^^^^^^^^^^^^^^^^^^
12+
note: ...but the trait is unstable
13+
--> $DIR/staged-api.rs:91:7
14+
|
15+
LL | trait U {}
16+
| ^
17+
18+
error: trait implementations cannot be const stable yet
19+
--> $DIR/staged-api.rs:102:1
20+
|
21+
LL | impl const U for u16 {}
22+
| ^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
= note: see issue #67792 <https://github.com./rust-lang/rust/issues/67792> for more information
25+
26+
error: const stability on the impl does not match the const stability on the trait
27+
--> $DIR/staged-api.rs:102:1
28+
|
29+
LL | impl const U for u16 {}
30+
| ^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
note: this impl is (implicitly) stable...
33+
--> $DIR/staged-api.rs:102:1
34+
|
35+
LL | impl const U for u16 {}
36+
| ^^^^^^^^^^^^^^^^^^^^^^^
37+
note: ...but the trait is unstable
38+
--> $DIR/staged-api.rs:91:7
39+
|
40+
LL | trait U {}
41+
| ^
42+
43+
error: trait implementations cannot be const stable yet
44+
--> $DIR/staged-api.rs:113:1
45+
|
46+
LL | impl const S for u16 {}
47+
| ^^^^^^^^^^^^^^^^^^^^^^^
48+
|
49+
= note: see issue #67792 <https://github.com./rust-lang/rust/issues/67792> for more information
50+
51+
error: const stability on the impl does not match the const stability on the trait
52+
--> $DIR/staged-api.rs:117:1
53+
|
54+
LL | impl const S for u32 {}
55+
| ^^^^^^^^^^^^^^^^^^^^^^^
56+
|
57+
note: this impl is unstable...
58+
--> $DIR/staged-api.rs:117:1
59+
|
60+
LL | impl const S for u32 {}
61+
| ^^^^^^^^^^^^^^^^^^^^^^^
62+
note: ...but the trait is stable
63+
--> $DIR/staged-api.rs:95:7
64+
|
65+
LL | trait S {}
66+
| ^
67+
168
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_trait_impl)]`
269
--> $DIR/staged-api.rs:38:5
370
|
@@ -323,5 +390,5 @@ LL + #[rustc_allow_const_fn_unstable(const_trait_impl)]
323390
LL | const fn implicitly_stable_const_context() {
324391
|
325392

326-
error: aborting due to 19 previous errors
393+
error: aborting due to 24 previous errors
327394

0 commit comments

Comments
 (0)