Public extension method in extension with internal requirements


(^) #1

I have several public structs that conform to this internal protocol. The
protocol has an associated type IntV so that it can service 2, 3, or 4
dimensional noise.

protocol HashedTilingNoise
{
    associatedtype IntV

    var amplitude:Double { get }
    var frequency:Double { get }
    var wavelengths:IntV { get }

    init(amplitude:Double, frequency:Double, wavelengths:IntV)
}

I extend it to provide common functionality for all the conforming structs.

extension HashedTilingNoise
{
    public
    func amplitude_scaled(by factor:Double) -> Self
    {
        return Self(amplitude: self.amplitude * factor, frequency:
self.frequency,
wavelengths: self.wavelengths)
    }

    public
    func frequency_scaled(by factor:Double) -> Self
    {
        return Self(amplitude: self.amplitude, frequency: self.frequency *
factor, wavelengths: self.wavelengths)
    }

    ...
}

But now I want to provide common functionality just for structs with a
certain dimension. For example, I want to provide a transpose(octaves:)
function for the structs that have 3 dimensional wavelengths.

extension HashedTilingNoise where IntV == Math.IntV3
{
    public
    func transposed(octaves:Int) -> Self
    {
        return Self(amplitude: self.amplitude, frequency: self.frequency,
                    wavelengths: (self.wavelengths.a << octaves,
self.wavelengths.b
<< octaves, self.wavelengths.c << octaves))
    }
}

But this gives the compiler error

/home/taylorswift/noise/sources/noise/hash.swift:67:5: error: cannot
declare a public instance method in an extension with internal requirements
    public
    ^~~~~~
    internal

Because the Math.IntV3 type and the HashedTilingNoise protocol are
internal. I don’t want to expose these as part of the API as they are just
containers for shared functionality.

How do I fix this?