Skip to content

Commit

Permalink
Merge branch 'feature/mutability-restrictions' of https://github.com/…
Browse files Browse the repository at this point in the history
…onflow/cadence into supun/entitlement-improvements
  • Loading branch information
SupunS committed Jul 6, 2023
2 parents 99d7541 + 3a298b0 commit 3d4dc10
Show file tree
Hide file tree
Showing 43 changed files with 523 additions and 152 deletions.
23 changes: 21 additions & 2 deletions runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4945,7 +4945,22 @@ func (interpreter *Interpreter) GetPathCapabilityFinalTarget(
}

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

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

return ty, nil
}

elaboration := interpreter.getElaboration(location)
if elaboration == nil {
return nil, TypeLoadingError{
Expand All @@ -4964,7 +4979,11 @@ func (interpreter *Interpreter) getEntitlement(typeID common.TypeID) (*sema.Enti
}

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

elaboration := interpreter.getElaboration(location)
if elaboration == nil {
return nil, TypeLoadingError{
Expand Down
8 changes: 4 additions & 4 deletions runtime/interpreter/interpreter_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func (interpreter *Interpreter) memberExpressionGetterSetter(memberExpression *a

isNestedResourceMove := interpreter.Program.Elaboration.IsNestedResourceMoveExpression(memberExpression)

memberInfo, ok := interpreter.Program.Elaboration.MemberExpressionMemberInfo(memberExpression)
memberAccessInfo, ok := interpreter.Program.Elaboration.MemberExpressionMemberAccessInfo(memberExpression)
if !ok {
panic(errors.NewUnreachableError())
}
Expand Down Expand Up @@ -222,9 +222,9 @@ func (interpreter *Interpreter) memberExpressionGetterSetter(memberExpression *a

// Return a reference, if the member is accessed via a reference.
// This is pre-computed at the checker.
if memberInfo.ReturnReference {
if memberAccessInfo.ReturnReference {
// Get a reference to the value
resultValue = interpreter.getReferenceValue(resultValue, memberInfo.ResultingType)
resultValue = interpreter.getReferenceValue(resultValue, memberAccessInfo.ResultingType)
}

return resultValue
Expand Down Expand Up @@ -281,7 +281,7 @@ func (interpreter *Interpreter) checkMemberAccess(
target Value,
locationRange LocationRange,
) {
memberInfo, _ := interpreter.Program.Elaboration.MemberExpressionMemberInfo(memberExpression)
memberInfo, _ := interpreter.Program.Elaboration.MemberExpressionMemberAccessInfo(memberExpression)
expectedType := memberInfo.AccessedType

switch expectedType := expectedType.(type) {
Expand Down
6 changes: 2 additions & 4 deletions runtime/resourcedictionary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,11 @@ func TestRuntimeResourceDictionaryValues(t *testing.T) {
transaction {
prepare(signer: AuthAccount) {
let c <- signer.load<@Test.C>(from: /storage/c)!
let c = signer.borrow<&Test.C>(from: /storage/c)!
log(c.rs["b"]?.value)
destroy c.remove("b")
c.forceInsert("b", <- Test.createR(4))
log(c.rs["b"]?.value)
signer.save(<-c, to: /storage/c)
}
}
`)
Expand Down Expand Up @@ -293,11 +292,10 @@ func TestRuntimeResourceDictionaryValues(t *testing.T) {
transaction {
prepare(signer: AuthAccount) {
let c <- signer.load<@Test.C>(from: /storage/c)!
let c = signer.borrow<&Test.C>(from: /storage/c)!
log(c.rs["b"]?.value)
destroy c.remove("b")
log(c.rs["b"]?.value)
signer.save(<-c, to: /storage/c)
}
}
`)
Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/account_capability_controller.cdc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
access(all) struct AccountCapabilityController: MemberAccessible {
access(all) struct AccountCapabilityController: ContainFields {

/// An arbitrary "tag" for the controller.
/// For example, it could be used to describe the purpose of the capability.
Expand Down
22 changes: 11 additions & 11 deletions runtime/sema/account_capability_controller.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions runtime/sema/anyresource_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ var AnyResourceType = &SimpleType{
Equatable: false,
Comparable: false,
// The actual returnability of a value is checked at run-time
Exportable: true,
Importable: false,
MemberAccessible: true,
Exportable: true,
Importable: false,
ContainFields: true,
}
4 changes: 2 additions & 2 deletions runtime/sema/anystruct_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ var AnyStructType = &SimpleType{
Comparable: false,
Exportable: true,
// The actual importability is checked at runtime
Importable: true,
MemberAccessible: true,
Importable: true,
ContainFields: true,
}

var AnyStructTypeAnnotation = NewTypeAnnotation(AnyStructType)
2 changes: 1 addition & 1 deletion runtime/sema/authaccount.cdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

access(all) struct AuthAccount: MemberAccessible {
access(all) struct AuthAccount {

/// The address of the account.
access(all) let address: Address
Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/block.cdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

access(all) struct Block: MemberAccessible {
access(all) struct Block: ContainFields {

/// The height of the block.
///
Expand Down
22 changes: 11 additions & 11 deletions runtime/sema/block.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions runtime/sema/character.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 5 additions & 5 deletions runtime/sema/check_member_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,11 @@ func (checker *Checker) getReferenceType(typ Type, substituteAuthorization bool,
}

func shouldReturnReference(parentType, memberType Type) bool {
if !isReferenceType(parentType) {
if memberType == nil || !isReferenceType(parentType) {
return false
}

return memberType.IsMemberAccessible()
return memberType.ContainFieldsOrElements()
}

func isReferenceType(typ Type) bool {
Expand All @@ -126,17 +126,17 @@ func isReferenceType(typ Type) bool {
}

func (checker *Checker) visitMember(expression *ast.MemberExpression) (accessedType Type, resultingType Type, member *Member, isOptional bool) {
memberInfo, ok := checker.Elaboration.MemberExpressionMemberInfo(expression)
memberInfo, ok := checker.Elaboration.MemberExpressionMemberAccessInfo(expression)
if ok {
return memberInfo.AccessedType, memberInfo.ResultingType, memberInfo.Member, memberInfo.IsOptional
}

returnReference := false

defer func() {
checker.Elaboration.SetMemberExpressionMemberInfo(
checker.Elaboration.SetMemberExpressionMemberAccessInfo(
expression,
MemberInfo{
MemberAccessInfo{
AccessedType: accessedType,
ResultingType: resultingType,
Member: member,
Expand Down
3 changes: 2 additions & 1 deletion runtime/sema/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1942,7 +1942,8 @@ func (checker *Checker) checkEntitlementMapAccess(
}
}
default:
if declarationType.IsMemberAccessible() {
// Also allow entitlement mappings for container-typed fields
if declarationType.ContainFieldsOrElements() {
return
}
}
Expand Down
2 changes: 1 addition & 1 deletion runtime/sema/deployedcontract.cdc
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

access(all) struct DeployedContract: MemberAccessible {
access(all) struct DeployedContract: ContainFields {
/// The address of the account where the contract is deployed at.
access(all) let address: Address

Expand Down
22 changes: 11 additions & 11 deletions runtime/sema/deployedcontract.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

70 changes: 35 additions & 35 deletions runtime/sema/elaboration.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/onflow/cadence/runtime/common"
)

type MemberInfo struct {
type MemberAccessInfo struct {
AccessedType Type
ResultingType Type
Member *Member
Expand Down Expand Up @@ -111,33 +111,33 @@ type ExpressionTypes struct {
}

type Elaboration struct {
fixedPointExpressionTypes map[*ast.FixedPointExpression]Type
interfaceTypeDeclarations map[*InterfaceType]*ast.InterfaceDeclaration
entitlementTypeDeclarations map[*EntitlementType]*ast.EntitlementDeclaration
entitlementMapTypeDeclarations map[*EntitlementMapType]*ast.EntitlementMappingDeclaration
swapStatementTypes map[*ast.SwapStatement]SwapStatementTypes
assignmentStatementTypes map[*ast.AssignmentStatement]AssignmentStatementTypes
compositeDeclarationTypes map[ast.CompositeLikeDeclaration]*CompositeType
compositeTypeDeclarations map[*CompositeType]ast.CompositeLikeDeclaration
interfaceDeclarationTypes map[*ast.InterfaceDeclaration]*InterfaceType
entitlementDeclarationTypes map[*ast.EntitlementDeclaration]*EntitlementType
entitlementMapDeclarationTypes map[*ast.EntitlementMappingDeclaration]*EntitlementMapType
transactionDeclarationTypes map[*ast.TransactionDeclaration]*TransactionType
constructorFunctionTypes map[*ast.SpecialFunctionDeclaration]*FunctionType
functionExpressionFunctionTypes map[*ast.FunctionExpression]*FunctionType
invocationExpressionTypes map[*ast.InvocationExpression]InvocationExpressionTypes
castingExpressionTypes map[*ast.CastingExpression]CastingExpressionTypes
lock *sync.RWMutex
binaryExpressionTypes map[*ast.BinaryExpression]BinaryExpressionTypes
memberExpressionMemberInfos map[*ast.MemberExpression]MemberInfo
memberExpressionExpectedTypes map[*ast.MemberExpression]Type
arrayExpressionTypes map[*ast.ArrayExpression]ArrayExpressionTypes
dictionaryExpressionTypes map[*ast.DictionaryExpression]DictionaryExpressionTypes
integerExpressionTypes map[*ast.IntegerExpression]Type
stringExpressionTypes map[*ast.StringExpression]Type
returnStatementTypes map[*ast.ReturnStatement]ReturnStatementTypes
functionDeclarationFunctionTypes map[*ast.FunctionDeclaration]*FunctionType
variableDeclarationTypes map[*ast.VariableDeclaration]VariableDeclarationTypes
fixedPointExpressionTypes map[*ast.FixedPointExpression]Type
interfaceTypeDeclarations map[*InterfaceType]*ast.InterfaceDeclaration
entitlementTypeDeclarations map[*EntitlementType]*ast.EntitlementDeclaration
entitlementMapTypeDeclarations map[*EntitlementMapType]*ast.EntitlementMappingDeclaration
swapStatementTypes map[*ast.SwapStatement]SwapStatementTypes
assignmentStatementTypes map[*ast.AssignmentStatement]AssignmentStatementTypes
compositeDeclarationTypes map[ast.CompositeLikeDeclaration]*CompositeType
compositeTypeDeclarations map[*CompositeType]ast.CompositeLikeDeclaration
interfaceDeclarationTypes map[*ast.InterfaceDeclaration]*InterfaceType
entitlementDeclarationTypes map[*ast.EntitlementDeclaration]*EntitlementType
entitlementMapDeclarationTypes map[*ast.EntitlementMappingDeclaration]*EntitlementMapType
transactionDeclarationTypes map[*ast.TransactionDeclaration]*TransactionType
constructorFunctionTypes map[*ast.SpecialFunctionDeclaration]*FunctionType
functionExpressionFunctionTypes map[*ast.FunctionExpression]*FunctionType
invocationExpressionTypes map[*ast.InvocationExpression]InvocationExpressionTypes
castingExpressionTypes map[*ast.CastingExpression]CastingExpressionTypes
lock *sync.RWMutex
binaryExpressionTypes map[*ast.BinaryExpression]BinaryExpressionTypes
memberExpressionMemberAccessInfos map[*ast.MemberExpression]MemberAccessInfo
memberExpressionExpectedTypes map[*ast.MemberExpression]Type
arrayExpressionTypes map[*ast.ArrayExpression]ArrayExpressionTypes
dictionaryExpressionTypes map[*ast.DictionaryExpression]DictionaryExpressionTypes
integerExpressionTypes map[*ast.IntegerExpression]Type
stringExpressionTypes map[*ast.StringExpression]Type
returnStatementTypes map[*ast.ReturnStatement]ReturnStatementTypes
functionDeclarationFunctionTypes map[*ast.FunctionDeclaration]*FunctionType
variableDeclarationTypes map[*ast.VariableDeclaration]VariableDeclarationTypes
// nestedResourceMoveExpressions indicates the index or member expression
// is implicitly moving a resource out of the container, e.g. in a shift or swap statement.
nestedResourceMoveExpressions map[ast.Expression]struct{}
Expand Down Expand Up @@ -638,20 +638,20 @@ func (e *Elaboration) SetIntegerExpressionType(expression *ast.IntegerExpression
e.integerExpressionTypes[expression] = actualType
}

func (e *Elaboration) MemberExpressionMemberInfo(expression *ast.MemberExpression) (memberInfo MemberInfo, ok bool) {
if e.memberExpressionMemberInfos == nil {
func (e *Elaboration) MemberExpressionMemberAccessInfo(expression *ast.MemberExpression) (memberInfo MemberAccessInfo, ok bool) {
if e.memberExpressionMemberAccessInfos == nil {
ok = false
return
}
memberInfo, ok = e.memberExpressionMemberInfos[expression]
memberInfo, ok = e.memberExpressionMemberAccessInfos[expression]
return
}

func (e *Elaboration) SetMemberExpressionMemberInfo(expression *ast.MemberExpression, memberInfo MemberInfo) {
if e.memberExpressionMemberInfos == nil {
e.memberExpressionMemberInfos = map[*ast.MemberExpression]MemberInfo{}
func (e *Elaboration) SetMemberExpressionMemberAccessInfo(expression *ast.MemberExpression, memberAccessInfo MemberAccessInfo) {
if e.memberExpressionMemberAccessInfos == nil {
e.memberExpressionMemberAccessInfos = map[*ast.MemberExpression]MemberAccessInfo{}
}
e.memberExpressionMemberInfos[expression] = memberInfo
e.memberExpressionMemberAccessInfos[expression] = memberAccessInfo
}

func (e *Elaboration) MemberExpressionExpectedType(expression *ast.MemberExpression) Type {
Expand Down
6 changes: 6 additions & 0 deletions runtime/sema/entitlements.cdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

entitlement Mutable

entitlement Insertable

entitlement Removable
Loading

0 comments on commit 3d4dc10

Please sign in to comment.