Should we be more strict with const and SemVer

With const generics approaching, will const and const fn values be an unexpected part of the semantic versioning of a crate? Consider this code, split across two crates at version 1.0.

// crate a
const VAL_A: usize = 1;
const VAL_B: usize = 2;
// crate b
#[derive(PartialEq)]
struct Foobar<const N: usize> { inner: [(); N] } ;
impl Eq for Foobar<{a::VAL_A}> {}
impl Eq for Foobar<{a::VAL_B}> {}

Now crate a is within its (current) SemVer rights to publish 1.1 with:

const VAL_A: usize = 2; //!!
const VAL_B: usize = 2;

However this breaks crate b since the two impls of Eq will now overlap. This can of course already be a problem without const genericss since [T; N] is a stable type that can use a constant generic parameter. This wasn't a very common problem, however, since it existed only for directly use of arrays. However, with const generics and const fn I would expect this to be more common, in particular with the expansion beyond min-const-generics.

Are there any interface guidelines for the case? Should we adopt API-markers where values can be relied upon?

6 Likes

Is there something specific about constants within Rust's SemVer guarantees that isn't obvious?

To me it seems like changing an exported constant would always be a SemVer major changes.

It's contextual. There was some semver conversation in the tracking issue.

1 Like

I think this case is similar:

#[derive(PartialEq)]
struct Foo<const N: u32> { /* ... */ }
impl Eq for Foo<{u32::BITS}> {}
impl Eq for Foo<{usize::BITS}> {}

Once BITS is stabilized, this would compile on target_pointer_width = "64" and fail to compile on target_pointer_width = "32".

2 Likes