diff --git a/src/interface.jl b/src/interface.jl index 95b77f3..287252f 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -484,7 +484,7 @@ function run_lint( # We are now reaching a bug HERE if isnothing(r) - @error "BUG FOUND IN StaticLint.jl, message from hint $(m) cannot be extracted" + @error "BUG FOUND IN StaticLint.jl, message from hint: $(m) cannot be extracted" return "ERROR" end diff --git a/src/linting/extended_checks.jl b/src/linting/extended_checks.jl index c7273b6..97647e4 100644 --- a/src/linting/extended_checks.jl +++ b/src/linting/extended_checks.jl @@ -212,6 +212,7 @@ struct RelPathAPIUsage_Extension <: ViolationExtendedRule end struct NonFrontShapeAPIUsage_Extension <: ViolationExtendedRule end struct InterpolationInSafeLog_Extension <: RecommendationExtendedRule end struct UseOfStaticThreads <: ViolationExtendedRule end +struct ReturnTypeInDerived <: ViolationExtendedRule end const all_extended_rule_types = Ref{Any}( @@ -574,4 +575,10 @@ function check(t::UseOfStaticThreads, x::EXPR) msg = "Use `Threads.@threads :dynamic` instead of `Threads.@threads :static`. Static threads must not be used as generated tasks will not be able to migrate across threads." generic_check(t, x, "@threads :static hole_variable_star", msg) generic_check(t, x, "Threads.@threads :static hole_variable_star", msg) +end + +function check(t::ReturnTypeInDerived, x::EXPR, markers::Dict{Symbol,String}) + msg = "Return type necessary in `@derived` functions." + generic_check(t, x, "@derived hole_variable function hole_variable(hole_variable_star) hole_variable_star end", msg) + generic_check(t, x, "@derived function hole_variable(hole_variable_star) hole_variable_star end", msg) end \ No newline at end of file diff --git a/test/rai_rules_tests.jl b/test/rai_rules_tests.jl index 6597cc1..cb990d7 100644 --- a/test/rai_rules_tests.jl +++ b/test/rai_rules_tests.jl @@ -1988,3 +1988,50 @@ end @test lint_test(source, "Line 2, column 5: Use `Threads.@threads :dynamic` instead of `Threads.@threads :static`.") @test lint_test(source, "Line 6, column 5: Use `Threads.@threads :dynamic` instead of `Threads.@threads :static`.") end + +@testset "Return type in derived functions" begin + @testset "No error" begin + source = """ + @derived v=10 function PhaseAPI.generated_defs_for_id( + rt::Runtime, + path::RelPath, + phase::PhaseNormalization, + )::PhaseResult + + return nothing + end + """ + @test !lint_has_error_test(source) + # @test lint_test(source, "Line 1, column 1: Return type necessary in `@derived` functions.") + end + @testset "With error 01" begin + source = """ + @derived v=10 function PhaseAPI.generated_defs_for_id( + rt::Runtime, + path::RelPath, + phase::PhaseNormalization, + ) + + return nothing + end + """ + @test lint_has_error_test(source) + @test lint_test(source, "Line 1, column 1: Return type necessary in `@derived` functions.") + end + + @testset "With error 02" begin + source = """ + @derived function PhaseAPI.generated_defs_for_id( + rt::Runtime, + path::RelPath, + phase::PhaseNormalization, + ) + + return nothing + end + """ + @test lint_has_error_test(source) + @test lint_test(source, "Line 1, column 1: Return type necessary in `@derived` functions.") + end +end +