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
Joe_Groff
(Joe Groff)
2
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?