• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37477

pending completion
#37477

push

local

web-flow
Allow external lattice elements to properly union split (#49030)

Currently `MustAlias` is the only lattice element that is allowed
to widen to union types. However, there are others in external
packages. Expand the support we have for this in order to allow
union splitting of lattice elements.

Co-authored-by: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com>

26 of 26 new or added lines in 5 files covered. (100.0%)

71476 of 82705 relevant lines covered (86.42%)

34756248.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.11
/base/pointer.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
"""
4
    Ptr{T}
5

6
A memory address referring to data of type `T`.  However, there is no guarantee that the
7
memory is actually valid, or that it actually represents data of the specified type.
8
"""
9
Ptr
10

11
## converting pointers to an appropriate unsigned ##
12

13
"""
14
    C_NULL
15

16
The C null pointer constant, sometimes used when calling external code.
17
"""
18
const C_NULL = bitcast(Ptr{Cvoid}, 0)
19

20
# TODO: deprecate these conversions. C doesn't even allow them.
21

22
# pointer to integer
23
convert(::Type{T}, x::Ptr) where {T<:Integer} = T(UInt(x))::T
204,812✔
24

25
# integer to pointer
26
convert(::Type{Ptr{T}}, x::Union{Int,UInt}) where {T} = Ptr{T}(x)
1,067,579,378✔
27

28
# pointer to pointer
29
convert(::Type{Ptr{T}}, p::Ptr{T}) where {T} = p
4,527✔
30
convert(::Type{Ptr{T}}, p::Ptr) where {T} = bitcast(Ptr{T}, p)::Ptr{T}
1,058,755,772✔
31

32
# object to pointer (when used with ccall)
33

34
"""
35
    unsafe_convert(T, x)
36

37
Convert `x` to a C argument of type `T`
38
where the input `x` must be the return value of `cconvert(T, ...)`.
39

40
In cases where [`convert`](@ref) would need to take a Julia object
41
and turn it into a `Ptr`, this function should be used to define and perform
42
that conversion.
43

44
Be careful to ensure that a Julia reference to `x` exists as long as the result of this
45
function will be used. Accordingly, the argument `x` to this function should never be an
46
expression, only a variable name or field reference. For example, `x=a.b.c` is acceptable,
47
but `x=[a,b,c]` is not.
48

49
The `unsafe` prefix on this function indicates that using the result of this function after
50
the `x` argument to this function is no longer accessible to the program may cause undefined
51
behavior, including program corruption or segfaults, at any later time.
52

53
See also [`cconvert`](@ref)
54
"""
55
function unsafe_convert end
56

57
unsafe_convert(::Type{Ptr{UInt8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{UInt8}, (Any,), x)
902,009✔
58
unsafe_convert(::Type{Ptr{Int8}}, x::Symbol) = ccall(:jl_symbol_name, Ptr{Int8}, (Any,), x)
33,773,644✔
59
unsafe_convert(::Type{Ptr{UInt8}}, s::String) = ccall(:jl_string_ptr, Ptr{UInt8}, (Any,), s)
437,146,747✔
60
unsafe_convert(::Type{Ptr{Int8}}, s::String) = ccall(:jl_string_ptr, Ptr{Int8}, (Any,), s)
2,623,199✔
61
# convert strings to String etc. to pass as pointers
62
cconvert(::Type{Ptr{UInt8}}, s::AbstractString) = String(s)
259✔
63
cconvert(::Type{Ptr{Int8}}, s::AbstractString) = String(s)
×
64

65
unsafe_convert(::Type{Ptr{T}}, a::Array{T}) where {T} = ccall(:jl_array_ptr, Ptr{T}, (Any,), a)
641,064,989✔
66
unsafe_convert(::Type{Ptr{S}}, a::AbstractArray{T}) where {S,T} = convert(Ptr{S}, unsafe_convert(Ptr{T}, a))
156,493,455✔
67
unsafe_convert(::Type{Ptr{T}}, a::AbstractArray{T}) where {T} = error("conversion to pointer not defined for $(typeof(a))")
8✔
68

69
# unsafe pointer to array conversions
70
"""
71
    unsafe_wrap(Array, pointer::Ptr{T}, dims; own = false)
72

73
Wrap a Julia `Array` object around the data at the address given by `pointer`,
74
without making a copy.  The pointer element type `T` determines the array
75
element type. `dims` is either an integer (for a 1d array) or a tuple of the array dimensions.
76
`own` optionally specifies whether Julia should take ownership of the memory,
77
calling `free` on the pointer when the array is no longer referenced.
78

79
This function is labeled "unsafe" because it will crash if `pointer` is not
80
a valid memory address to data of the requested length. Unlike [`unsafe_load`](@ref)
81
and [`unsafe_store!`](@ref), the programmer is responsible also for ensuring that the
82
underlying data is not accessed through two arrays of different element type, similar
83
to the strict aliasing rule in C.
84
"""
85
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
8,380✔
86
                     p::Ptr{T}, dims::NTuple{N,Int}; own::Bool = false) where {T,N}
87
    ccall(:jl_ptr_to_array, Array{T,N}, (Any, Ptr{Cvoid}, Any, Int32),
4,191✔
88
          Array{T,N}, p, dims, own)
89
end
90
function unsafe_wrap(::Union{Type{Array},Type{Array{T}},Type{Array{T,1}}},
935✔
91
                     p::Ptr{T}, d::Integer; own::Bool = false) where {T}
92
    ccall(:jl_ptr_to_array_1d, Array{T,1},
698✔
93
          (Any, Ptr{Cvoid}, Csize_t, Cint), Array{T,1}, p, d, own)
94
end
95
unsafe_wrap(Atype::Union{Type{Array},Type{Array{T}},Type{Array{T,N}}},
96
            p::Ptr{T}, dims::NTuple{N,<:Integer}; own::Bool = false) where {T,N} =
7,852✔
97
    unsafe_wrap(Atype, p, convert(Tuple{Vararg{Int}}, dims), own = own)
98

99
"""
100
    unsafe_load(p::Ptr{T}, i::Integer=1)
101

102
Load a value of type `T` from the address of the `i`th element (1-indexed) starting at `p`.
103
This is equivalent to the C expression `p[i-1]`.
104

105
The `unsafe` prefix on this function indicates that no validation is performed on the
106
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
107
that referenced memory is not freed or garbage collected while invoking this function.
108
Incorrect usage may segfault your program or return garbage answers. Unlike C, dereferencing
109
memory region allocated as different type may be valid provided that the types are compatible.
110
"""
111
unsafe_load(p::Ptr, i::Integer=1) = pointerref(p, Int(i), 1)
1,667,855,469✔
112

113
"""
114
    unsafe_store!(p::Ptr{T}, x, i::Integer=1)
115

116
Store a value of type `T` to the address of the `i`th element (1-indexed) starting at `p`.
117
This is equivalent to the C expression `p[i-1] = x`.
118

119
The `unsafe` prefix on this function indicates that no validation is performed on the
120
pointer `p` to ensure that it is valid. Like C, the programmer is responsible for ensuring
121
that referenced memory is not freed or garbage collected while invoking this function.
122
Incorrect usage may segfault your program. Unlike C, storing memory region allocated as
123
different type may be valid provided that that the types are compatible.
124
"""
125
unsafe_store!(p::Ptr{Any}, @nospecialize(x), i::Integer=1) = pointerset(p, x, Int(i), 1)
1✔
126
unsafe_store!(p::Ptr{T}, x, i::Integer=1) where {T} = pointerset(p, convert(T,x), Int(i), 1)
128,514,713✔
127

128
# convert a raw Ptr to an object reference, and vice-versa
129
"""
130
    unsafe_pointer_to_objref(p::Ptr)
131

132
Convert a `Ptr` to an object reference. Assumes the pointer refers to a valid heap-allocated
133
Julia object. If this is not the case, undefined behavior results, hence this function is
134
considered "unsafe" and should be used with care.
135

136
See also [`pointer_from_objref`](@ref).
137
"""
138
unsafe_pointer_to_objref(x::Ptr) = ccall(:jl_value_ptr, Any, (Ptr{Cvoid},), x)
1,894,947✔
139

140
"""
141
    pointer_from_objref(x)
142

143
Get the memory address of a Julia object as a `Ptr`. The existence of the resulting `Ptr`
144
will not protect the object from garbage collection, so you must ensure that the object
145
remains referenced for the whole time that the `Ptr` will be used.
146

147
This function may not be called on immutable objects, since they do not have
148
stable memory addresses.
149

150
See also [`unsafe_pointer_to_objref`](@ref).
151
"""
152
function pointer_from_objref(@nospecialize(x))
1,441,197✔
153
    @inline
1,439,666✔
154
    ismutable(x) || error("pointer_from_objref cannot be used on immutable objects")
1,441,128✔
155
    ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x)
796,419,395✔
156
end
157

158
## limited pointer arithmetic & comparison ##
159

160
isequal(x::Ptr, y::Ptr) = (x === y)
×
161
isless(x::Ptr{T}, y::Ptr{T}) where {T} = x < y
×
162

163
==(x::Ptr, y::Ptr) = UInt(x) == UInt(y)
598,734,126✔
164
<(x::Ptr,  y::Ptr) = UInt(x) < UInt(y)
44,258,212✔
165
-(x::Ptr,  y::Ptr) = UInt(x) - UInt(y)
3,483,118✔
166

167
+(x::Ptr, y::Integer) = oftype(x, add_ptr(UInt(x), (y % UInt) % UInt))
775,489,461✔
168
-(x::Ptr, y::Integer) = oftype(x, sub_ptr(UInt(x), (y % UInt) % UInt))
292,158,617✔
169
+(x::Integer, y::Ptr) = y + x
1✔
170

171
unsigned(x::Ptr) = UInt(x)
×
172
signed(x::Ptr) = Int(x)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc