From 089768c5735ee1044514795243754274adc9caaf Mon Sep 17 00:00:00 2001 From: Daniel Sainati Date: Tue, 3 Oct 2023 11:50:36 -0400 Subject: [PATCH 1/2] before statements require pure arguments --- runtime/sema/check_function.go | 5 +- runtime/tests/checker/conditions_test.go | 81 ++++++++++++++++++++++++ runtime/tests/checker/resources_test.go | 5 +- 3 files changed, 88 insertions(+), 3 deletions(-) diff --git a/runtime/sema/check_function.go b/runtime/sema/check_function.go index 26c4ec7228..c84275e3af 100644 --- a/runtime/sema/check_function.go +++ b/runtime/sema/check_function.go @@ -344,7 +344,10 @@ func (checker *Checker) visitWithPostConditions(postConditions *ast.Conditions, checker.Elaboration.SetPostConditionsRewrite(postConditions, rewriteResult) - checker.visitStatements(rewriteResult.BeforeStatements) + // all condition blocks are `view` + checker.InNewPurityScope(true, func() { + checker.visitStatements(rewriteResult.BeforeStatements) + }) } body() diff --git a/runtime/tests/checker/conditions_test.go b/runtime/tests/checker/conditions_test.go index 8960d89fc1..b0d3b11398 100644 --- a/runtime/tests/checker/conditions_test.go +++ b/runtime/tests/checker/conditions_test.go @@ -1018,3 +1018,84 @@ func TestCheckRewrittenPostConditions(t *testing.T) { }) } + +func TestCheckBeforeConditions(t *testing.T) { + + t.Parallel() + + t.Run("function call", func(t *testing.T) { + + _, err := ParseAndCheck(t, ` + fun impure(): Int { + return 0 + } + + fun test() { + post { + before(impure()) > 0 + } + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.PurityError{}, errs[0]) + }) + + t.Run("view function call", func(t *testing.T) { + + _, err := ParseAndCheck(t, ` + view fun pure(): Int { + return 0 + } + + fun test() { + post { + before(pure()) > 0 + } + } + `) + + require.NoError(t, err) + }) + + t.Run("nested function call", func(t *testing.T) { + + _, err := ParseAndCheck(t, ` + view fun pure(): Int { + return 0 + } + + fun impure(): Int { + return 0 + } + + fun test() { + post { + before(before(impure())) > pure() + } + } + `) + + errs := RequireCheckerErrors(t, err, 1) + + assert.IsType(t, &sema.PurityError{}, errs[0]) + }) + + t.Run("nested pure function call", func(t *testing.T) { + + _, err := ParseAndCheck(t, ` + view fun pure(): Int { + return 0 + } + + fun test() { + post { + before(before(pure())) > 0 + } + } + `) + + require.NoError(t, err) + }) +} diff --git a/runtime/tests/checker/resources_test.go b/runtime/tests/checker/resources_test.go index f814147eee..db9726e67a 100644 --- a/runtime/tests/checker/resources_test.go +++ b/runtime/tests/checker/resources_test.go @@ -5673,9 +5673,10 @@ func TestCheckInvalidationInPostConditionBefore(t *testing.T) { } `) - errs := RequireCheckerErrors(t, err, 1) + errs := RequireCheckerErrors(t, err, 2) - assert.IsType(t, &sema.ResourceUseAfterInvalidationError{}, errs[0]) + assert.IsType(t, &sema.PurityError{}, errs[0]) + assert.IsType(t, &sema.ResourceUseAfterInvalidationError{}, errs[1]) } func TestCheckInvalidationInPostCondition(t *testing.T) { From bf4207b31747c8ad9a9c165ad8f7db14d2354784 Mon Sep 17 00:00:00 2001 From: Daniel Sainati Date: Tue, 3 Oct 2023 12:19:55 -0400 Subject: [PATCH 2/2] parallelize --- runtime/tests/checker/conditions_test.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/tests/checker/conditions_test.go b/runtime/tests/checker/conditions_test.go index b0d3b11398..d00d0a94ae 100644 --- a/runtime/tests/checker/conditions_test.go +++ b/runtime/tests/checker/conditions_test.go @@ -1025,6 +1025,8 @@ func TestCheckBeforeConditions(t *testing.T) { t.Run("function call", func(t *testing.T) { + t.Parallel() + _, err := ParseAndCheck(t, ` fun impure(): Int { return 0 @@ -1044,6 +1046,8 @@ func TestCheckBeforeConditions(t *testing.T) { t.Run("view function call", func(t *testing.T) { + t.Parallel() + _, err := ParseAndCheck(t, ` view fun pure(): Int { return 0 @@ -1061,6 +1065,8 @@ func TestCheckBeforeConditions(t *testing.T) { t.Run("nested function call", func(t *testing.T) { + t.Parallel() + _, err := ParseAndCheck(t, ` view fun pure(): Int { return 0 @@ -1084,6 +1090,8 @@ func TestCheckBeforeConditions(t *testing.T) { t.Run("nested pure function call", func(t *testing.T) { + t.Parallel() + _, err := ParseAndCheck(t, ` view fun pure(): Int { return 0