Skip to content

Commit 3699192

Browse files
authored
Merge pull request #32427 from JuliaLang/jn/Tuple-pure
reduce usage of _pure_meta macro annotation
2 parents de9c371 + 90c1159 commit 3699192

File tree

14 files changed

+188
-211
lines changed

14 files changed

+188
-211
lines changed

base/bool.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,7 @@ julia> .![true false true]
3030
0 1 0
3131
```
3232
"""
33-
function !(x::Bool)
34-
## We need a better heuristic to detect this automatically
35-
@_pure_meta
36-
return not_int(x)
37-
end
33+
!(x::Bool) = not_int(x)
3834

3935
(~)(x::Bool) = !x
4036
(&)(x::Bool, y::Bool) = and_int(x, y)

base/compiler/compiler.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ using .Iterators: zip, enumerate
7979
using .Iterators: Flatten, Filter, product # for generators
8080
include("namedtuple.jl")
8181

82+
ntuple(f, ::Val{0}) = ()
83+
ntuple(f, ::Val{1}) = (@_inline_meta; (f(1),))
84+
ntuple(f, ::Val{2}) = (@_inline_meta; (f(1), f(2)))
85+
ntuple(f, ::Val{3}) = (@_inline_meta; (f(1), f(2), f(3)))
86+
ntuple(f, ::Val{n}) where {n} = ntuple(f, n::Int)
87+
ntuple(f, n) = (Any[f(i) for i = 1:n]...,)
88+
8289
# core docsystem
8390
include("docs/core.jl")
8491

base/compiler/tfuncs.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -927,12 +927,16 @@ function _fieldtype_nothrow(@nospecialize(s), exact::Bool, name::Const)
927927
isa(fld, Int) || return false
928928
ftypes = datatype_fieldtypes(u)
929929
nf = length(ftypes)
930-
if u.name === Tuple.name && fld >= nf && isvarargtype(ftypes[nf])
931-
# If we don't know the exact type, the length of the tuple will be determined
932-
# at runtime and we can't say anything.
933-
return exact
930+
fld >= 1 || return false
931+
if u.name === Tuple.name && nf > 0 && isvarargtype(ftypes[nf])
932+
if !exact && fld >= nf
933+
# If we don't know the exact type, the length of the tuple will be determined
934+
# at runtime and we can't say anything.
935+
return false
936+
end
937+
elseif fld > nf
938+
return false
934939
end
935-
(fld >= 1 && fld <= nf) || return false
936940
return true
937941
end
938942

base/essentials.jl

Lines changed: 78 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,40 @@ macro specialize(vars...)
106106
return Expr(:meta, :specialize, vars...)
107107
end
108108

109+
"""
110+
@isdefined s -> Bool
111+
112+
Tests whether variable `s` is defined in the current scope.
113+
114+
See also [`isdefined`](@ref).
115+
116+
# Examples
117+
```jldoctest
118+
julia> @isdefined newvar
119+
false
120+
121+
julia> newvar = 1
122+
1
123+
124+
julia> @isdefined newvar
125+
true
126+
127+
julia> function f()
128+
println(@isdefined x)
129+
x = 3
130+
println(@isdefined x)
131+
end
132+
f (generic function with 1 method)
133+
134+
julia> f()
135+
false
136+
true
137+
```
138+
"""
139+
macro isdefined(s::Symbol)
140+
return Expr(:escape, Expr(:isdefined, s))
141+
end
142+
109143
macro _pure_meta()
110144
return Expr(:meta, :pure)
111145
end
@@ -207,31 +241,6 @@ ERROR: ArgumentError: Cannot call tail on an empty tuple.
207241
tail(x::Tuple) = argtail(x...)
208242
tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple."))
209243

210-
tuple_type_head(T::Type) = (@_pure_meta; fieldtype(T, 1))
211-
212-
function tuple_type_tail(T::Type)
213-
@_pure_meta
214-
if isa(T, UnionAll)
215-
return UnionAll(T.var, tuple_type_tail(T.body))
216-
elseif isa(T, Union)
217-
return Union{tuple_type_tail(T.a), tuple_type_tail(T.b)}
218-
else
219-
T.name === Tuple.name || throw(MethodError(tuple_type_tail, (T,)))
220-
if isvatuple(T) && length(T.parameters) == 1
221-
va = T.parameters[1]
222-
(isa(va, DataType) && isa(va.parameters[2], Int)) || return T
223-
return Tuple{Vararg{va.parameters[1], va.parameters[2]-1}}
224-
end
225-
return Tuple{argtail(T.parameters...)...}
226-
end
227-
end
228-
229-
tuple_type_cons(::Type, ::Type{Union{}}) = Union{}
230-
function tuple_type_cons(::Type{S}, ::Type{T}) where T<:Tuple where S
231-
@_pure_meta
232-
Tuple{S, T.parameters...}
233-
end
234-
235244
function unwrap_unionall(@nospecialize(a))
236245
while isa(a,UnionAll)
237246
a = a.body
@@ -248,7 +257,7 @@ end
248257

249258
# replace TypeVars in all enclosing UnionAlls with fresh TypeVars
250259
function rename_unionall(@nospecialize(u))
251-
if !isa(u,UnionAll)
260+
if !isa(u, UnionAll)
252261
return u
253262
end
254263
body = rename_unionall(u.body)
@@ -301,52 +310,49 @@ function typename(a::Union)
301310
end
302311
typename(union::UnionAll) = typename(union.body)
303312

304-
const AtLeast1 = Tuple{Any, Vararg{Any}}
305-
306-
# converting to empty tuple type
307-
convert(::Type{Tuple{}}, ::Tuple{}) = ()
308-
convert(::Type{Tuple{}}, x::AtLeast1) = throw(MethodError(convert, (Tuple{}, x)))
309-
310-
# converting to tuple types with at least one element
311-
convert(::Type{T}, x::T) where {T<:AtLeast1} = x
312-
convert(::Type{T}, x::AtLeast1) where {T<:AtLeast1} =
313-
(convert(tuple_type_head(T), x[1]), convert(tuple_type_tail(T), tail(x))...)
314-
315-
# converting to Vararg tuple types
316-
convert(::Type{Tuple{Vararg{V}}}, x::Tuple{Vararg{V}}) where {V} = x
317-
convert(T::Type{Tuple{Vararg{V}}}, x::Tuple) where {V} =
318-
(convert(tuple_type_head(T), x[1]), convert(T, tail(x))...)
319-
320-
# TODO: the following definitions are equivalent (behaviorally) to the above method
321-
# I think they may be faster / more efficient for inference,
322-
# if we could enable them, but are they?
323-
# TODO: These currently can't be used (#21026, #23017) since with
324-
# z(::Type{<:Tuple{Vararg{T}}}) where {T} = T
325-
# calling
326-
# z(Tuple{Val{T}} where T)
327-
# fails, even though `Type{Tuple{Val}} == Type{Tuple{Val{S}} where S}`
328-
# and so T should be `Val` (aka `Val{S} where S`)
329-
#convert(_::Type{Tuple{S}}, x::Tuple{S}) where {S} = x
330-
#convert(_::Type{Tuple{S}}, x::Tuple{Any}) where {S} = (convert(S, x[1]),)
331-
#convert(_::Type{T}, x::T) where {S, N, T<:Tuple{S, Vararg{S, N}}} = x
332-
#convert(_::Type{Tuple{S, Vararg{S, N}}},
333-
# x::Tuple{Any, Vararg{Any, N}}) where
334-
# {S, N} = cnvt_all(S, x...)
335-
#convert(_::Type{Tuple{Vararg{S, N}}},
336-
# x::Tuple{Vararg{Any, N}}) where
337-
# {S, N} = cnvt_all(S, x...)
338-
# TODO: These are similar to the methods we currently use but cnvt_all might work better:
339-
#convert(_::Type{Tuple{Vararg{S}}},
340-
# x::Tuple{Any, Vararg{Any}}) where
341-
# {S} = cnvt_all(S, x...)
342-
#convert(_::Type{Tuple{Vararg{S}}},
343-
# x::Tuple{Vararg{Any}}) where
344-
# {S} = cnvt_all(S, x...)
345-
#cnvt_all(T) = ()
346-
#cnvt_all(T, x, rest...) = (convert(T, x), cnvt_all(T, rest...)...)
347-
# TODO: These may be necessary if the above are enabled
313+
_tuple_error(T::Type, x) = (@_noinline_meta; throw(MethodError(convert, (T, x))))
314+
315+
convert(::Type{T}, x::T) where {T<:Tuple} = x
316+
function convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:Tuple}
317+
# First see if there could be any conversion of the input type that'd be a subtype of the output.
318+
# If not, we'll throw an explicit MethodError (otherwise, it might throw a typeassert).
319+
if typeintersect(NTuple{N,Any}, T) === Union{}
320+
_tuple_error(T, x)
321+
end
322+
cvt1(n) = (@_inline_meta; convert(fieldtype(T, n), getfield(x, n, #=boundscheck=#false)))
323+
return ntuple(cvt1, Val(N))::NTuple{N,Any}
324+
end
325+
326+
# optimizations?
327+
# converting to tuple types of fixed length
328+
#convert(::Type{T}, x::T) where {N, T<:NTuple{N,Any}} = x
329+
#convert(::Type{T}, x::NTuple{N,Any}) where {N, T<:NTuple{N,Any}} =
330+
# ntuple(n -> convert(fieldtype(T, n), x[n]), Val(N))
331+
#convert(::Type{T}, x::Tuple{Vararg{Any}}) where {N, T<:NTuple{N,Any}} =
332+
# throw(MethodError(convert, (T, x)))
333+
# converting to tuple types of indefinite length
334+
#convert(::Type{Tuple{Vararg{V}}}, x::Tuple{Vararg{V}}) where {V} = x
335+
#convert(::Type{NTuple{N, V}}, x::NTuple{N, V}) where {N, V} = x
336+
#function convert(T::Type{Tuple{Vararg{V}}}, x::Tuple) where {V}
337+
# @isdefined(V) || (V = fieldtype(T, 1))
338+
# return map(t -> convert(V, t), x)
339+
#end
340+
#function convert(T::Type{NTuple{N, V}}, x::NTuple{N, Any}) where {N, V}
341+
# @isdefined(V) || (V = fieldtype(T, 1))
342+
# return map(t -> convert(V, t), x)
343+
#end
344+
# short tuples
348345
#convert(::Type{Tuple{}}, ::Tuple{}) = ()
349-
#convert(::Type{Tuple{Vararg{S}}} where S, ::Tuple{}) = ()
346+
#convert(::Type{Tuple{S}}, x::Tuple{S}) where {S} = x
347+
#convert(::Type{Tuple{S, T}}, x::Tuple{S, T}) where {S, T} = x
348+
#convert(::Type{Tuple{S, T, U}}, x::Tuple{S, T, U}) where {S, T, U} = x
349+
#convert(::Type{Tuple{S}}, x::Tuple{Any}) where {S} = (convert(S, x[1]),)
350+
#convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} = (convert(S, x[1]), convert(T, x[2]),)
351+
#convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = (convert(S, x[1]), convert(T, x[2]), convert(U, x[3]))
352+
#convert(::Type{Tuple{}}, x::Tuple) = _tuple_error(Tuple{}, x)
353+
#convert(::Type{Tuple{S}}, x::Tuple) = _tuple_error(Tuple{S}, x)
354+
#convert(::Type{Tuple{S, T}}, x::Tuple{Any, Any}) where {S, T} =_tuple_error(Tuple{S, T}, x)
355+
#convert(::Type{Tuple{S, T, U}}, x::Tuple{Any, Any, Any}) where {S, T, U} = _tuple_error(Tuple{S, T, U}, x)
350356

351357
"""
352358
oftype(x, y)
@@ -695,7 +701,7 @@ julia> f(Val(true))
695701
struct Val{x}
696702
end
697703

698-
Val(x) = (@_pure_meta; Val{x}())
704+
Val(x) = Val{x}()
699705

700706
"""
701707
invokelatest(f, args...; kwargs...)

0 commit comments

Comments
 (0)