Skip to content

Commit fac4515

Browse files
committed
Fixes for Julia 1.6 (#212)
This PR fixes TuringLang/Turing.jl#1525 (comment) and fixes the model definition and some warning on Julia 1.6. It also includes a line number node of the call site instead of a reference to `src/compiler.jl` in the model definition for easier debugging. On Julia 1.6, initially I got warnings about method redefinitions (models of the same name) that all referred to line 344 in `src/compiler.jl` instead of the place where the model was defined by the user. Turing tests are disabled currently since they crash (segmentation fault). Might be related to the fact that Libtask is not compatible with Julia 1.6 yet (therefore also an older version of Turing and Libtask would be used on Julia 1.6). Co-authored-by: David Widmann <[email protected]>
1 parent 873d5e9 commit fac4515

File tree

9 files changed

+92
-77
lines changed

9 files changed

+92
-77
lines changed

.github/workflows/DynamicPPL-CI.yml renamed to .github/workflows/CI.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: DynamicPPL-CI
1+
name: CI
22

33
on:
44
push:
@@ -13,13 +13,11 @@ on:
1313
jobs:
1414
test:
1515
runs-on: ${{ matrix.os }}
16-
continue-on-error: ${{ matrix.version == 'nightly' }}
1716
strategy:
1817
matrix:
1918
version:
20-
- '1.3'
21-
- '1'
22-
# - 'nightly'
19+
- '1.3' # minimum supported version
20+
- '1' # current stable version
2321
os:
2422
- ubuntu-latest
2523
- macOS-latest

.github/workflows/JuliaNightly.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: JuliaNightly
2+
3+
on:
4+
push:
5+
branches:
6+
# This is where pull requests from "bors r+" are built.
7+
- staging
8+
# This is where pull requests from "bors try" are built.
9+
- trying
10+
# Build the master branch.
11+
- master
12+
13+
jobs:
14+
test:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v2
18+
- uses: julia-actions/setup-julia@v1
19+
with:
20+
version: 'nightly'
21+
arch: x64
22+
- uses: actions/cache@v1
23+
env:
24+
cache-name: cache-artifacts
25+
with:
26+
path: ~/.julia/artifacts
27+
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
28+
restore-keys: |
29+
${{ runner.os }}-test-${{ env.cache-name }}-
30+
${{ runner.os }}-test-
31+
${{ runner.os }}-
32+
- uses: julia-actions/julia-buildpkg@latest
33+
- uses: julia-actions/julia-runtest@latest

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "DynamicPPL"
22
uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8"
3-
version = "0.10.5"
3+
version = "0.10.6"
44

55
[deps]
66
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
@@ -16,6 +16,6 @@ AbstractMCMC = "2"
1616
Bijectors = "0.5.2, 0.6, 0.7, 0.8"
1717
ChainRulesCore = "0.9.7"
1818
Distributions = "0.23.8, 0.24"
19-
MacroTools = "0.5.1"
19+
MacroTools = "0.5.6"
2020
NaturalSort = "1"
2121
julia = "1.3"

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# DynamicPPL.jl
22

3-
[![Build Status](https://travis-ci.com/TuringLang/DynamicPPL.jl.svg?branch=master)](https://travis-ci.com/TuringLang/DynamicPPL.jl)
4-
[![Build Status](https://github.com/TuringLang/DynamicPPL.jl/workflows/DynamicPPL-CI/badge.svg)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3ADynamicPPL-CI+branch%3Amaster)
3+
[![Build Status](https://github.com/TuringLang/DynamicPPL.jl/workflows/CI/badge.svg?branch=master)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3ACI+branch%3Amaster)
4+
[![Build Status](https://github.com/TuringLang/DynamicPPL.jl/workflows/JuliaNightly/badge.svg?branch=master)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3AJuliaNightly+branch%3Amaster)
5+
[![Coverage Status](https://coveralls.io/repos/github/TuringLang/DynamicPPL.jl/badge.svg?branch=master)](https://coveralls.io/github/TuringLang/DynamicPPL.jl?branch=master)
56
[![Codecov](https://codecov.io/gh/TuringLang/DynamicPPL.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/TuringLang/DynamicPPL.jl)
67
[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://colprac.sciml.ai/)
78
[![Bors enabled](https://bors.tech/images/badge_small.svg)](https://app.bors.tech/repositories/24589)

src/compiler.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,20 @@ end
6262
To generate a `Model`, call `model(xvalue)` or `model(xvalue, yvalue)`.
6363
"""
6464
macro model(expr, warn=true)
65-
esc(model(expr, warn))
65+
# include `LineNumberNode` with information about the call site in the
66+
# generated function for easier debugging and interpretation of error messages
67+
esc(model(expr, __source__, warn))
6668
end
6769

68-
function model(expr, warn)
70+
function model(expr, linenumbernode, warn)
6971
modelinfo = build_model_info(expr)
7072

7173
# Generate main body
7274
modelinfo[:body] = generate_mainbody(
7375
modelinfo[:modeldef][:body], modelinfo[:allargs_syms], warn
7476
)
7577

76-
return build_output(modelinfo)
78+
return build_output(modelinfo, linenumbernode)
7779
end
7880

7981
"""
@@ -301,11 +303,11 @@ hasmissing(T::Type{<:AbstractArray{>:Missing}}) = true
301303
hasmissing(T::Type) = false
302304

303305
"""
304-
build_output(modelinfo)
306+
build_output(modelinfo, linenumbernode)
305307
306308
Builds the output expression.
307309
"""
308-
function build_output(modelinfo)
310+
function build_output(modelinfo, linenumbernode)
309311
## Build the anonymous evaluator from the user-provided model definition.
310312

311313
# Remove the name.
@@ -340,8 +342,12 @@ function build_output(modelinfo)
340342
# We use a name for the anonymous evaluator that does not conflict with other variables.
341343
modeldef = modelinfo[:modeldef]
342344
@gensym evaluator
343-
modeldef[:body] = quote
344-
$evaluator = $(combinedef_anonymous(evaluatordef))
345+
# We use `MacroTools.@q begin ... end` instead of regular `quote ... end` to ensure
346+
# that no new `LineNumberNode`s are added apart from the reference `linenumbernode`
347+
# to the call site
348+
modeldef[:body] = MacroTools.@q begin
349+
$(linenumbernode)
350+
$evaluator = $(MacroTools.combinedef(evaluatordef))
345351
return $(DynamicPPL.Model)(
346352
$(QuoteNode(modeldef[:name])),
347353
$evaluator,

src/utils.jl

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,6 @@
22
struct NoDefault end
33
const NO_DEFAULT = NoDefault()
44

5-
# FIXME: This is copied from MacroTools and should be removed when a MacroTools release with
6-
# support for anonymous functions is available (> 0.5.5).
7-
function combinedef_anonymous(dict::Dict)
8-
rtype = get(dict, :rtype, nothing)
9-
params = get(dict, :params, [])
10-
wparams = get(dict, :whereparams, [])
11-
body = MacroTools.block(dict[:body])
12-
13-
if isempty(dict[:kwargs])
14-
arg = :($(dict[:args]...),)
15-
else
16-
arg = Expr(:tuple, Expr(:parameters, dict[:kwargs]...), dict[:args]...)
17-
end
18-
if isempty(wparams)
19-
if rtype==nothing
20-
MacroTools.@q($arg -> $body)
21-
else
22-
MacroTools.@q(($arg::$rtype) -> $body)
23-
end
24-
else
25-
if rtype === nothing
26-
MacroTools.@q(($arg where {$(wparams...)}) -> $body)
27-
else
28-
MacroTools.@q(($arg::$rtype where {$(wparams...)}) -> $body)
29-
end
30-
end
31-
end
32-
335
"""
346
@addlogprob!(ex)
357
@@ -52,6 +24,8 @@ function getargs_dottilde(expr::Expr)
5224
return MacroTools.@match expr begin
5325
(.~)(L_, R_) => (L, R)
5426
(~).(L_, R_) => (L, R)
27+
# Julia 1.6: see https://github.com/TuringLang/Turing.jl/issues/1525
28+
(L_ .~ R_) => (L, R)
5529
x_ => nothing
5630
end
5731
end

test/compiler.jl

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,30 @@ end
2020
testmodel_comp(1.0, 1.2)
2121

2222
# check if drawing from the prior works
23-
@model function testmodel0(x = missing)
23+
@model function testmodel01(x = missing)
2424
x ~ Normal()
2525
return x
2626
end
27-
f0_mm = testmodel0()
27+
f0_mm = testmodel01()
2828
@test mean(f0_mm() for _ in 1:1000) 0. atol=0.1
2929

3030
# Test #544
31-
@model function testmodel0(x = missing)
31+
@model function testmodel02(x = missing)
3232
if x === missing
3333
x = Vector{Float64}(undef, 2)
3434
end
3535
x[1] ~ Normal()
3636
x[2] ~ Normal()
3737
return x
3838
end
39-
f0_mm = testmodel0()
39+
f0_mm = testmodel02()
4040
@test all(x -> isapprox(x, 0; atol = 0.1), mean(f0_mm() for _ in 1:1000))
4141

42-
@model function testmodel01(x = missing)
42+
@model function testmodel03(x = missing)
4343
x ~ Bernoulli(0.5)
4444
return x
4545
end
46-
f01_mm = testmodel01()
46+
f01_mm = testmodel03()
4747
@test mean(f01_mm() for _ in 1:1000) 0.5 atol=0.1
4848

4949
# test if we get the correct return values
@@ -133,22 +133,22 @@ end
133133
@test_throws ArgumentError btest()
134134

135135
# Test missing input arguments
136-
@model function testmodel(x)
137-
x ~ Bernoulli(0.5)
136+
@model function testmodel_missing1(x)
137+
x ~ Bernoulli(0.5)
138138
return x
139139
end
140-
@test_throws MethodError testmodel()
140+
@test_throws MethodError testmodel_missing1()
141141

142142
# Test missing initialization for vector observation turned parameter
143-
@model function testmodel(x)
144-
x[1] ~ Bernoulli(0.5)
143+
@model function testmodel_missing2(x)
144+
x[1] ~ Bernoulli(0.5)
145145
return x
146146
end
147-
@test_throws MethodError testmodel(missing)()
147+
@test_throws MethodError testmodel_missing2(missing)()
148148

149149
# Test use of internal names
150-
@model function testmodel(x)
151-
x[1] ~  Bernoulli(0.5)
150+
@model function testmodel_missing3(x)
151+
x[1] ~ Bernoulli(0.5)
152152
global varinfo_ = _varinfo
153153
global sampler_ = _sampler
154154
global model_ = _model
@@ -157,7 +157,7 @@ end
157157
global lp = getlogp(_varinfo)
158158
return x
159159
end
160-
model = testmodel([1.0])
160+
model = testmodel_missing3([1.0])
161161
varinfo = VarInfo(model)
162162
@test getlogp(varinfo) == lp
163163
@test varinfo_ isa AbstractVarInfo
@@ -167,8 +167,8 @@ end
167167
@test rng_ isa Random.AbstractRNG
168168

169169
# disable warnings
170-
@model function testmodel(x)
171-
x[1] ~  Bernoulli(0.5)
170+
@model function testmodel_missing4(x)
171+
x[1] ~ Bernoulli(0.5)
172172
global varinfo_ = _varinfo
173173
global sampler_ = _sampler
174174
global model_ = _model
@@ -178,17 +178,17 @@ end
178178
return x
179179
end false
180180
lpold = lp
181-
model = testmodel([1.0])
181+
model = testmodel_missing4([1.0])
182182
varinfo = VarInfo(model)
183183
@test getlogp(varinfo) == lp == lpold
184184

185185
# test DPPL#61
186-
@model function testmodel(z)
186+
@model function testmodel_missing5(z)
187187
m ~ Normal()
188188
z[1:end] ~ MvNormal(fill(m, length(z)), 1.0)
189189
return m
190190
end
191-
model = testmodel(rand(10))
191+
model = testmodel_missing5(rand(10))
192192
@test all(z -> isapprox(z, 0; atol = 0.2), mean(model() for _ in 1:1000))
193193

194194
# test Turing#1464

test/runtests.jl

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,20 @@ include("test_util.jl")
4343
include(joinpath("compat", "ad.jl"))
4444
end
4545

46-
@testset "turing" begin
47-
# activate separate test environment
48-
Pkg.activate(DIRECTORY_Turing_tests)
49-
Pkg.develop(PackageSpec(path=DIRECTORY_DynamicPPL))
50-
Pkg.instantiate()
51-
52-
# make sure that the new environment is considered `using` and `import` statements
53-
# (not added automatically on Julia 1.3, see e.g. PR #209)
54-
if !(joinpath(DIRECTORY_Turing_tests, "Project.toml") in Base.load_path())
55-
pushfirst!(LOAD_PATH, DIRECTORY_Turing_tests)
46+
@static if VERSION <= v"1.5.3"
47+
@testset "turing" begin
48+
# activate separate test environment
49+
Pkg.activate(DIRECTORY_Turing_tests)
50+
Pkg.develop(PackageSpec(path=DIRECTORY_DynamicPPL))
51+
Pkg.instantiate()
52+
53+
# make sure that the new environment is considered `using` and `import` statements
54+
# (not added automatically on Julia 1.3, see e.g. PR #209)
55+
if !(joinpath(DIRECTORY_Turing_tests, "Project.toml") in Base.load_path())
56+
pushfirst!(LOAD_PATH, DIRECTORY_Turing_tests)
57+
end
58+
59+
include(joinpath("turing", "runtests.jl"))
5660
end
57-
58-
include(joinpath("turing", "runtests.jl"))
5961
end
6062
end

test/utils.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
@test getargs_dottilde(:(x ~ Normal(μ, σ))) === nothing
2323
@test getargs_dottilde(:((.~)(x, Normal(μ, σ)))) == (:x, :(Normal(μ, σ)))
2424
@test getargs_dottilde(:((~).(x, Normal(μ, σ)))) == (:x, :(Normal(μ, σ)))
25+
@test getargs_dottilde(:(x .~ Normal(μ, σ))) == (:x, :(Normal(μ, σ)))
2526
@test getargs_dottilde(:(@. x ~ Normal(μ, σ))) === nothing
2627
@test getargs_dottilde(:(@. x ~ Normal(μ, $(Expr(:$, :(sqrt(v))))))) === nothing
2728
@test getargs_dottilde(:(@~ Normal.(μ, σ))) === nothing
@@ -41,4 +42,4 @@
4142
@test getargs_tilde(:(@. x ~ Normal(μ, $(Expr(:$, :(sqrt(v))))))) === nothing
4243
@test getargs_tilde(:(@~ Normal.(μ, σ))) === nothing
4344
end
44-
end
45+
end

0 commit comments

Comments
 (0)