Skip to content

Commit

Permalink
make preference loading a bit more type stable (JuliaLang#38285)
Browse files Browse the repository at this point in the history
* make preference loading a bit nicer to inference
  • Loading branch information
KristofferC authored Nov 3, 2020
1 parent 469d6f8 commit ac8445c
Showing 1 changed file with 36 additions and 33 deletions.
69 changes: 36 additions & 33 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1535,19 +1535,20 @@ end

# Test to see if this UUID is mentioned in this `Project.toml`; either as
# the top-level UUID (e.g. that of the project itself) or as a dependency.
function get_uuid_name(project::Dict, uuid::UUID)
if haskey(project, "uuid") && haskey(project, "name") &&
UUID(project["uuid"]::String) == uuid
return project["name"]::String
elseif haskey(project, "deps")
struuid = string(uuid)
for (k, v) in project["deps"]::Dict{String, Any}
if v::String == struuid
return k::String
function get_uuid_name(project::Dict{String, Any}, uuid::UUID)
uuid_p = get(project, "uuid", nothing)::Union{Nothing, String}
name = get(project, "name", nothing)::Union{Nothing, String}
if name !== nothing && uuid_p !== nothing && UUID(uuid_p) == uuid
return name
end
deps = get(project, "deps", nothing)::Union{Nothing, Dict{String, Any}}
if deps !== nothing
for (k, v) in deps
if uuid == UUID(v::String)
return k
end
end
end

return nothing
end

Expand All @@ -1556,7 +1557,7 @@ function get_uuid_name(project_toml::String, uuid::UUID)
return get_uuid_name(project, uuid)
end

function collect_preferences!(project_toml::String, uuid::UUID)
function collect_preferences(project_toml::String, uuid::UUID)
# We'll return a list of dicts to be merged
dicts = Dict{String, Any}[]

Expand All @@ -1568,8 +1569,9 @@ function collect_preferences!(project_toml::String, uuid::UUID)
end

# Look first inside of `Project.toml` to see we have preferences embedded within there
if haskey(project, "preferences") && isa(project["preferences"], Dict)
push!(dicts, get(project["preferences"], pkg_name, Dict()))
proj = get(project, "preferences", nothing)
if proj isa Dict{String, Any}
push!(dicts, get(Dict{String, Any}, proj, pkg_name)::Dict{String, Any})
end

# Next, look for `(Julia)LocalPreferences.toml` files next to this `Project.toml`
Expand All @@ -1578,7 +1580,7 @@ function collect_preferences!(project_toml::String, uuid::UUID)
toml_path = joinpath(project_dir, name)
if isfile(toml_path)
prefs = parsed_toml(toml_path)
push!(dicts, get(prefs, pkg_name, Dict{String,Any}())::Dict{String,Any})
push!(dicts, get(Dict{String, Any}, prefs, pkg_name)::Dict{String,Any})

# If we find `JuliaLocalPreferences.toml`, don't look for `LocalPreferences.toml`
break
Expand All @@ -1594,23 +1596,25 @@ end
Helper function to merge preference dicts recursively, honoring overrides in nested
dictionaries properly.
"""
function recursive_prefs_merge(base::Dict, overrides::Dict...)
function recursive_prefs_merge(base::Dict{String, Any}, overrides::Dict{String, Any}...)
new_base = Base._typeddict(base, overrides...)

for override in overrides
# Clear entries are keys that should be deleted from any previous setting.
if haskey(override, "__clear__") && isa(override["__clear__"], Vector)
for k in override["__clear__"]
override_clear = get(override, "__clear__", nothing)
if override_clear isa Vector{String}
for k in override_clear
delete!(new_base, k)
end
end

for (k, v) in override
for (k, override_k) in override
# Note that if `base` has a mapping that is _not_ a `Dict`, and `override`
if haskey(new_base, k) && isa(new_base[k], Dict) && isa(override[k], Dict)
new_base[k] = recursive_prefs_merge(new_base[k], override[k])
new_base_k = get(new_base, k, nothing)
if new_base_k isa Dict{String, Any} && override_k isa Dict{String, Any}
new_base[k] = recursive_prefs_merge(new_base_k, override_k)
else
new_base[k] = override[k]
new_base[k] = override_k
end
end
end
Expand All @@ -1626,29 +1630,31 @@ function get_preferences(uuid::UUID)
end

# Collect all dictionaries from the current point in the load path, then merge them in
dicts = collect_preferences!(project_toml, uuid)
dicts = collect_preferences(project_toml, uuid)
merged_prefs = recursive_prefs_merge(merged_prefs, dicts...)
end
return merged_prefs
end

function get_preferences_hash(uuid::UUID, prefs_list::Vector{String})
function get_preferences_hash(uuid::Union{UUID, Nothing}, prefs_list::Vector{String})
# Start from the "null" hash
h = get_preferences_hash(nothing, prefs_list)
h = UInt64(0x6e65726566657250)
uuid === nothing && return h

# Load the preferences
prefs = get_preferences(uuid)

# Walk through each name that's called out as a compile-time preference
for name in prefs_list
if haskey(prefs, name)
h = hash(prefs[name], h)
prefs_name = get(prefs, name, nothing)::Union{String, Nothing}
if prefs_name !== nothing
h = hash(prefs_name, h)
end
end
return h
end

get_preferences_hash(m::Module, prefs_list::Vector{String}) = get_preferences_hash(PkgId(m).uuid, prefs_list)
get_preferences_hash(::Nothing, prefs_list::Vector{String}) = UInt64(0x6e65726566657250)

# This is how we keep track of who is using what preferences at compile-time
const COMPILETIME_PREFERENCES = Dict{UUID,Set{String}}()
Expand All @@ -1657,14 +1663,11 @@ const COMPILETIME_PREFERENCES = Dict{UUID,Set{String}}()
# we mark that usage as a usage at compile-time and call this method, so that at the end of `.ji` generation,
# we can record the list of compile-time preferences and embed that into the `.ji` header
function record_compiletime_preference(uuid::UUID, key::String)
if !haskey(COMPILETIME_PREFERENCES, uuid)
COMPILETIME_PREFERENCES[uuid] = Set((key,))
else
push!(COMPILETIME_PREFERENCES[uuid], key)
end
pref = get!(Set{String}, COMPILETIME_PREFERENCES, uuid)
push!(pref, key)
return nothing
end
get_compiletime_preferences(uuid::UUID) = collect(get(COMPILETIME_PREFERENCES, uuid, String[]))
get_compiletime_preferences(uuid::UUID) = collect(get(Vector{String}, COMPILETIME_PREFERENCES, uuid))
get_compiletime_preferences(m::Module) = get_compiletime_preferences(PkgId(m).uuid)
get_compiletime_preferences(::Nothing) = String[]

Expand Down

0 comments on commit ac8445c

Please sign in to comment.