diff --git a/NEWS.md b/NEWS.md index 2ff018ce96ce4..9bb942671afec 100644 --- a/NEWS.md +++ b/NEWS.md @@ -6,6 +6,8 @@ New language features * Structs with all isbits and isbitsunion fields are now stored inline in arrays ([#32448]). +* `import` now allows quoted symbols, e.g. `import Base.:+` ([#33158]). + Language changes ---------------- diff --git a/base/errorshow.jl b/base/errorshow.jl index ad2f9169bcd55..c9062eb0c5cb7 100644 --- a/base/errorshow.jl +++ b/base/errorshow.jl @@ -235,15 +235,14 @@ function showerror(io::IO, ex::MethodError) if f_is_function && isdefined(Base, name) basef = getfield(Base, name) if basef !== ex.f && hasmethod(basef, arg_types) - println(io) - print(io, "You may have intended to import Base.", name) + print(io, "\nYou may have intended to import ") + show_unquoted(io, Expr(:., :Base, QuoteNode(name))) end end if (ex.world != typemax(UInt) && hasmethod(ex.f, arg_types) && !hasmethod(ex.f, arg_types, world = ex.world)) curworld = get_world_counter() - println(io) - print(io, "The applicable method may be too new: running in world age $(ex.world), while current world is $(curworld).") + print(io, "\nThe applicable method may be too new: running in world age $(ex.world), while current world is $(curworld).") end if !is_arg_types # Check for row vectors used where a column vector is intended. @@ -455,8 +454,7 @@ function show_method_candidates(io::IO, ex::MethodError, @nospecialize kwargs=() if !isempty(lines) # Display up to three closest candidates Base.with_output_color(:normal, io) do io - println(io) - print(io, "Closest candidates are:") + print(io, "\nClosest candidates are:") sort!(lines, by = x -> -x[2]) i = 0 for line in lines diff --git a/src/ast.scm b/src/ast.scm index b9d4ac24c19ca..997135da7d042 100644 --- a/src/ast.scm +++ b/src/ast.scm @@ -274,6 +274,10 @@ (define (quoted? e) (memq (car e) '(quote top core globalref outerref line break inert meta))) (define (quotify e) `',e) +(define (unquote e) + (if (and (pair? e) (memq (car e) '(quote inert))) + (cadr e) + e)) (define (lam:args x) (cadr x)) (define (lam:vars x) (llist-vars (lam:args x))) diff --git a/src/julia-parser.scm b/src/julia-parser.scm index 1b7608fb0ad1a..5d4c142051eca 100644 --- a/src/julia-parser.scm +++ b/src/julia-parser.scm @@ -1602,7 +1602,7 @@ ((eq? nxt '|.|) (if (ts:space? s) (disallowed-space word nxt)) (take-token s) - (loop (cons (macrocall-to-atsym (parse-unary-prefix s)) path))) + (loop (cons (unquote (macrocall-to-atsym (parse-unary-prefix s))) path))) ((or (memv nxt '(#\newline #\; #\, :)) (eof-object? nxt)) (cons '|.| (reverse path))) diff --git a/test/errorshow.jl b/test/errorshow.jl index 5281382e7ad8f..cbac2a13ef3f6 100644 --- a/test/errorshow.jl +++ b/test/errorshow.jl @@ -206,7 +206,7 @@ import ..@except_str global + +() = nothing err_str = @except_str 1 + 2 MethodError -@test occursin("import Base.+", err_str) +@test occursin("import Base.:+", err_str) err_str = @except_str Float64[](1) MethodError @test !occursin("import Base.Array", err_str) @@ -578,3 +578,19 @@ let t1 = @async(error(1)), @test length(findall("Stacktrace:", s)) == 2 @test occursin("[1] error(::Int", s) end + +module TestMethodShadow + struct Foo; x; end + +(a::Foo, b::Foo) = Foo(a.x + b.x) + ==(a::Foo, b::Foo) = Foo(a.x == b.x) + div(a::Foo, b::Foo) = Foo(div(a.x, b.x)) +end +for (func,str) in ((TestMethodShadow.:+,":+"), (TestMethodShadow.:(==),":(==)"), (TestMethodShadow.:div,"div")) + ex = try + foo = TestMethodShadow.Foo(3) + func(foo,foo) + catch e + e + end::MethodError + @test occursin("You may have intended to import Base.$str", sprint(Base.showerror, ex)) +end \ No newline at end of file diff --git a/test/syntax.jl b/test/syntax.jl index fc6afd199b43f..4d445828e5284 100644 --- a/test/syntax.jl +++ b/test/syntax.jl @@ -1928,6 +1928,10 @@ end # Stream positioning after parsing var @test Meta.parse("var'", 1, greedy=false) == (:var, 4) +# quoted names in import (#33158) +@test Meta.parse("import Base.:+") == :(import Base.+) +@test Meta.parse("import Base.Foo.:(==).bar") == :(import Base.Foo.==.bar) + # issue #33135 function f33135(x::T) where {C1, T} let C1 = 1, C2 = 2 @@ -1935,3 +1939,4 @@ function f33135(x::T) where {C1, T} end end @test f33135(0) == 1 +