Skip to content

Commit

Permalink
Merge branch 'master' into bastian/update-atree-register-inlining-v1.0-7
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Jul 8, 2024
2 parents dd97a3e + 5979bf0 commit 38f634c
Show file tree
Hide file tree
Showing 16 changed files with 2,695 additions and 977 deletions.
882 changes: 445 additions & 437 deletions migrations_data/staged-contracts-report-2024-06-12T13-03-00Z-testnet.md

Large diffs are not rendered by default.

894 changes: 451 additions & 443 deletions migrations_data/staged-contracts-report-2024-06-19T12-31-00Z-testnet.md

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

137 changes: 124 additions & 13 deletions runtime/capabilities_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,20 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
entitlement X
access(all)
resource R {
resource interface RI {}
access(all)
resource R: RI {
access(all)
let foo: Int
access(X)
let bar: Int
init() {
self.foo = 42
self.bar = 21
}
}
Expand Down Expand Up @@ -128,6 +135,12 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
let noCap = self.account.capabilities.storage.issue<&R>(/storage/nonExistentTarget)
self.account.capabilities.publish(noCap, at: /public/nonExistentTarget)
let unentitledRICap = self.account.capabilities.storage.issue<&{RI}>(/storage/r)
self.account.capabilities.publish(unentitledRICap, at: /public/unentitledRI)
let entitledRICap = self.account.capabilities.storage.issue<auth(X) &{RI}>(/storage/r)
self.account.capabilities.publish(entitledRICap, at: /public/entitledRI)
}
access(all)
Expand Down Expand Up @@ -252,15 +265,51 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testSwap(): Int {
let ref = self.account.capabilities.get<&R>(/public/r).borrow()!
let ref = self.account.capabilities.get<&R>(/public/r).borrow()!
let r <- self.account.storage.load<@R>(from: /storage/r)
destroy r
let r <- self.account.storage.load<@R>(from: /storage/r)
destroy r
let r2 <- create R2()
self.account.storage.save(<-r2, to: /storage/r)
let r2 <- create R2()
self.account.storage.save(<-r2, to: /storage/r)
return ref.foo
return ref.foo
}
access(all)
fun testRI() {
// Borrow /public/unentitledRI.
// - All unentitled borrows should succeed (as &{RI} / as &R)
// - All entitled borrows should fail (as &{RI} / as &R)
let unentitledRI1 = self.account.capabilities.get<&{RI}>(/public/unentitledRI).borrow()
assert(unentitledRI1 != nil, message: "unentitledRI1 should not be nil")
let entitledRI1 = self.account.capabilities.get<auth(X) &{RI}>(/public/unentitledRI).borrow()
assert(entitledRI1 == nil, message: "entitledRI1 should be nil")
let unentitledR1 = self.account.capabilities.get<&R>(/public/unentitledRI).borrow()
assert(unentitledR1 != nil, message: "unentitledR1 should not be nil")
let entitledR1 = self.account.capabilities.get<auth(X) &R>(/public/unentitledRI).borrow()
assert(entitledR1 == nil, message: "entitledR1 should be nil")
// Borrow /public/entitledRI.
// All borrows should succeed:
// - As &{RI} / as &R
// - Unentitled / entitled
let unentitledRI2 = self.account.capabilities.get<&{RI}>(/public/entitledRI).borrow()
assert(unentitledRI2 != nil, message: "unentitledRI2 should not be nil")
let entitledRI2 = self.account.capabilities.get<auth(X) &{RI}>(/public/entitledRI).borrow()
assert(entitledRI2 != nil, message: "entitledRI2 should not be nil")
let unentitledR2 = self.account.capabilities.get<&R>(/public/entitledRI).borrow()
assert(unentitledR2 != nil, message: "unentitledR2 should not be nil")
let entitledR2 = self.account.capabilities.get<auth(X) &R>(/public/entitledRI).borrow()
assert(entitledR2 != nil, message: "entitledR2 should not be nil")
}
}
`
Expand Down Expand Up @@ -327,6 +376,12 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {

require.ErrorAs(t, err, &interpreter.DereferenceError{})
})

t.Run("testRI", func(t *testing.T) {

_, err := invoke("testRI")
require.NoError(t, err)
})
})

t.Run("struct", func(t *testing.T) {
Expand All @@ -347,13 +402,20 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
entitlement X
access(all)
struct S {
struct interface SI {}
access(all)
struct S: SI {
access(all)
let foo: Int
access(X)
let bar: Int
init() {
self.foo = 42
self.bar = 21
}
}
Expand Down Expand Up @@ -395,6 +457,12 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
let noCap = self.account.capabilities.storage.issue<&S>(/storage/nonExistentTarget)
self.account.capabilities.publish(noCap, at: /public/nonExistentTarget)
let unentitledSICap = self.account.capabilities.storage.issue<&{SI}>(/storage/s)
self.account.capabilities.publish(unentitledSICap, at: /public/unentitledSI)
let entitledSICap = self.account.capabilities.storage.issue<auth(X) &{SI}>(/storage/s)
self.account.capabilities.publish(entitledSICap, at: /public/entitledSI)
}
access(all)
Expand Down Expand Up @@ -519,14 +587,51 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {
access(all)
fun testSwap(): Int {
let ref = self.account.capabilities.get<&S>(/public/s).borrow()!
let ref = self.account.capabilities.get<&S>(/public/s).borrow()!
self.account.storage.load<S>(from: /storage/s)
let s2 = S2()
self.account.storage.save(s2, to: /storage/s)
return ref.foo
}
access(all)
fun testSI() {
self.account.storage.load<S>(from: /storage/s)
// Borrow /public/unentitledSI.
// - All unentitled borrows should succeed (as &{SI} / as &S)
// - All entitled borrows should fail (as &{SI} / as &S)
let s2 = S2()
self.account.storage.save(s2, to: /storage/s)
let unentitledSI1 = self.account.capabilities.get<&{SI}>(/public/unentitledSI).borrow()
assert(unentitledSI1 != nil, message: "unentitledSI1 should not be nil")
return ref.foo
let entitledSI1 = self.account.capabilities.get<auth(X) &{SI}>(/public/unentitledSI).borrow()
assert(entitledSI1 == nil, message: "entitledSI1 should be nil")
let unentitledS1 = self.account.capabilities.get<&S>(/public/unentitledSI).borrow()
assert(unentitledS1 != nil, message: "unentitledS1 should not be nil")
let entitledS1 = self.account.capabilities.get<auth(X) &S>(/public/unentitledSI).borrow()
assert(entitledS1 == nil, message: "entitledS1 should be nil")
// Borrow /public/entitledSI.
// All borrows should succeed:
// - As &{SI} / as &S
// - Unentitled / entitled
let unentitledSI2 = self.account.capabilities.get<&{SI}>(/public/entitledSI).borrow()
assert(unentitledSI2 != nil, message: "unentitledSI2 should not be nil")
let entitledSI2 = self.account.capabilities.get<auth(X) &{SI}>(/public/entitledSI).borrow()
assert(entitledSI2 != nil, message: "entitledSI2 should not be nil")
let unentitledS2 = self.account.capabilities.get<&S>(/public/entitledSI).borrow()
assert(unentitledS2 != nil, message: "unentitledS2 should not be nil")
let entitledS2 = self.account.capabilities.get<auth(X) &S>(/public/entitledSI).borrow()
assert(entitledS2 != nil, message: "entitledS2 should not be nil")
}
}
`
Expand Down Expand Up @@ -593,6 +698,12 @@ func TestRuntimeCapability_borrowAndCheck(t *testing.T) {

require.ErrorAs(t, err, &interpreter.DereferenceError{})
})

