Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add external mutability improvements #2718

Merged
merged 102 commits into from
Aug 15, 2023
Merged
Changes from 7 commits
Commits
Show all changes
102 commits
Select commit Hold shift + click to select a range
9743293
Change member access result type to a reference
SupunS Jun 9, 2023
ece3d8f
Fix attachment 'self' access
SupunS Jun 9, 2023
ccc053e
Update interpreter member access
SupunS Jun 12, 2023
e26ff54
Update tests
SupunS Jun 13, 2023
ab854e2
Fix more tests
SupunS Jun 13, 2023
85d294a
Add member-acess expr to static reference validity checking
SupunS Jun 14, 2023
0421eb0
Add test for static attachment invalidation
SupunS Jun 14, 2023
b965147
Refactor code
SupunS Jun 14, 2023
aabca06
Add more tests
SupunS Jun 14, 2023
fc5ea48
Merge branch 'feature/entitlements' of https://github.com/onflow/cade…
SupunS Jun 15, 2023
04e7ac8
Update to match entitlements
SupunS Jun 15, 2023
f0f77d2
Add built-in entitlements
SupunS Jun 15, 2023
5845813
Auto regiter generated entitlements
SupunS Jun 16, 2023
9b9c937
Add builtin entitlements to array functions
SupunS Jun 19, 2023
5c8ea34
Re-use pre-computed results from checker
SupunS Jun 19, 2023
eca92df
Improve tests
SupunS Jun 19, 2023
498c63a
Add test for index expression resource loss
SupunS Jun 19, 2023
5dceaa6
Refactor checking access modifiers
SupunS Jun 19, 2023
b5e26fc
Pass authorization to members
SupunS Jun 19, 2023
5157711
Simplify reference creation
SupunS Jun 19, 2023
81a8c8f
Merge branch 'supun/member-access-semantics' into supun/entitlement-i…
SupunS Jun 19, 2023
dadf1c3
Simplify reference creation for index expressions
SupunS Jun 19, 2023
8b45a77
Merge branch 'supun/member-access-semantics' into supun/entitlement-i…
SupunS Jun 20, 2023
b33b86c
Pass down proper authorization for member-access on reference
SupunS Jun 20, 2023
5165954
Fix tests
SupunS Jun 20, 2023
bd13b6e
Pass proper entitlements to index expression members
SupunS Jun 20, 2023
0970761
Merge branch 'supun/entitlement-improvements' into supun/use-builtin-…
SupunS Jun 20, 2023
388d662
Add identity mapping
SupunS Jun 20, 2023
f7b554c
Merge branch 'supun/identity-mapping' into supun/use-builtin-entitlem…
SupunS Jun 20, 2023
c2699ab
Update tests
SupunS Jun 20, 2023
efce305
Fix tests
SupunS Jun 20, 2023
3e8e30e
Merge branch 'supun/identity-mapping' into supun/use-builtin-entitlem…
SupunS Jun 20, 2023
630b7ca
Merge branch 'supun/builtin-entitlements' into supun/mutability-changes
SupunS Jun 20, 2023
bbe5bb9
Merge branch 'supun/identity-mapping' into supun/mutability-changes
SupunS Jun 20, 2023
533cbb4
Return unauthorized reference for array/dictionary elements
SupunS Jun 21, 2023
bb86a41
Merge branch 'supun/entitlement-improvements' into supun/use-builtin-…
SupunS Jun 21, 2023
2508590
Merge branch 'supun/entitlement-improvements' into supun/mutability-c…
SupunS Jun 21, 2023
6eed27b
Merge branch 'supun/mutability-changes' of https://github.com/onflow/…
SupunS Jun 21, 2023
a073e17
Test redeclaring built-in entitlements
SupunS Jun 21, 2023
7a4ff32
ADd more tests for identity mapping
SupunS Jun 21, 2023
b35e6a8
Replace 'pub' with 'access(all)'
SupunS Jun 21, 2023
5d6babd
Add more tests
SupunS Jun 22, 2023
6bd53e9
Add entitlements to dictionary functions
SupunS Jun 22, 2023
03197ec
Require insertable/mutatble refrence for index assignment
SupunS Jun 22, 2023
7cf1c65
Remove external mutation checks
SupunS Jun 22, 2023
20d2125
Update tests
SupunS Jun 22, 2023
354e042
Merge branch 'supun/allow-external-mutation' into supun/entitled-assi…
SupunS Jun 22, 2023
37c0667
Merge branch 'supun/sync-mutability-restrictions' into supun/member-a…
SupunS Jun 22, 2023
ade5bba
Update test
SupunS Jun 22, 2023
fa638ae
Fix swap statement
SupunS Jun 22, 2023
10dbec2
Merge branch 'supun/member-access-semantics' into supun/entitlement-i…
SupunS Jun 22, 2023
3ff9208
Merge branch 'supun/builtin-entitlements' into supun/identity-mapping
SupunS Jun 22, 2023
efd6db1
Merge branch 'supun/identity-mapping' into supun/mutability-changes
SupunS Jun 22, 2023
1df5774
Merge branch 'supun/mutability-changes' into supun/use-builtin-entitl…
SupunS Jun 22, 2023
9c97207
Merge branch 'supun/member-access-semantics' into supun/builtin-entit…
SupunS Jun 22, 2023
a82ff3d
Merge branch 'supun/builtin-entitlements' into supun/identity-mapping
SupunS Jun 22, 2023
665397a
Merge branch 'supun/entitlement-improvements' into supun/mutability-c…
SupunS Jun 22, 2023
282b0c2
Merge branch 'supun/mutability-changes' of https://github.com/onflow/…
SupunS Jun 22, 2023
a2eead4
Adjust tests
SupunS Jun 22, 2023
ba6e193
Merge branch 'supun/use-builtin-entitlements' into supun/allow-extern…
SupunS Jun 22, 2023
c5c6f01
Merge branch 'supun/allow-external-mutation' into supun/entitled-assi…
SupunS Jun 22, 2023
351673b
Merge pull request #2600 from onflow/supun/sync-mutability-restrictions
SupunS Jun 22, 2023
651f4b5
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jun 22, 2023
8b909b3
Update tests
SupunS Jun 23, 2023
a80ac51
Lint
SupunS Jun 23, 2023
7cfcc05
Move is-container check to the type itself
SupunS Jun 23, 2023
99d7541
Merge branch 'supun/member-access-semantics' into supun/entitlement-i…
SupunS Jun 23, 2023
c16e568
Update tests
SupunS Jun 23, 2023
84e7e0f
Rename MemberInfo to MemberAccessInfo
SupunS Jul 4, 2023
b72a3b1
Update tests
SupunS Jul 4, 2023
26149a0
Fix tidy
SupunS Jul 4, 2023
fe2a7be
Return a reference with entitlements, when access through owned values
SupunS Jul 5, 2023
e47f451
Rename 'MemberAccessible' to 'ContainFieldsOrElements'
SupunS Jul 5, 2023
2a08798
Merge pull request #2573 from onflow/supun/member-access-semantics
SupunS Jul 6, 2023
0726316
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
21c47ab
Add licence header
SupunS Jul 6, 2023
3a298b0
Merge pull request #2586 from onflow/supun/builtin-entitlements
SupunS Jul 6, 2023
3d4dc10
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
77a8b23
Merge pull request #2587 from onflow/supun/entitlement-improvements
SupunS Jul 6, 2023
6e58924
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
e9508ca
Merge pull request #2588 from onflow/supun/identity-mapping
SupunS Jul 6, 2023
aaef3a3
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
750be9f
Merge pull request #2598 from onflow/supun/use-builtin-entitlements
SupunS Jul 6, 2023
73c9b97
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
8fe5295
Merge pull request #2599 from onflow/supun/allow-external-mutation
SupunS Jul 6, 2023
899a0fa
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 6, 2023
a54cad8
Return all supported entitlements for owned value's fields
SupunS Jul 6, 2023
842a9cd
Add more tests
SupunS Jul 10, 2023
e8c73bd
Merge pull request #2637 from onflow/supun/identity-mapping-improvement
SupunS Jul 18, 2023
b7d6df2
Merge branch 'feature/mutability-restrictions' of https://github.com/…
SupunS Jul 18, 2023
97ab8c0
Update tests
SupunS Jul 18, 2023
57821ec
Add more tests
SupunS Jul 18, 2023
34b30d5
Requrie mutablity entitlements for index assignment
SupunS Jul 19, 2023
ae64ba2
Conform dictionaries and arrays to EntitlementSupportingType
SupunS Aug 1, 2023
c142c39
Remove redundant nil check
SupunS Aug 1, 2023
5b47d1a
Merge pull request #2664 from onflow/supun/entitled-assigment
SupunS Aug 2, 2023
5d40cd1
Rename mutability entitlements
SupunS Aug 2, 2023
894095b
Merge pull request #2690 from onflow/supun/rename-entitlements
SupunS Aug 2, 2023
9093316
Merge branch 'feature/stable-cadence' into bastian/mutability-restric…
turbolent Aug 11, 2023
01186e8
lint: delete unused code
turbolent Aug 11, 2023
7f32297
lint
turbolent Aug 11, 2023
4acc8de
Merge pull request #2714 from onflow/bastian/mutability-restrictions
turbolent Aug 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
@@ -4979,11 +4979,22 @@ func (interpreter *Interpreter) getEntitlement(typeID common.TypeID) (*sema.Enti
}

