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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

type inference runtime correctness (oldworld) #17057

Merged
merged 8 commits into from
Dec 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Language changes
for `.*` etcetera. This also means that "dot operations" automatically
fuse into a single loop, along with other dot calls `f.(x)`. ([#17623])

* Newly defined methods are no longer callable from the same dynamic runtime
scope they were defined in ([#17057]).

Breaking changes
----------------

Expand Down Expand Up @@ -50,6 +53,10 @@ This section lists changes that do not have deprecation warnings.
* `broadcast` now treats `Ref` (except for `Ptr`) arguments as 0-dimensional
arrays ([#18965]).

* The runtime now enforces when new method definitions can take effect ([#17057]).
The flip-side of this is that new method definitions should now reliably actually
take effect, and be called when evaluating new code ([#265]).

Library improvements
--------------------

Expand Down
6 changes: 3 additions & 3 deletions base/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function eval_user_input(ast::ANY, backend::REPLBackend)
value = eval(Main, ast)
backend.in_eval = false
# note: value wrapped in a closure to ensure it doesn't get passed through expand
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
put!(backend.response_channel, (value, nothing))
end
break
Expand Down Expand Up @@ -153,9 +153,9 @@ function print_response(errio::IO, val::ANY, bt, show_value::Bool, have_color::B
if val !== nothing && show_value
try
if specialdisplay === nothing
display(val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(val)))))
else
display(specialdisplay,val)
eval(Main, Expr(:body, Expr(:return, Expr(:call, specialdisplay, QuoteNode(val)))))
end
catch err
println(errio, "Error showing value of type ", typeof(val), ":")
Expand Down
5 changes: 3 additions & 2 deletions base/REPLCompletions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,12 @@ function get_type_call(expr::Expr)
found ? push!(args, typ) : push!(args, Any)
end
# use _methods_by_ftype as the function is supplied as a type
mt = Base._methods_by_ftype(Tuple{ft, args...}, -1)
world = typemax(UInt)
Copy link
Sponsor Member

Choose a reason for hiding this comment

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

Can these be default values of the extra arguments to _methods_by_ftype?

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

yeah, I'll add a cleanup note. This commit was a bit of a hack-and-slash job.

mt = Base._methods_by_ftype(Tuple{ft, args...}, -1, world)
length(mt) == 1 || return (Any, false)
m = first(mt)
# Typeinference
params = Core.Inference.InferenceParams()
params = Core.Inference.InferenceParams(world)
return_type = Core.Inference.typeinf_type(m[3], m[1], m[2], true, params)
return_type === nothing && return (Any, false)
return (return_type, true)
Expand Down
3 changes: 3 additions & 0 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ Alternatively, there is no unique most-specific method.
type MethodError <: Exception
f
args
world::UInt
MethodError(f::ANY, args::ANY, world::UInt) = new(f, args, world)
end
MethodError(f::ANY, args::ANY) = MethodError(f, args, typemax(UInt))

"""
EOFError()
Expand Down
10 changes: 10 additions & 0 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ unsafe_convert{T}(::Type{T}, x::T) = x

typealias NTuple{N,T} Tuple{Vararg{T,N}}


# primitive array constructors
(::Type{Array{T,N}}){T,N}(d::NTuple{N,Int}) =
ccall(:jl_new_array, Array{T,N}, (Any,Any), Array{T,N}, d)
Expand Down Expand Up @@ -338,6 +339,15 @@ Array{T}(::Type{T}, m::Int,n::Int) = Array{T,2}(m,n)
Array{T}(::Type{T}, m::Int,n::Int,o::Int) = Array{T,3}(m,n,o)


# primitive Symbol constructors
Symbol(s::String) = Symbol(s.data)
function Symbol(a::Array{UInt8,1})
return ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int),
ccall(:jl_array_ptr, Ptr{UInt8}, (Any,), a),
Intrinsics.arraylen(a))
end


# docsystem basics
macro doc(x...)
atdoc(x...)
Expand Down
7 changes: 4 additions & 3 deletions base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,13 @@ function eval_user_input(ast::ANY, show_value)
else
ast = expand(ast)
value = eval(Main, ast)
eval(Main, Expr(:(=), :ans, Expr(:call, ()->value)))
if value!==nothing && show_value
eval(Main, Expr(:body, Expr(:(=), :ans, QuoteNode(value)), Expr(:return, nothing)))
if !(value === nothing) && show_value
if have_color
print(answer_color())
end
try display(value)
try
eval(Main, Expr(:body, Expr(:return, Expr(:call, display, QuoteNode(value)))))
catch err
println(STDERR, "Evaluation succeeded, but an error occurred while showing value of type ", typeof(value), ":")
rethrow(err)
Expand Down
19 changes: 6 additions & 13 deletions base/coreimg.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@ import Core: print, println, show, write, unsafe_write, STDOUT, STDERR

ccall(:jl_set_istopmod, Void, (Bool,), false)

eval(x) = Core.eval(Inference,x)
eval(m,x) = Core.eval(m,x)
eval(x) = Core.eval(Inference, x)
eval(m, x) = Core.eval(m, x)

include = Core.include
const include = Core.include
# conditional to allow redefining Core.Inference after base exists
isdefined(Main, :Base) || ((::Type{T}){T}(arg) = convert(T, arg)::T)

## Load essential files and libraries
include("ctypes.jl")
include("essentials.jl")
include("ctypes.jl")
include("generator.jl")
include("reflection.jl")
include("options.jl")
Expand All @@ -33,15 +35,6 @@ include("operators.jl")
include("pointer.jl")
const checked_add = +
const checked_sub = -
if !isdefined(Main, :Base)
# conditional to allow redefining Core.Inference after base exists
(::Type{T}){T}(arg) = convert(T, arg)::T
end

# Symbol constructors
Symbol(s::String) = Symbol(s.data)
Symbol(a::Array{UInt8,1}) =
ccall(:jl_symbol_n, Ref{Symbol}, (Ptr{UInt8}, Int32), a, length(a))

# core array operations
include("array.jl")
Expand Down
2 changes: 1 addition & 1 deletion base/docs/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import ..esc, ..push!, ..getindex, ..current_module, ..unsafe_load, ..Csize_t
function doc!(str, ex)
ptr = unsafe_load(Core.Intrinsics.cglobal(:jl_filename, Ptr{UInt8}))
len = ccall(:strlen, Csize_t, (Ptr{UInt8},), ptr)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Int32), ptr, len)
file = ccall(:jl_symbol_n, Any, (Ptr{UInt8}, Csize_t), ptr, len)
line = unsafe_load(Core.Intrinsics.cglobal(:jl_lineno, Int32)) # Cint
push!(DOCS, (current_module(), ex, str, file, line))
end
Expand Down
6 changes: 4 additions & 2 deletions base/error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ systemerror(p, b::Bool; extrainfo=nothing) = b ? throw(Main.Base.SystemError(str
assert(x) = x ? nothing : throw(Main.Base.AssertionError())
macro assert(ex, msgs...)
msg = isempty(msgs) ? ex : msgs[1]
if !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
if isa(msg, AbstractString)
msg = msg # pass-through
elseif !isempty(msgs) && (isa(msg, Expr) || isa(msg, Symbol))
# message is an expression needing evaluating
msg = :(Main.Base.string($(esc(msg))))
elseif isdefined(Main, :Base) && isdefined(Main.Base, :string)
Expand All @@ -47,7 +49,7 @@ macro assert(ex, msgs...)
# string() might not be defined during bootstrap
msg = :(Main.Base.string($(Expr(:quote,msg))))
end
:($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
return :($(esc(ex)) ? $(nothing) : throw(Main.Base.AssertionError($msg)))
end

# NOTE: Please keep the constant values specified below in sync with the doc string
Expand Down
Loading