Skip to content
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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid method ambiguities in TypedefMutualRef's #458

Merged
merged 8 commits into from Dec 24, 2023

Conversation

JamesWrigley
Copy link
Member

emit!() for TypedefMutualRef will create some specializations of Base.unsafe_convert(), and previously they didn't declare a type for the Ref/Ptr value being passed to them, which would cause a method ambiguity with Base (detected by Aqua.jl).

The problem is that the typedef will of course be declared in the C header before the struct it references, so the Base.unsafe_convert() specializations couldn't use the actual struct type in their signature because it won't have been created yet. This commit fixes that with the notion of a partially emitted node that contains premature exprs that haven't been emitted yet. Now emit!() for TypedefMutualRef will record the Base.unsafe_convert() methods as premature exprs and mark itself as a partially emitted node. Then later, emit!() for the StructDefinition will look for any partially emitted nodes that are marked for it and emit their premature expressions itself.

Before:

mutable struct __JL_foo_struct
end

function Base.unsafe_load(x::Ptr{__JL_foo_struct})
    unsafe_load(Ptr{foo_struct}(x))
end

function Base.getproperty(x::Ptr{__JL_foo_struct}, f::Symbol)
    getproperty(Ptr{foo_struct}(x), f)
end

function Base.setproperty!(x::Ptr{__JL_foo_struct}, f::Symbol, v)
    setproperty!(Ptr{foo_struct}(x), f, v)
end

Base.unsafe_convert(::Type{Ptr{__JL_foo_struct}}, x::Ref) = Base.unsafe_convert(Ptr{__JL_foo_struct}, Base.unsafe_convert(Ptr{foo_struct}, x))

Base.unsafe_convert(::Type{Ptr{__JL_foo_struct}}, x::Ptr) = Ptr{__JL_foo_struct}(x)

const foo = Ptr{__JL_foo_struct}

struct foo_struct
    bar::foo
end

After:

mutable struct __JL_foo_struct
end

function Base.unsafe_load(x::Ptr{__JL_foo_struct})
    unsafe_load(Ptr{foo_struct}(x))
end

function Base.getproperty(x::Ptr{__JL_foo_struct}, f::Symbol)
    getproperty(Ptr{foo_struct}(x), f)
end

function Base.setproperty!(x::Ptr{__JL_foo_struct}, f::Symbol, v)
    setproperty!(Ptr{foo_struct}(x), f, v)
end

const foo = Ptr{__JL_foo_struct}

struct foo_struct
    bar::foo
end
Base.unsafe_convert(::Type{Ptr{__JL_foo_struct}}, x::Ref{foo_struct}) = Base.unsafe_convert(Ptr{__JL_foo_struct}, Base.unsafe_convert(Ptr{foo_struct}, x))

Base.unsafe_convert(::Type{Ptr{__JL_foo_struct}}, x::Ptr{foo_struct}) = Ptr{__JL_foo_struct}(x)

I'm not sure why there's no newline after the struct definition 馃

`emit!()` for `TypedefMutualRef` will create some specializations of
`Base.unsafe_convert()`, and previously they didn't declare a type for the
`Ref`/`Ptr` value being passed to them, which would cause a method ambiguity
with Base (detected by Aqua.jl).

The problem is that the typedef will of course be declared in the C header
before the struct it references, so the `Base.unsafe_convert()` specializations
couldn't use the actual struct type in their signature because it won't have
been created yet. This commit fixes that with the notion of a *partially emitted
node* that contains *premature exprs* that haven't been emitted yet. Now
`emit!()` for `TypedefMutualRef` will record the `Base.unsafe_convert()` methods
as premature exprs and mark itself as a partially emitted node. Then later,
`emit!()` for the `StructDefinition` will look for any partially emitted nodes
that are marked for it and emit their premature expressions itself.
@JamesWrigley
Copy link
Member Author

I'll try fixing the docs, but I have no idea what's going on with the Windows CI 馃憖 AFAICT it seems unrelated?

Useful if some codebase is missing docstrings for a few definitions.
It looks like this also automatically the version of Clang 15 used.
@JamesWrigley
Copy link
Member Author

Well, that was a bit of a rabbit hole 馃檭 TL;DR:

  • One reason the docs weren't building is because of missing docstrings, so I added support for using callback_documentation as a fallback even when extract_c_comment_style is set (5c78b0a).
  • Then I regenerated the bindings in 25acb38, but my system seems to have pulled in a newer version of clang 15? Not sure how important that is, if you like I can remove all the non-docstring hunks from the commit.
  • And finally, fixed the remaining issues with the docs (bd2fc8a).

@JamesWrigley
Copy link
Member Author

Hmph, now I know why the windows tests are failing... 7zip was recently moved to a different directory, which is used by BinDeps.jl, which is used by CMake.jl, which is used by our tests: JuliaLang/julia#48931
That was backported to 1.9, which is why the Julia 1 tests are failing too and not just nightly. Relevant issue: JuliaPackaging/CMake.jl#23

JamesWrigley added a commit to JamesWrigley/Clang.jl that referenced this pull request Dec 22, 2023
CMake.jl is currently broken on 1.9 because the location of 7z.exe changed:
- JuliaPackaging/CMake.jl#23
- JuliaLang/julia#48931
- JuliaInterop#458 (comment)
@JamesWrigley
Copy link
Member Author

Ok, got there in the end 馃帀 Main fix was switching to CMake_jll in 31876f0, and then some other minor fixes in 3afee34 and 61f1c48.

@@ -6937,7 +7112,7 @@ end

const CINDEX_VERSION_MAJOR = 0

const CINDEX_VERSION_MINOR = 62
const CINDEX_VERSION_MINOR = 63
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

although these low-level APIs are not exported by Clang.jl, but I think we should bump Clang.jl's minor version as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, fixed in 423820b.

src/type.jl Outdated
@@ -70,7 +70,7 @@ getPointeeType(t::CLType)::CLType = clang_getPointeeType(t)
getTypeDeclaration(t::CXType) -> CXCursor
getTypeDeclaration(t::CLType) -> CLCursor
Return the cursor for the declaration of the given type. To get the type of the cursor,
see [`type`](@ref). Wrapper for libclang's [`clang_getTypeDeclaration`](@ref).
see `typeof`. Wrapper for libclang's [`clang_getTypeDeclaration`](@ref).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
see `typeof`. Wrapper for libclang's [`clang_getTypeDeclaration`](@ref).
see [`getCursorType`](@ref). Wrapper for libclang's [`clang_getTypeDeclaration`](@ref).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops 馃槄 Fixed in 49abae7.

@Gnimuc
Copy link
Member

Gnimuc commented Dec 23, 2023

Thanks for fixing this! I'll give it a test and update the test-suite: https://github.com/Gnimuc/GeneratorScripts

Note that :missing_docs is now warn-only because it was complaining about
everything in Clang.Generators, which we don't want/need to document. I didn't
have any luck ignoring those with a `Filter` either.
This was polluting the `readdir()` results and causing the BB build to wrongly
be marked as failed and fall back to the native build method with
`build_libbitfield_native()`.

Also added a full backtrace to the warning logs when build errors do occur in
either functions.
CMake.jl is currently broken on 1.9 because the location of 7z.exe changed:
- JuliaPackaging/CMake.jl#23
- JuliaLang/julia#48931
- JuliaInterop#458 (comment)
This seems to be required on Windows. Also cleaned up the whitespace.
@Gnimuc Gnimuc merged commit 8b698dc into JuliaInterop:master Dec 24, 2023
11 checks passed
Gnimuc pushed a commit that referenced this pull request Dec 24, 2023
CMake.jl is currently broken on 1.9 because the location of 7z.exe changed:
- JuliaPackaging/CMake.jl#23
- JuliaLang/julia#48931
- #458 (comment)
Gnimuc added a commit to Gnimuc/GeneratorScripts that referenced this pull request Dec 24, 2023
@JamesWrigley JamesWrigley deleted the method-ambiguity branch December 24, 2023 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants