-
Notifications
You must be signed in to change notification settings - Fork 21
replace constructorof with something not UB #99
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
Conversation
It is confusing that `constructorof` is documented as returning the constructor of `T`, which is normally defined to be `T`, and then typically does not return `T`, and so does not usually construct `T`. However, this PR is intended just to remove the undefined behavior here of using an unsound generated function (examining mutable state with getfield).
This didn't work out so well in the past: It would need to come with an assurance that its type stable and new julia versions wont break that. ( |
There is also UB at ConstructionBase.jl/src/functions.jl Line 11 in 72bb19d
|
#55 does not appear to have anything at all to do with this, except for pattern matching on the text "generated", as that touches a different function for different reasons @KristofferC that is good to know too. That one may be harder to make entirely safe, since it exists for the specific purpose of violating the safety of the compiler, but can perhaps have the same change made to it anyways |
#55 just has the "removing generated function lead to type instability and bug reports" problem. This generated function was also for performance at some stage - but that may have been driven by wanting to avoid @vtjnash it would just be good to have confirmation that |
getfield(parentmodule(T), nameof(T)) | ||
end | ||
|
||
constructorof(T::Type) = Base.typename(T).wrapper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constructorof(T::Type) = Base.typename(T).wrapper | |
constructorof(::Type{T}) where T = Base.typename(T).wrapper |
Is there a reason why the where T
was dropped as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In practice, the where just reduces the information inference is permitted to use about the argument during inlining
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I guess I don't understand the scope of consequences of that.
From practical experience using where
on types and functions like this often fixes type stability bugs.
(The reason for my concern is a small loss of type stability in constructorof
could break the performance of 100s of packages)
Could you please rebase on master? CI was cleaned up there to avoid almost all spurious test failures. |
It appears that you have that ability disabled in settings |
Bump. On current v1.12 and v1.13, ConstructionBase.jl causes ungodly amounts of deprecation warnings to be printed. Furthermore, after JuliaLang/julia#58651 gets merged, and backported to v1.12, ConstructionBase will be completely broken. |
Also see: JuliaLang/julia#57701 |
I guess a new PR with the same content is needed, as we cannot rebase this one and run tests? I have no idea what the issue with rebasing is... |
More generally, restrictions on generated functions are very unclear IMO.
Any generated function that calls any other generic function "examines mutable state" (the method table). Even some examples from Julia docs. |
Generated function restrictions are hard enough, so please don't just make more things up. The generated function execution world is a constant, which is an equivalent statement to saying that the method table is constant, so there is no mutable state in the method table. |
Then the restriction that generated functions must not use |
This is not the right place to have this off-topic conversation, as it has not relevance to this PR. But anyways, there is no restriction on calling |
Sorry for derailing, and thanks for clarifying that
I was just following the docs that say (and has been doing so for years):
|
Lets close this in favor of #102 |
It is confusing that
constructorof
is documented as returning the constructor ofT
, which is normally defined to beT
, and then typically does not returnT
, and so does not usually constructT
. However, this PR is intended just to remove the undefined behavior here of using an unsound generated function (examining mutable state with getfield).