For example:
struct Foo: ~Copyable {
var bar = 0
}
let u = Foo ()
print (type (of: u))
// error: Metatype 'Foo.Type' cannot be cast to 'Any' because 'Foo' is noncopyable
print("\(type (of: u))")
// error: Noncopyable type 'Foo' cannot be erased to copyable existential type 'Any'
I was expecting it to be able to take ~Copyable things, but it doesn't.
Should it?
1 Like
vns
2
According to proposal that has introduced noncopyable types, that is currently not allowed by the language:
At this time, as noted above, generic types are still always required to beCopyable, so noncopyable types themselves are not allowed to be used as a generic type argument. This means a noncopyable type cannot:
- conform to any protocols, except for
Sendable.
- serve as a type witness for an
associatedtype requirement.
- be used as a type argument when instantiating generic types or calling generic functions.
- be cast to (or from)
Any or any other existential.
- be accessed through reflection.
- appear in a tuple.
I suppose that would be possible with SE-0427 that introduces noncopyable generics.
3 Likes
The nice thing about type(of:) is that it can be written naturally without any internal black magic. This makes it easy to write your own overload that takes non-copyable types.
func type<T: ~Copyable>(of value: borrowing T) -> T.Type {
T.self
}
You do need non-copyable generics enabled for this to work though.
3 Likes
type(of:) has two special behaviors that cannot be simulated with your function:
- applied to an existential, it takes the dynamic type of the value and outputs an existential metatype (and not the metatype of the existential)
- applied to a class it returns the dynamic type of the instance (and not the static type)
type(of:) not working for non-Copyable types is an oversight that should be fixed.
14 Likes