func (interpreter *Interpreter) getEntitlementMapType(typeID common.TypeID) (*sema.EntitlementMapType, error) {
location, _, err := common.DecodeTypeID(interpreter, string(typeID))
location, qualifiedIdentifier, err := common.DecodeTypeID(interpreter, string(typeID))
if err != nil {
return nil, err
}

if location == nil {
ty := sema.BuiltinEntitlementMappings[qualifiedIdentifier]
if ty == nil {
return nil, TypeLoadingError{
TypeID: typeID,
}
}

return ty, nil
}

elaboration := interpreter.getElaboration(location)
if elaboration == nil {
return nil, TypeLoadingError{
5 changes: 5 additions & 0 deletions runtime/sema/access.go
Original file line number Diff line number Diff line change
@@ -339,6 +339,11 @@ func (e EntitlementMapAccess) entitlementImage(entitlement *EntitlementType) (ou
// defined by the map in `e`, producing a new entitlement set of the image of the
// arguments.
func (e EntitlementMapAccess) Image(inputs Access, astRange func() ast.Range) (Access, error) {

if e.Type == IdentityMappingType {
return inputs, nil
}

switch inputs := inputs.(type) {
// primitive access always passes trivially through the map
case PrimitiveAccess:
8 changes: 8 additions & 0 deletions runtime/sema/type.go
Original file line number Diff line number Diff line change
@@ -3458,6 +3458,8 @@ func init() {
addToBaseActivation(ty)
}

addToBaseActivation(IdentityMappingType)

// The AST contains empty type annotations, resolve them to Void

BaseTypeActivation.Set(
@@ -3481,6 +3483,8 @@ func addToBaseActivation(ty Type) {
)
}

var IdentityMappingType = NewEntitlementMapType(nil, nil, "Identity")

func baseTypeVariable(name string, ty Type) *Variable {
return &Variable{
Identifier: name,
@@ -3560,6 +3564,10 @@ var AllNumberTypes = append(

var BuiltinEntitlements = map[string]*EntitlementType{}

var BuiltinEntitlementMappings = map[string]*EntitlementMapType{
IdentityMappingType.QualifiedIdentifier(): IdentityMappingType,
}

const NumberTypeMinFieldName = "min"
const NumberTypeMaxFieldName = "max"

9 changes: 9 additions & 0 deletions runtime/sema/type_test.go
Original file line number Diff line number Diff line change
@@ -802,6 +802,9 @@ func TestCommonSuperType(t *testing.T) {
if _, ok := BuiltinEntitlements[name]; ok {
return nil
}
if _, ok := BuiltinEntitlementMappings[name]; ok {
return nil
}

typ := variable.Type

@@ -1900,6 +1903,9 @@ func TestTypeInclusions(t *testing.T) {
if _, ok := BuiltinEntitlements[name]; ok {
return nil
}
if _, ok := BuiltinEntitlementMappings[name]; ok {
return nil
}

t.Run(name, func(t *testing.T) {

@@ -1925,6 +1931,9 @@ func TestTypeInclusions(t *testing.T) {
if _, ok := BuiltinEntitlements[name]; ok {
return nil
}
if _, ok := BuiltinEntitlementMappings[name]; ok {
return nil
}

t.Run(name, func(t *testing.T) {

122 changes: 122 additions & 0 deletions runtime/tests/checker/entitlements_test.go
Original file line number Diff line number Diff line change
@@ -5335,3 +5335,125 @@ func TestCheckBuiltinEntitlements(t *testing.T) {
})

}

func TestCheckIdentityMapping(t *testing.T) {

t.Parallel()

t.Run("owned value", func(t *testing.T) {
t.Parallel()

_, err := ParseAndCheck(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

// OK
let resultRef1: &AnyStruct = s.foo()

// Error: Must return an unauthorized ref
let resultRef2: auth(Mutable) &AnyStruct = s.foo()
}
`)

errors := RequireCheckerErrors(t, err, 1)
typeMismatchError := &sema.TypeMismatchError{}
require.ErrorAs(t, errors[0], &typeMismatchError)

require.IsType(t, &sema.ReferenceType{}, typeMismatchError.ActualType)
actualReference := typeMismatchError.ActualType.(*sema.ReferenceType)

require.IsType(t, sema.EntitlementSetAccess{}, actualReference.Authorization)
actualAuth := actualReference.Authorization.(sema.EntitlementSetAccess)

assert.Equal(t, 0, actualAuth.Entitlements.Len())
})

t.Run("unauthorized ref", func(t *testing.T) {
t.Parallel()

_, err := ParseAndCheck(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let ref = &s as &S

// OK
let resultRef1: &AnyStruct = ref.foo()

// Error: Must return an unauthorized ref
let resultRef2: auth(Mutable) &AnyStruct = ref.foo()
}
`)

errors := RequireCheckerErrors(t, err, 1)
typeMismatchError := &sema.TypeMismatchError{}
require.ErrorAs(t, errors[0], &typeMismatchError)
})

t.Run("basic entitled ref", func(t *testing.T) {
t.Parallel()

_, err := ParseAndCheck(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let mutableRef = &s as auth(Mutable) &S
let ref1: auth(Mutable) &AnyStruct = mutableRef.foo()

let insertableRef = &s as auth(Insertable) &S
let ref2: auth(Insertable) &AnyStruct = insertableRef.foo()

let removableRef = &s as auth(Removable) &S
let ref3: auth(Removable) &AnyStruct = removableRef.foo()
}
`)

assert.NoError(t, err)
})

t.Run("entitlement set ref", func(t *testing.T) {
t.Parallel()

_, err := ParseAndCheck(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let ref1 = &s as auth(Insertable | Removable) &S
let resultRef1: auth(Insertable | Removable) &AnyStruct = ref1.foo()

let ref2 = &s as auth(Insertable, Removable) &S
let resultRef2: auth(Insertable, Removable) &AnyStruct = ref2.foo()
}
`)

assert.NoError(t, err)
})
}
108 changes: 108 additions & 0 deletions runtime/tests/interpreter/entitlements_test.go
Original file line number Diff line number Diff line change
@@ -2972,3 +2972,111 @@ func TestInterpretBuiltinEntitlements(t *testing.T) {
_, err := inter.Invoke("main")
assert.NoError(t, err)
}

func TestInterpretIdentityMapping(t *testing.T) {

t.Parallel()

t.Run("owned value", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

// OK: Must return an unauthorized ref
let resultRef1: &AnyStruct = s.foo()
}
`)

_, err := inter.Invoke("main")
assert.NoError(t, err)
})

t.Run("unauthorized ref", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let ref = &s as &S

// OK: Must return an unauthorized ref
let resultRef1: &AnyStruct = ref.foo()
}
`)

_, err := inter.Invoke("main")
assert.NoError(t, err)
})

t.Run("basic entitled ref", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let mutableRef = &s as auth(Mutable) &S
let ref1: auth(Mutable) &AnyStruct = mutableRef.foo()

let insertableRef = &s as auth(Insertable) &S
let ref2: auth(Insertable) &AnyStruct = insertableRef.foo()

let removableRef = &s as auth(Removable) &S
let ref3: auth(Removable) &AnyStruct = removableRef.foo()
}
`)

_, err := inter.Invoke("main")
assert.NoError(t, err)
})

t.Run("entitlement set ref", func(t *testing.T) {
t.Parallel()

inter := parseCheckAndInterpret(t, `
struct S {
access(Identity) fun foo(): auth(Identity) &AnyStruct {
let a: AnyStruct = "hello"
return &a as auth(Identity) &AnyStruct
}
}

fun main() {
let s = S()

let ref1 = &s as auth(Insertable | Removable) &S
let resultRef1: auth(Insertable | Removable) &AnyStruct = ref1.foo()

let ref2 = &s as auth(Insertable, Removable) &S
let resultRef2: auth(Insertable, Removable) &AnyStruct = ref2.foo()
}
`)

_, err := inter.Invoke("main")
assert.NoError(t, err)
})
}