-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
It's too easy to accidentally sidestep our convert(::Type{T}, ::T)
no-op fallback
#17559
Comments
I would say this is a dup of #6383. As you observe, if the |
Do you think the action item here (automatically defining If it's the former, I can try taking a stab at it when I get some time. If it's the latter, this issue can closed in favor of #6383. |
As another data point, this was the problem here: eschnett/SIMD.jl#12 (solved by eschnett/SIMD.jl#6). If an experience julia coder like Eric can make this mistake, many others surely do. |
I think we should fix #6383, and not add an extra |
Actually, after thinking about it a bit more, I believe this issue might be slightly different than #6383. Even after #6383 is fixed, the following behavior would remain the same, yes? julia> type Foo{T}
x::T
end
julia> function Base.convert{T}(::Type{Foo{T}}, f::Foo)
println("made new instance")
return Foo{T}(T(f.x))
end
julia> convert(Foo{Int}, Foo{Int}(1))
made new instance
Foo{Int64}(made new instance
1) In this issue, I'm arguing that the above behavior should change; that Though maybe I'm misunderstanding, and fixing #6383 will result in the no-op behavior I'm arguing for. If that's the case, feel free to close this. |
There is no way to guarantee that converting to the same type is a no-op, or even that converting to a certain type actually returns something of the requested type (though that could potentially be provided by some kind of whole-function type declaration). |
Nor do I suggest that a guarantee is required here. Rather, I'm suggesting that the current no-op Many users who overload |
There are a lot of types (in particular, one per generic function), so that would create a lot of methods. |
as the discussion above noted, close as dup of #6383 |
The following ambiguity error seems wonky to me:
Additionally, this kind of behavior can result in silent copies (or worse) whenever implicit conversions occur:
Note that the above examples don't have this behavior if the
T
parameter isn't restricted toT<:Real
in the type definition.Now, these examples were silly, but they show that it's currently very easy to screw this up and get weird behavior and performance problems as a result.
convert
unexpectedly copying data is a problem that I've seen in real code - it showed up in our ownTuple
code a while ago, and I've just spent a couple of hours chasing a bug this behavior caused in a prototype package I'm working on.I'd argue that the root of this problem is that our current no-op convert fallback (
convert{T}(::Type{T}, x::T) = x
) is too easy to accidentally sidestep. To fix this, I propose that all new type definitions also add the following method toBase.convert
:It still wouldn't help in messier cases like #11767, but AFAIK, it'd at least be more specific than our current fallback.
The text was updated successfully, but these errors were encountered: