diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 6276544100888..fb76331c04e55 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -966,11 +966,47 @@ function split_cfg_entry(ce::ConfigEntry) end # Abstract object types + +""" + AbstractGitObject + +`AbstractGitObject`s must obey the following interface: +- `obj.owner`, if present, must be a `Union{Nothing,GitRepo,GitTree}` +- `obj.ptr`, if present, must be a `Union{Ptr{Cvoid},Ptr{SignatureStruct}}` +""" abstract type AbstractGitObject end + +function Base.getproperty(obj::AbstractGitObject, name::Symbol) + # These type-assertions enforce the interface requirements above. + # They assist type-inference in cases where the compiler only knows that it + # has an `AbstractGitObject` without being certain about the concrete type. + # See detailed explanation in https://github.com/JuliaLang/julia/pull/36452. + if name === :owner + return getfield(obj, :owner)::Union{Nothing,GitRepo,GitTree} + elseif name === :ptr + return getfield(obj, :ptr)::Union{Ptr{Cvoid},Ptr{SignatureStruct}} + else + return getfield(obj, name) + end +end + Base.isempty(obj::AbstractGitObject) = (obj.ptr == C_NULL) +# `GitObject`s must obey the following interface: +# - `obj.owner` must be a `GitRepo` +# - `obj.ptr` must be a Ptr{Cvoid} abstract type GitObject <: AbstractGitObject end +function Base.getproperty(obj::GitObject, name::Symbol) + if name === :owner + return getfield(obj, :owner)::GitRepo + elseif name === :ptr + return getfield(obj, :ptr)::Ptr{Cvoid} + else + return getfield(obj, name) + end +end + for (typ, owntyp, sup, cname) in [ (:GitRepo, nothing, :AbstractGitObject, :git_repository), (:GitConfig, :(Union{GitRepo, Nothing}), :AbstractGitObject, :git_config),