How to define an operator that consumes the LHS?

i’ve got an path API that has an appending(_:) API that’s defined as such:

extension QualifiedPath
{
    __consuming
    func appending(_ component:String) -> Self
    {
        var path:Self = self
        path.suffix.append(component)
        return path
    }
}

as i understand it, the __consuming modifier allows this to happen without triggering copy-on-write.

now, i want to make this API an operator instead of an instance method:

extension QualifiedPath
{
    public static
    func / (self:Self, component:String) -> Self
    {
        self.appending(component)
    }
}

because self now lives for the duration of the operator call (regardless of __owned apparently), this suffers from copy-on-write when called from outside the module.

as with everything else in swift, the problem might go away if you spray enough @inlinable on it.

extension QualifiedPath
{
    @usableFromInline internal __consuming
    func appending(_ component:String) -> Self
    {
        var path:Self = self
        path.suffix.append(component)
        return path
    }
    @inlinable public static
    func / (self:Self, component:String) -> Self
    {
        self.appending(component)
    }
}

but is there a more hygienic way to implement this?

2 Likes

You can put __owned (or in Swift 5.9, consuming) on the argument to the operator. __consuming is just making the self parameter __owned. If the argument in a call is a local variable, then there shouldn't be any reason for it to be copied to persist its lifetime if it's not used after the consuming call, but you could use (consume x) / component to force it.

2 Likes

i thought the new lifetime rules mean that x would live for the entire duration of the /(_:_:) call, regardless of whether it’s passed +1 or +0. doesn’t that mean that if i do something like:

        var path:Self = self
        path.suffix.append(component)

in the operator implementation, this will always suffer from copy-on-write, since the original instance of self is still alive?