diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index a50edeb4c72a0..0645f41879b51 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -1147,6 +1147,8 @@ function typeinf_local(frame::InferenceState) # only propagate information we know we can store # and is valid inter-procedurally rt = widenconst(rt) + elseif isa(rt, Const) && rt.actual + rt = Const(rt.val) end if tchanged(rt, frame.bestguess) # new (wider) return type for frame diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index 9e5e3f2731816..97cbba7ad0173 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -663,7 +663,7 @@ function analyze_method!(idx::Int, sig::Signature, @nospecialize(metharg), meths methsig = method.sig # Check whether this call just evaluates to a constant - if isa(f, widenconst(ft)) && !isdefined(method, :generator) && method.pure && + if isa(f, widenconst(ft)) && isa(stmttyp, Const) && stmttyp.actual && is_inlineable_constant(stmttyp.val) return ConstantCase(quoted(stmttyp.val), method, Any[methsp...], metharg) end diff --git a/test/compiler/contextual.jl b/test/compiler/contextual.jl index 7b12cd380f425..e2b235830c2d4 100644 --- a/test/compiler/contextual.jl +++ b/test/compiler/contextual.jl @@ -62,7 +62,7 @@ module MiniCassette end function overdub_generator(self, c, f, args) - if f <: Core.Builtin || !isdefined(f, :instance) + if !isdefined(f, :instance) return :(return f(args...)) end @@ -83,6 +83,10 @@ module MiniCassette code_info end + @inline function overdub(c::Ctx, f::Union{Core.Builtin, Core.IntrinsicFunction}, args...) + f(args...) + end + @eval function overdub(c::Ctx, f, args...) $(Expr(:meta, :generated_only)) $(Expr(:meta, @@ -112,5 +116,20 @@ f() = 2 # Test that pure propagates for Cassette Base.@pure isbitstype(T) = T.isbitstype f31012(T) = Val(isbitstype(T)) -@test @inferred overdub(Ctx(), f31012, Int64) == Val(true) +@test @inferred(overdub(Ctx(), f31012, Int64)) == Val(true) + +@generated bar(::Val{align}) where {align} = :(42) +foo(i) = i+bar(Val(1)) +@test @inferred(overdub(Ctx(), foo, 1)) == 43 + +# Check that misbehaving pure functions propagate their error +Base.@pure func1() = 42 +Base.@pure func2() = (this_is_an_exception; func1()) + +let method = which(func2, ()) + mi = Core.Compiler.specialize_method(method, Tuple{typeof(func2)}, Core.svec()) + mi.inInference = true +end +func3() = func2() +@test_throws UndefVarError func3()