t.Run("testSI", func(t *testing.T) {

_, err := invoke("testSI")
require.NoError(t, err)
})
})

t.Run("account", func(t *testing.T) {
Expand Down
30 changes: 11 additions & 19 deletions runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1792,7 +1792,7 @@ func (interpreter *Interpreter) VisitEnumCaseDeclaration(_ *ast.EnumCaseDeclarat
panic(errors.NewUnreachableError())
}

func (interpreter *Interpreter) substituteMappedEntitlements(ty sema.Type) sema.Type {
func (interpreter *Interpreter) SubstituteMappedEntitlements(ty sema.Type) sema.Type {
if interpreter.SharedState.currentEntitlementMappedValue == nil {
return ty
}
Expand Down Expand Up @@ -1831,7 +1831,7 @@ func (interpreter *Interpreter) transferAndConvert(
true, // value is standalone.
)

targetType = interpreter.substituteMappedEntitlements(targetType)
targetType = interpreter.SubstituteMappedEntitlements(targetType)

result := interpreter.ConvertAndBox(
locationRange,
Expand Down Expand Up @@ -3998,39 +3998,31 @@ func (interpreter *Interpreter) IsSubType(subType StaticType, superType StaticTy
return interpreter.IsSubTypeOfSemaType(subType, semaType)
}

func (interpreter *Interpreter) IsSubTypeOfSemaType(subType StaticType, superType sema.Type) bool {
func (interpreter *Interpreter) IsSubTypeOfSemaType(staticSubType StaticType, superType sema.Type) bool {
if superType == sema.AnyType {
return true
}

switch subType := subType.(type) {
// Optimization: Implement subtyping for common cases directly,
// without converting the subtype to a sema type.

switch staticSubType := staticSubType.(type) {
case *OptionalStaticType:
if superType, ok := superType.(*sema.OptionalType); ok {
return interpreter.IsSubTypeOfSemaType(subType.Type, superType.Type)
return interpreter.IsSubTypeOfSemaType(staticSubType.Type, superType.Type)
}

switch superType {
case sema.AnyStructType, sema.AnyResourceType:
return interpreter.IsSubTypeOfSemaType(subType.Type, superType)
}

case *ReferenceStaticType:
if superType, ok := superType.(*sema.ReferenceType); ok {

// First, check that the static type of the referenced value
// is a subtype of the super type

return subType.ReferencedType != nil &&
interpreter.IsSubTypeOfSemaType(subType.ReferencedType, superType.Type) &&
superType.Authorization.PermitsAccess(interpreter.MustConvertStaticAuthorizationToSemaAccess(subType.Authorization))
return interpreter.IsSubTypeOfSemaType(staticSubType.Type, superType)
}

return superType == sema.AnyStructType
}

semaType := interpreter.MustConvertStaticToSemaType(subType)
semaSubType := interpreter.MustConvertStaticToSemaType(staticSubType)

return sema.IsSubType(semaType, superType)
return sema.IsSubType(semaSubType, superType)
}

func (interpreter *Interpreter) domainPaths(address common.Address, domain common.PathDomain) []Value {
Expand Down
4 changes: 2 additions & 2 deletions runtime/interpreter/interpreter_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -1312,7 +1312,7 @@ func (interpreter *Interpreter) VisitCastingExpression(expression *ast.CastingEx
}

castingExpressionTypes := interpreter.Program.Elaboration.CastingExpressionTypes(expression)
expectedType := interpreter.substituteMappedEntitlements(castingExpressionTypes.TargetType)
expectedType := interpreter.SubstituteMappedEntitlements(castingExpressionTypes.TargetType)

switch expression.Operation {
case ast.OperationFailableCast, ast.OperationForceCast:
Expand All @@ -1325,7 +1325,7 @@ func (interpreter *Interpreter) VisitCastingExpression(expression *ast.CastingEx
// thus this is the only place where it becomes necessary to "instantiate" the result of a map to its
// concrete outputs. In other places (e.g. interface conformance checks) we want to leave maps generic,
// so we don't substitute them.
valueSemaType := interpreter.substituteMappedEntitlements(interpreter.MustSemaTypeOfValue(value))
valueSemaType := interpreter.SubstituteMappedEntitlements(interpreter.MustSemaTypeOfValue(value))
valueStaticType := ConvertSemaToStaticType(interpreter, valueSemaType)
isSubType := interpreter.IsSubTypeOfSemaType(valueStaticType, expectedType)

Expand Down
Loading

0 comments on commit 38f634c

Please sign in to comment.