Skip to content

PrivateMethods' items aren't private, they are accessible via MaskElement #537

Description

@obi1kenobi

A surprising new SemVer breakage case was discovered earlier this week, affecting sealed traits' associated items (consts, types, functions with or without receivers — everything) being accessible to subtraits. This is non-obvious and usually isn't intended by the authors of such code, which can lead to accidental breakage.

portable-simd has such an at-risk pattern here

mod private_methods {
    pub impl(super) trait PrivateMethods {
        fn valid<const N: usize>(values: Simd<Self, N>) -> bool
        where
            Self: SimdElement;

        fn eq(self, other: Self) -> bool;

        fn to_usize(self) -> usize;
        fn max_unsigned() -> u64;

        type Unsigned: SimdElement;

        const TRUE: Self;

        const FALSE: Self;
    }
}

Despite the name PrivateMethods, all of those items and methods are accessible downstream (including in downstream crates) via any pub subtrait of PrivateMethods, such as the adjacent MaskElement:

pub impl(self) unsafe trait MaskElement:
    SimdElement<Mask = Self> + SimdCast + PrivateMethods {}

Stabilizing MaskElement could lead to accidentally stabilizing all those PrivateMethods items too, which seems undesirable.

This is a sibling issue of rust-lang/rust#158654 which flags an analogous concern in the Rust standard library itself.

Hat tip to @jhpratt for looping me in to look at the SemVer breakage and suggesting that we scan portable-simd for this pattern. I used AI tools for the scan, but wrote this issue fully by hand otherwise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions