From a0ea3d541b4e3c7c4759b376ff9c1f1c6cbbf6b1 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Fri, 30 Jun 2023 10:54:38 -0500 Subject: [PATCH 1/8] Delegate Cadence composite Storable() to Atree Currently, Cadence ArrayValue, CompositeValue, and DictionaryValue creates atree.Storable directly from StorageID of its Atree values. In the future, some Atree values can be inlined so they don't have StorageID, and Atree values need to handle Storable depending on maxInlineSize and other factors. This commit delegates Cadence composite values' Storable() to its internal Atree values. So future changes to Atree values and their storables don't break Cadence. --- runtime/interpreter/value.go | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 9a95830648..38d98f4817 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -2540,8 +2540,12 @@ func (v *ArrayValue) Equal(interpreter *Interpreter, locationRange LocationRange return true } -func (v *ArrayValue) Storable(_ atree.SlabStorage, _ atree.Address, _ uint64) (atree.Storable, error) { - return atree.StorageIDStorable(v.StorageID()), nil +func (v *ArrayValue) Storable( + storage atree.SlabStorage, + address atree.Address, + maxInlineSize uint64, +) (atree.Storable, error) { + return v.array.Storable(storage, address, maxInlineSize) } func (v *ArrayValue) IsReferenceTrackedResourceKindedValue() {} @@ -16022,12 +16026,16 @@ func (v *CompositeValue) IsStorable() bool { return v.Location != nil } -func (v *CompositeValue) Storable(_ atree.SlabStorage, _ atree.Address, _ uint64) (atree.Storable, error) { +func (v *CompositeValue) Storable( + storage atree.SlabStorage, + address atree.Address, + maxInlineSize uint64, +) (atree.Storable, error) { if !v.IsStorable() { return NonStorable{Value: v}, nil } - return atree.StorageIDStorable(v.StorageID()), nil + return v.dictionary.Storable(storage, address, maxInlineSize) } func (v *CompositeValue) NeedsStoreTo(address atree.Address) bool { @@ -17533,8 +17541,12 @@ func (v *DictionaryValue) Equal(interpreter *Interpreter, locationRange Location } } -func (v *DictionaryValue) Storable(_ atree.SlabStorage, _ atree.Address, _ uint64) (atree.Storable, error) { - return atree.StorageIDStorable(v.StorageID()), nil +func (v *DictionaryValue) Storable( + storage atree.SlabStorage, + address atree.Address, + maxInlineSize uint64, +) (atree.Storable, error) { + return v.dictionary.Storable(storage, address, maxInlineSize) } func (v *DictionaryValue) IsReferenceTrackedResourceKindedValue() {} From 675137783e31435668c4fba0742be7c47a380f02 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Fri, 30 Jun 2023 11:40:12 -0500 Subject: [PATCH 2/8] Delegate storage address to Atree Currently, storage address is derived from StorageID(). In the future, some Atree values can be inlined so they don't have StorageID and address needs be derived differently. This commit delegates storage address to its internal Atree values, by calling Address(). --- runtime/interpreter/value.go | 44 ++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 9a95830648..59d06dc0ae 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -2583,11 +2583,10 @@ func (v *ArrayValue) Transfer( } currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address array := v.array - needsStoreTo := address != currentAddress + needsStoreTo := v.NeedsStoreTo(address) isResourceKinded := v.IsResourceKinded(interpreter) if needsStoreTo || !isResourceKinded { @@ -2694,7 +2693,7 @@ func (v *ArrayValue) Clone(interpreter *Interpreter) Value { array, err := atree.NewArrayFromBatchData( config.Storage, - v.StorageID().Address, + v.StorageAddress(), v.array.Type(), func() (atree.Value, error) { value, err := iterator.Next() @@ -2760,8 +2759,12 @@ func (v *ArrayValue) StorageID() atree.StorageID { return v.array.StorageID() } +func (v *ArrayValue) StorageAddress() atree.Address { + return v.array.Address() +} + func (v *ArrayValue) GetOwner() common.Address { - return common.Address(v.StorageID().Address) + return common.Address(v.StorageAddress()) } func (v *ArrayValue) SemaType(interpreter *Interpreter) sema.ArrayType { @@ -2773,7 +2776,7 @@ func (v *ArrayValue) SemaType(interpreter *Interpreter) sema.ArrayType { } func (v *ArrayValue) NeedsStoreTo(address atree.Address) bool { - return address != v.StorageID().Address + return address != v.StorageAddress() } func (v *ArrayValue) IsResourceKinded(interpreter *Interpreter) bool { @@ -15583,7 +15586,7 @@ func (v *CompositeValue) InitializeFunctions(interpreter *Interpreter) { } func (v *CompositeValue) OwnerValue(interpreter *Interpreter, locationRange LocationRange) OptionalValue { - address := v.StorageID().Address + address := v.StorageAddress() if address == (atree.Address{}) { return NilOptionalValue @@ -15695,7 +15698,7 @@ func (v *CompositeValue) SetMember( }() } - address := v.StorageID().Address + address := v.StorageAddress() value = value.Transfer( interpreter, @@ -16031,7 +16034,7 @@ func (v *CompositeValue) Storable(_ atree.SlabStorage, _ atree.Address, _ uint64 } func (v *CompositeValue) NeedsStoreTo(address atree.Address) bool { - return address != v.StorageID().Address + return address != v.StorageAddress() } func (v *CompositeValue) IsResourceKinded(interpreter *Interpreter) bool { @@ -16083,11 +16086,11 @@ func (v *CompositeValue) Transfer( } currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address + currentAddress := v.StorageAddress() dictionary := v.dictionary - needsStoreTo := address != currentAddress + needsStoreTo := v.NeedsStoreTo(address) isResourceKinded := v.IsResourceKinded(interpreter) if needsStoreTo && v.Kind == common.CompositeKindContract { @@ -16250,7 +16253,7 @@ func (v *CompositeValue) Clone(interpreter *Interpreter) Value { dictionary, err := atree.NewMapFromBatchData( config.Storage, - v.StorageID().Address, + v.StorageAddress(), atree.NewDefaultDigesterBuilder(), v.dictionary.Type(), StringAtreeValueComparator, @@ -16337,7 +16340,7 @@ func (v *CompositeValue) DeepRemove(interpreter *Interpreter) { } func (v *CompositeValue) GetOwner() common.Address { - return common.Address(v.StorageID().Address) + return common.Address(v.StorageAddress()) } // ForEachField iterates over all field-name field-value pairs of the composite value. @@ -16360,6 +16363,10 @@ func (v *CompositeValue) StorageID() atree.StorageID { return v.dictionary.StorageID() } +func (v *CompositeValue) StorageAddress() atree.Address { + return v.dictionary.Address() +} + func (v *CompositeValue) RemoveField( interpreter *Interpreter, _ LocationRange, @@ -17579,11 +17586,10 @@ func (v *DictionaryValue) Transfer( } currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address dictionary := v.dictionary - needsStoreTo := address != currentAddress + needsStoreTo := v.NeedsStoreTo(address) isResourceKinded := v.IsResourceKinded(interpreter) if needsStoreTo || !isResourceKinded { @@ -17705,7 +17711,7 @@ func (v *DictionaryValue) Clone(interpreter *Interpreter) Value { dictionary, err := atree.NewMapFromBatchData( config.Storage, - v.StorageID().Address, + v.StorageAddress(), atree.NewDefaultDigesterBuilder(), v.dictionary.Type(), valueComparator, @@ -17783,13 +17789,17 @@ func (v *DictionaryValue) DeepRemove(interpreter *Interpreter) { } func (v *DictionaryValue) GetOwner() common.Address { - return common.Address(v.StorageID().Address) + return common.Address(v.StorageAddress()) } func (v *DictionaryValue) StorageID() atree.StorageID { return v.dictionary.StorageID() } +func (v *DictionaryValue) StorageAddress() atree.Address { + return v.dictionary.Address() +} + func (v *DictionaryValue) SemaType(interpreter *Interpreter) *sema.DictionaryType { if v.semaType == nil { // this function will panic already if this conversion fails @@ -17799,7 +17809,7 @@ func (v *DictionaryValue) SemaType(interpreter *Interpreter) *sema.DictionaryTyp } func (v *DictionaryValue) NeedsStoreTo(address atree.Address) bool { - return address != v.StorageID().Address + return address != v.StorageAddress() } func (v *DictionaryValue) IsResourceKinded(interpreter *Interpreter) bool { From 2425f7c504f09476c4b2ffa47cd5e66492f3e70d Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Fri, 30 Jun 2023 12:36:29 -0500 Subject: [PATCH 3/8] Fix data race in type tests --- runtime/sema/type.go | 18 ++++++++++++++++++ runtime/sema/type_test.go | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/runtime/sema/type.go b/runtime/sema/type.go index 2e158dfb56..54a4eaa286 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -3794,6 +3794,15 @@ func (t *CompositeType) ID() TypeID { return t.cachedIdentifiers.TypeID } +// clearCachedIdentifiers clears cachedIdentifiers. +// This function currently is only used in tests. +func (t *CompositeType) clearCachedIdentifiers() { + t.cachedIdentifiersLock.Lock() + defer t.cachedIdentifiersLock.Unlock() + + t.cachedIdentifiers = nil +} + func (t *CompositeType) initializeIdentifiers() { t.cachedIdentifiersLock.Lock() defer t.cachedIdentifiersLock.Unlock() @@ -4382,6 +4391,15 @@ func (t *InterfaceType) checkIdentifiersCached() { } } +// clearCachedIdentifiers clears cachedIdentifiers. +// This function currently is only used in tests. +func (t *InterfaceType) clearCachedIdentifiers() { + t.cachedIdentifiersLock.Lock() + defer t.cachedIdentifiersLock.Unlock() + + t.cachedIdentifiers = nil +} + func (t *InterfaceType) GetCompositeKind() common.CompositeKind { return t.CompositeKind } diff --git a/runtime/sema/type_test.go b/runtime/sema/type_test.go index 0e27d87bba..666fc98171 100644 --- a/runtime/sema/type_test.go +++ b/runtime/sema/type_test.go @@ -690,7 +690,7 @@ func TestIdentifierCacheUpdate(t *testing.T) { cachedID := semaType.ID() // clear cached identifiers for one level - semaType.cachedIdentifiers = nil + semaType.clearCachedIdentifiers() recalculatedQualifiedID := semaType.QualifiedIdentifier() recalculatedID := semaType.ID() @@ -706,7 +706,7 @@ func TestIdentifierCacheUpdate(t *testing.T) { cachedID := semaType.ID() // clear cached identifiers for one level - semaType.cachedIdentifiers = nil + semaType.clearCachedIdentifiers() recalculatedQualifiedID := semaType.QualifiedIdentifier() recalculatedID := semaType.ID() From ad588404e7480000f8452be2ac2989919c6e69c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 30 Jun 2023 16:34:53 -0700 Subject: [PATCH 4/8] only check program's types --- runtime/sema/type_test.go | 47 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/runtime/sema/type_test.go b/runtime/sema/type_test.go index 666fc98171..3233d9c323 100644 --- a/runtime/sema/type_test.go +++ b/runtime/sema/type_test.go @@ -631,23 +631,23 @@ func TestIdentifierCacheUpdate(t *testing.T) { t.Parallel() code := ` - pub contract interface Test { + contract interface Test { - pub struct interface NestedInterface { - pub fun test(): Bool - } - - pub struct Nested: NestedInterface {} + struct interface NestedInterface { + pub fun test(): Bool } - pub contract TestImpl { + struct Nested: NestedInterface {} + } - pub struct Nested { - pub fun test(): Bool { - return true - } + contract TestImpl { + + struct Nested { + fun test(): Bool { + return true } } + } ` program, err := parser.ParseProgram(nil, []byte(code), parser.Config{}) @@ -658,7 +658,7 @@ func TestIdentifierCacheUpdate(t *testing.T) { common.StringLocation("test"), nil, &Config{ - AccessCheckMode: AccessCheckModeStrict, + AccessCheckMode: AccessCheckModeNotSpecifiedUnrestricted, }, ) require.NoError(t, err) @@ -666,8 +666,10 @@ func TestIdentifierCacheUpdate(t *testing.T) { err = checker.Check() require.NoError(t, err) + var typeIDs []common.TypeID + checker.typeActivations.ForEachVariableDeclaredInAndBelow( - 0, + checker.valueActivations.Depth(), func(_ string, value *Variable) { typ := value.Type @@ -698,6 +700,8 @@ func TestIdentifierCacheUpdate(t *testing.T) { assert.Equal(t, recalculatedQualifiedID, cachedQualifiedID) assert.Equal(t, recalculatedID, cachedID) + typeIDs = append(typeIDs, recalculatedID) + // Recursively check for nested types checkNestedTypes(semaType.NestedTypes) @@ -714,13 +718,28 @@ func TestIdentifierCacheUpdate(t *testing.T) { assert.Equal(t, recalculatedQualifiedID, cachedQualifiedID) assert.Equal(t, recalculatedID, cachedID) + typeIDs = append(typeIDs, recalculatedID) + // Recursively check for nested types checkNestedTypes(semaType.NestedTypes) } } checkIdentifiers(t, typ) - }) + }, + ) + + assert.Equal(t, + []common.TypeID{ + "S.test.Test", + "S.test.Test.NestedInterface", + "S.test.Test.Nested", + "S.test.TestImpl", + "S.test.TestImpl.Nested", + }, + typeIDs, + ) + } func TestCommonSuperType(t *testing.T) { From d6c7dfbc9a3d411a687e1ea1a7fd3390739234d8 Mon Sep 17 00:00:00 2001 From: Faye Amacker <33205765+fxamacker@users.noreply.github.com> Date: Mon, 3 Jul 2023 17:41:25 -0500 Subject: [PATCH 5/8] Track resources with atree.ID instead of StorageID Currently, Array.StorageID() and OrderedMap.StorageID() are used as identifier to track resources, etc because storage IDs are guaranteed to unique. However, atree storage ID should be only used to retrieve slabs (registers) from storage. Also, when Atree register inlining is implemented in the future, some resources may not be stored in separate slabs, so they will not have storage IDs anymore. This commit uses Array.ID() and OrderedMap.ID() to uniquely identify resources. --- go.mod | 2 +- go.sum | 4 +- runtime/interpreter/interpreter.go | 38 ++++---- runtime/interpreter/interpreter_expression.go | 6 +- runtime/interpreter/sharedstate.go | 10 +- runtime/interpreter/value.go | 97 +++++++++++-------- 6 files changed, 84 insertions(+), 73 deletions(-) diff --git a/go.mod b/go.mod index 871f5a0563..b17a06a98c 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/fxamacker/cbor/v2 v2.4.1-0.20230228173756-c0c9f774e40c github.com/go-test/deep v1.1.0 github.com/leanovate/gopter v0.2.9 - github.com/onflow/atree v0.6.1-0.20230629205511-5b7b45a566a9 + github.com/onflow/atree v0.6.1-0.20230629202201-116c95986e54 github.com/rivo/uniseg v0.4.4 github.com/schollz/progressbar/v3 v3.13.1 github.com/stretchr/testify v1.8.4 diff --git a/go.sum b/go.sum index 84e854a294..c126efb53f 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,8 @@ github.com/mattn/go-tty v0.0.4/go.mod h1:u5GGXBtZU6RQoKV8gY5W6UhMudbR5vXnUe7j3px github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/onflow/atree v0.6.1-0.20230629205511-5b7b45a566a9 h1:mffWKRKGrBq5NhCWplOox33eW+gf2lcgjvdI8aeCjGk= -github.com/onflow/atree v0.6.1-0.20230629205511-5b7b45a566a9/go.mod h1:7YNAyCd5JENq+NzH+fR1ABUZVzbSq9dkt0+5fZH3L2A= +github.com/onflow/atree v0.6.1-0.20230629202201-116c95986e54 h1:sYpk0UK7vHH907N3c/OIjrUq2PKtU7CcTi2O9YvKIYs= +github.com/onflow/atree v0.6.1-0.20230629202201-116c95986e54/go.mod h1:7YNAyCd5JENq+NzH+fR1ABUZVzbSq9dkt0+5fZH3L2A= github.com/pkg/term v1.2.0-beta.2 h1:L3y/h2jkuBVFdWiJvNfYfKmzcCnILw7mJWm2JQuMppw= github.com/pkg/term v1.2.0-beta.2/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 3791f68676..d463ef1c5f 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -239,7 +239,7 @@ type Storage interface { CheckHealth() error } -type ReferencedResourceKindedValues map[atree.StorageID]map[ReferenceTrackedResourceKindedValue]struct{} +type ReferencedResourceKindedValues map[atree.ID]map[ReferenceTrackedResourceKindedValue]struct{} type Interpreter struct { Location common.Location @@ -5100,12 +5100,12 @@ func (interpreter *Interpreter) ValidateAtreeValue(value atree.Value) { func (interpreter *Interpreter) maybeTrackReferencedResourceKindedValue(value Value) { if value, ok := value.(ReferenceTrackedResourceKindedValue); ok { - interpreter.trackReferencedResourceKindedValue(value.StorageID(), value) + interpreter.trackReferencedResourceKindedValue(value.ID(), value) } } func (interpreter *Interpreter) trackReferencedResourceKindedValue( - id atree.StorageID, + id atree.ID, value ReferenceTrackedResourceKindedValue, ) { values := interpreter.SharedState.referencedResourceKindedValues[id] @@ -5117,20 +5117,20 @@ func (interpreter *Interpreter) trackReferencedResourceKindedValue( } func (interpreter *Interpreter) updateReferencedResource( - currentStorageID atree.StorageID, - newStorageID atree.StorageID, + currentID atree.ID, + newID atree.ID, updateFunc func(value ReferenceTrackedResourceKindedValue), ) { - values := interpreter.SharedState.referencedResourceKindedValues[currentStorageID] + values := interpreter.SharedState.referencedResourceKindedValues[currentID] if values == nil { return } for value := range values { //nolint:maprange updateFunc(value) } - if newStorageID != currentStorageID { - interpreter.SharedState.referencedResourceKindedValues[newStorageID] = values - interpreter.SharedState.referencedResourceKindedValues[currentStorageID] = nil + if newID != currentID { + interpreter.SharedState.referencedResourceKindedValues[newID] = values + interpreter.SharedState.referencedResourceKindedValues[currentID] = nil } } @@ -5377,8 +5377,8 @@ func (interpreter *Interpreter) idCapabilityCheckFunction( ) } -func (interpreter *Interpreter) validateMutation(storageID atree.StorageID, locationRange LocationRange) { - _, present := interpreter.SharedState.containerValueIteration[storageID] +func (interpreter *Interpreter) validateMutation(id atree.ID, locationRange LocationRange) { + _, present := interpreter.SharedState.containerValueIteration[id] if !present { return } @@ -5387,32 +5387,32 @@ func (interpreter *Interpreter) validateMutation(storageID atree.StorageID, loca }) } -func (interpreter *Interpreter) withMutationPrevention(storageID atree.StorageID, f func()) { - oldIteration, present := interpreter.SharedState.containerValueIteration[storageID] - interpreter.SharedState.containerValueIteration[storageID] = struct{}{} +func (interpreter *Interpreter) withMutationPrevention(id atree.ID, f func()) { + oldIteration, present := interpreter.SharedState.containerValueIteration[id] + interpreter.SharedState.containerValueIteration[id] = struct{}{} f() if !present { - delete(interpreter.SharedState.containerValueIteration, storageID) + delete(interpreter.SharedState.containerValueIteration, id) } else { - interpreter.SharedState.containerValueIteration[storageID] = oldIteration + interpreter.SharedState.containerValueIteration[id] = oldIteration } } func (interpreter *Interpreter) withResourceDestruction( - storageID atree.StorageID, + id atree.ID, locationRange LocationRange, f func(), ) { - _, exists := interpreter.SharedState.destroyedResources[storageID] + _, exists := interpreter.SharedState.destroyedResources[id] if exists { panic(DestroyedResourceError{ LocationRange: locationRange, }) } - interpreter.SharedState.destroyedResources[storageID] = struct{}{} + interpreter.SharedState.destroyedResources[id] = struct{}{} f() } diff --git a/runtime/interpreter/interpreter_expression.go b/runtime/interpreter/interpreter_expression.go index fc49fd6ed3..60fff757a6 100644 --- a/runtime/interpreter/interpreter_expression.go +++ b/runtime/interpreter/interpreter_expression.go @@ -937,7 +937,7 @@ func (interpreter *Interpreter) visitInvocationExpressionWithImplicitArgument(in if boundFunction, ok := function.(BoundFunctionValue); ok && boundFunction.Self != nil { self := *boundFunction.Self if resource, ok := self.(ReferenceTrackedResourceKindedValue); ok { - storageID := resource.StorageID() + storageID := resource.ID() interpreter.trackReferencedResourceKindedValue(storageID, resource) } } @@ -1290,7 +1290,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta base, interpreter.MustSemaTypeOfValue(base).(*sema.CompositeType), ) - interpreter.trackReferencedResourceKindedValue(base.StorageID(), base) + interpreter.trackReferencedResourceKindedValue(base.ID(), base) attachment, ok := interpreter.visitInvocationExpressionWithImplicitArgument( attachExpression.Attachment, @@ -1302,7 +1302,7 @@ func (interpreter *Interpreter) VisitAttachExpression(attachExpression *ast.Atta } // Because `self` in attachments is a reference, we need to track the attachment if it's a resource - interpreter.trackReferencedResourceKindedValue(attachment.StorageID(), attachment) + interpreter.trackReferencedResourceKindedValue(attachment.ID(), attachment) base = base.Transfer( interpreter, diff --git a/runtime/interpreter/sharedstate.go b/runtime/interpreter/sharedstate.go index f250ce3f58..02800016cd 100644 --- a/runtime/interpreter/sharedstate.go +++ b/runtime/interpreter/sharedstate.go @@ -43,8 +43,8 @@ type SharedState struct { storageMutatedDuringIteration bool CapabilityControllerIterations map[AddressPath]int MutationDuringCapabilityControllerIteration bool - containerValueIteration map[atree.StorageID]struct{} - destroyedResources map[atree.StorageID]struct{} + containerValueIteration map[atree.ID]struct{} + destroyedResources map[atree.ID]struct{} } func NewSharedState(config *Config) *SharedState { @@ -59,11 +59,11 @@ func NewSharedState(config *Config) *SharedState { }, inStorageIteration: false, storageMutatedDuringIteration: false, - referencedResourceKindedValues: map[atree.StorageID]map[ReferenceTrackedResourceKindedValue]struct{}{}, + referencedResourceKindedValues: map[atree.ID]map[ReferenceTrackedResourceKindedValue]struct{}{}, resourceVariables: map[ResourceKindedValue]*Variable{}, CapabilityControllerIterations: map[AddressPath]int{}, - containerValueIteration: map[atree.StorageID]struct{}{}, - destroyedResources: map[atree.StorageID]struct{}{}, + containerValueIteration: map[atree.ID]struct{}{}, + destroyedResources: map[atree.ID]struct{}{}, } } diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index fd85c90010..b999991039 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -217,7 +217,7 @@ func maybeDestroy(interpreter *Interpreter, locationRange LocationRange, value V type ReferenceTrackedResourceKindedValue interface { ResourceKindedValue IsReferenceTrackedResourceKindedValue() - StorageID() atree.StorageID + ID() atree.ID } // ContractValue is the value of a contract. @@ -1717,7 +1717,7 @@ func (v *ArrayValue) Iterate(interpreter *Interpreter, f func(element Value) (re } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.StorageID(), iterate) + interpreter.withMutationPrevention(v.ID(), iterate) } else { iterate() } @@ -1784,10 +1784,10 @@ func (v *ArrayValue) Destroy(interpreter *Interpreter, locationRange LocationRan }() } - storageID := v.StorageID() + id := v.ID() interpreter.withResourceDestruction( - storageID, + id, locationRange, func() { v.Walk(interpreter, func(element Value) { @@ -1803,8 +1803,8 @@ func (v *ArrayValue) Destroy(interpreter *Interpreter, locationRange LocationRan } interpreter.updateReferencedResource( - storageID, - storageID, + id, + id, func(value ReferenceTrackedResourceKindedValue) { arrayValue, ok := value.(*ArrayValue) if !ok { @@ -1948,7 +1948,7 @@ func (v *ArrayValue) SetKey(interpreter *Interpreter, locationRange LocationRang func (v *ArrayValue) Set(interpreter *Interpreter, locationRange LocationRange, index int, element Value) { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Set function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2022,7 +2022,7 @@ func (v *ArrayValue) MeteredString(memoryGauge common.MemoryGauge, seenReference func (v *ArrayValue) Append(interpreter *Interpreter, locationRange LocationRange, element Value) { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) // length increases by 1 dataSlabs, metaDataSlabs := common.AdditionalAtreeMemoryUsage( @@ -2070,7 +2070,7 @@ func (v *ArrayValue) InsertKey(interpreter *Interpreter, locationRange LocationR func (v *ArrayValue) Insert(interpreter *Interpreter, locationRange LocationRange, index int, element Value) { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Insert function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2125,7 +2125,7 @@ func (v *ArrayValue) RemoveKey(interpreter *Interpreter, locationRange LocationR func (v *ArrayValue) Remove(interpreter *Interpreter, locationRange LocationRange, index int) Value { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) // We only need to check the lower bound before converting from `int` (signed) to `uint64` (unsigned). // atree's Array.Remove function will check the upper bound and report an atree.IndexOutOfBoundsError @@ -2582,12 +2582,11 @@ func (v *ArrayValue) Transfer( }() } - currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address + currentID := v.ID() array := v.array - needsStoreTo := address != currentAddress + needsStoreTo := v.NeedsStoreTo(address) isResourceKinded := v.IsResourceKinded(interpreter) if needsStoreTo || !isResourceKinded { @@ -2652,11 +2651,11 @@ func (v *ArrayValue) Transfer( res = v } - newStorageID := array.StorageID() + newID := array.ID() interpreter.updateReferencedResource( - currentStorageID, - newStorageID, + currentID, + newID, func(value ReferenceTrackedResourceKindedValue) { arrayValue, ok := value.(*ArrayValue) if !ok { @@ -2760,6 +2759,10 @@ func (v *ArrayValue) StorageID() atree.StorageID { return v.array.StorageID() } +func (v *ArrayValue) ID() atree.ID { + return v.array.ID() +} + func (v *ArrayValue) GetOwner() common.Address { return common.Address(v.StorageID().Address) } @@ -15373,10 +15376,10 @@ func (v *CompositeValue) Destroy(interpreter *Interpreter, locationRange Locatio }() } - storageID := v.StorageID() + id := v.ID() interpreter.withResourceDestruction( - storageID, + id, locationRange, func() { // if this type has attachments, destroy all of them before invoking the destructor @@ -15428,8 +15431,8 @@ func (v *CompositeValue) Destroy(interpreter *Interpreter, locationRange Locatio } interpreter.updateReferencedResource( - storageID, - storageID, + id, + id, func(value ReferenceTrackedResourceKindedValue) { compositeValue, ok := value.(*CompositeValue) if !ok { @@ -16082,12 +16085,12 @@ func (v *CompositeValue) Transfer( }() } - currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address + currentID := v.ID() + currentAddress := v.StorageID().Address dictionary := v.dictionary - needsStoreTo := address != currentAddress + needsStoreTo := v.NeedsStoreTo(address) isResourceKinded := v.IsResourceKinded(interpreter) if needsStoreTo && v.Kind == common.CompositeKindContract { @@ -16175,11 +16178,11 @@ func (v *CompositeValue) Transfer( res = v } - newStorageID := dictionary.StorageID() + newID := dictionary.ID() interpreter.updateReferencedResource( - currentStorageID, - newStorageID, + currentID, + newID, func(value ReferenceTrackedResourceKindedValue) { compositeValue, ok := value.(*CompositeValue) if !ok { @@ -16360,6 +16363,10 @@ func (v *CompositeValue) StorageID() atree.StorageID { return v.dictionary.StorageID() } +func (v *CompositeValue) ID() atree.ID { + return v.dictionary.ID() +} + func (v *CompositeValue) RemoveField( interpreter *Interpreter, _ LocationRange, @@ -16447,7 +16454,7 @@ func (v *CompositeValue) setBaseValue(interpreter *Interpreter, base *CompositeV // the base reference can only be borrowed with the declared type of the attachment's base v.base = NewEphemeralReferenceValue(interpreter, false, base, baseType) - interpreter.trackReferencedResourceKindedValue(base.StorageID(), base) + interpreter.trackReferencedResourceKindedValue(base.ID(), base) } func attachmentMemberName(ty sema.Type) string { @@ -16477,7 +16484,7 @@ func attachmentBaseAndSelfValues( base = v.getBaseValue(interpreter, locationRange) // in attachment functions, self is a reference value self = NewEphemeralReferenceValue(interpreter, false, v, interpreter.MustSemaTypeOfValue(v)) - interpreter.trackReferencedResourceKindedValue(v.StorageID(), v) + interpreter.trackReferencedResourceKindedValue(v.ID(), v) return } @@ -16528,7 +16535,7 @@ func (v *CompositeValue) GetTypeKey( attachment.setBaseValue(interpreter, v) attachmentRef := NewEphemeralReferenceValue(interpreter, false, attachment, ty) - interpreter.trackReferencedResourceKindedValue(attachment.StorageID(), attachment) + interpreter.trackReferencedResourceKindedValue(attachment.ID(), attachment) return NewSomeValueNonCopying(interpreter, attachmentRef) } @@ -16737,7 +16744,7 @@ func (v *DictionaryValue) Iterate(interpreter *Interpreter, f func(key, value Va } } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.StorageID(), iterate) + interpreter.withMutationPrevention(v.ID(), iterate) } else { iterate() } @@ -16835,10 +16842,10 @@ func (v *DictionaryValue) Destroy(interpreter *Interpreter, locationRange Locati }() } - storageID := v.StorageID() + id := v.ID() interpreter.withResourceDestruction( - storageID, + id, locationRange, func() { v.Iterate(interpreter, func(key, value Value) (resume bool) { @@ -16858,8 +16865,8 @@ func (v *DictionaryValue) Destroy(interpreter *Interpreter, locationRange Locati } interpreter.updateReferencedResource( - storageID, - storageID, + id, + id, func(value ReferenceTrackedResourceKindedValue) { dictionaryValue, ok := value.(*DictionaryValue) if !ok { @@ -16914,7 +16921,7 @@ func (v *DictionaryValue) ForEachKey( } if v.IsResourceKinded(interpreter) { - interpreter.withMutationPrevention(v.StorageID(), iterate) + interpreter.withMutationPrevention(v.ID(), iterate) } else { iterate() } @@ -16986,7 +16993,7 @@ func (v *DictionaryValue) SetKey( keyValue Value, value Value, ) { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) config := interpreter.SharedState.Config @@ -17270,7 +17277,7 @@ func (v *DictionaryValue) Remove( keyValue Value, ) OptionalValue { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) valueComparator := newValueComparator(interpreter, locationRange) hashInputProvider := newHashInputProvider(interpreter, locationRange) @@ -17327,7 +17334,7 @@ func (v *DictionaryValue) Insert( keyValue, value Value, ) OptionalValue { - interpreter.validateMutation(v.StorageID(), locationRange) + interpreter.validateMutation(v.ID(), locationRange) // length increases by 1 dataSlabs, metaDataSlabs := common.AdditionalAtreeMemoryUsage(v.dictionary.Count(), v.elementSize, false) @@ -17576,8 +17583,8 @@ func (v *DictionaryValue) Transfer( }() } - currentStorageID := v.StorageID() - currentAddress := currentStorageID.Address + currentID := v.ID() + currentAddress := v.StorageID().Address dictionary := v.dictionary @@ -17661,11 +17668,11 @@ func (v *DictionaryValue) Transfer( res = v } - newStorageID := dictionary.StorageID() + newID := dictionary.ID() interpreter.updateReferencedResource( - currentStorageID, - newStorageID, + currentID, + newID, func(value ReferenceTrackedResourceKindedValue) { dictionaryValue, ok := value.(*DictionaryValue) if !ok { @@ -17788,6 +17795,10 @@ func (v *DictionaryValue) StorageID() atree.StorageID { return v.dictionary.StorageID() } +func (v *DictionaryValue) ID() atree.ID { + return v.dictionary.ID() +} + func (v *DictionaryValue) SemaType(interpreter *Interpreter) *sema.DictionaryType { if v.semaType == nil { // this function will panic already if this conversion fails From 4c29e00d7d89b4ceb9ec6a19c052ee862060b82a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 4 Jul 2023 11:01:11 -0700 Subject: [PATCH 6/8] add mailmap --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .mailmap diff --git a/.mailmap b/.mailmap new file mode 100644 index 0000000000..e1e9f669d4 --- /dev/null +++ b/.mailmap @@ -0,0 +1,2 @@ +Bastian Müller +Bastian Müller From 233b1d8abdaa2339c15f7e82784bb151205c275c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 5 Jul 2023 09:45:23 -0700 Subject: [PATCH 7/8] fix races in tests --- runtime/ast/access.go | 10 +- runtime/common/concat.go | 36 ++ runtime/interpreter/value.go | 24 +- runtime/literal_test.go | 10 +- runtime/sema/type.go | 354 +++++++++--------- .../tests/checker/builtinfunctions_test.go | 9 +- runtime/tests/checker/events_test.go | 4 +- runtime/tests/checker/integer_test.go | 9 +- runtime/tests/checker/operations_test.go | 12 +- runtime/tests/interpreter/arithmetic_test.go | 13 +- 10 files changed, 265 insertions(+), 216 deletions(-) create mode 100644 runtime/common/concat.go diff --git a/runtime/ast/access.go b/runtime/ast/access.go index 014ff7e290..5105375114 100644 --- a/runtime/ast/access.go +++ b/runtime/ast/access.go @@ -21,6 +21,7 @@ package ast import ( "encoding/json" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/errors" ) @@ -58,9 +59,12 @@ var BasicAccesses = []Access{ AccessPublicSettable, } -var AllAccesses = append(BasicAccesses[:], - AccessContract, - AccessAccount, +var AllAccesses = common.Concat( + BasicAccesses, + []Access{ + AccessContract, + AccessAccount, + }, ) func (a Access) Keyword() string { diff --git a/runtime/common/concat.go b/runtime/common/concat.go new file mode 100644 index 0000000000..40034c3025 --- /dev/null +++ b/runtime/common/concat.go @@ -0,0 +1,36 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Dapper Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package common + +func Concat[T any](slices ...[]T) []T { + var length int + + for _, slice := range slices { + length += len(slice) + } + + result := make([]T, length) + + var offset int + for _, slice := range slices { + offset += copy(result[offset:], slice) + } + + return result +} diff --git a/runtime/interpreter/value.go b/runtime/interpreter/value.go index 9a95830648..b2befe7a84 100644 --- a/runtime/interpreter/value.go +++ b/runtime/interpreter/value.go @@ -2921,11 +2921,7 @@ func getNumberValueMember(interpreter *Interpreter, v NumberValue, name string, case sema.NumericTypeSaturatingAddFunctionName: return NewHostFunctionValue( interpreter, - &sema.FunctionType{ - ReturnTypeAnnotation: sema.NewTypeAnnotation( - typ, - ), - }, + sema.SaturatingArithmeticTypeFunctionTypes[typ], func(invocation Invocation) Value { other, ok := invocation.Arguments[0].(NumberValue) if !ok { @@ -2942,11 +2938,7 @@ func getNumberValueMember(interpreter *Interpreter, v NumberValue, name string, case sema.NumericTypeSaturatingSubtractFunctionName: return NewHostFunctionValue( interpreter, - &sema.FunctionType{ - ReturnTypeAnnotation: sema.NewTypeAnnotation( - typ, - ), - }, + sema.SaturatingArithmeticTypeFunctionTypes[typ], func(invocation Invocation) Value { other, ok := invocation.Arguments[0].(NumberValue) if !ok { @@ -2963,11 +2955,7 @@ func getNumberValueMember(interpreter *Interpreter, v NumberValue, name string, case sema.NumericTypeSaturatingMultiplyFunctionName: return NewHostFunctionValue( interpreter, - &sema.FunctionType{ - ReturnTypeAnnotation: sema.NewTypeAnnotation( - typ, - ), - }, + sema.SaturatingArithmeticTypeFunctionTypes[typ], func(invocation Invocation) Value { other, ok := invocation.Arguments[0].(NumberValue) if !ok { @@ -2984,11 +2972,7 @@ func getNumberValueMember(interpreter *Interpreter, v NumberValue, name string, case sema.NumericTypeSaturatingDivideFunctionName: return NewHostFunctionValue( interpreter, - &sema.FunctionType{ - ReturnTypeAnnotation: sema.NewTypeAnnotation( - typ, - ), - }, + sema.SaturatingArithmeticTypeFunctionTypes[typ], func(invocation Invocation) Value { other, ok := invocation.Arguments[0].(NumberValue) if !ok { diff --git a/runtime/literal_test.go b/runtime/literal_test.go index 19e1e4b94b..b0f80e8d4e 100644 --- a/runtime/literal_test.go +++ b/runtime/literal_test.go @@ -643,10 +643,12 @@ func TestParseLiteral(t *testing.T) { ) } - for _, signedIntegerType := range append( - sema.AllSignedIntegerTypes[:], - sema.IntegerType, - sema.SignedIntegerType, + for _, signedIntegerType := range common.Concat( + sema.AllSignedIntegerTypes, + []sema.Type{ + sema.IntegerType, + sema.SignedIntegerType, + }, ) { t.Run( diff --git a/runtime/sema/type.go b/runtime/sema/type.go index 2e158dfb56..dbfa9b6973 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -913,9 +913,10 @@ const numericTypeSaturatingDivideFunctionDocString = ` self / other, saturating at the numeric bounds instead of overflowing. ` -func addSaturatingArithmeticFunctions(t SaturatingArithmeticType, members map[string]MemberResolver) { +var SaturatingArithmeticTypeFunctionTypes = map[Type]*FunctionType{} - arithmeticFunctionType := &FunctionType{ +func registerSaturatingArithmeticType(t Type) { + SaturatingArithmeticTypeFunctionTypes[t] = &FunctionType{ Parameters: []Parameter{ { Label: ArgumentLabelNotRequired, @@ -925,13 +926,21 @@ func addSaturatingArithmeticFunctions(t SaturatingArithmeticType, members map[st }, ReturnTypeAnnotation: NewTypeAnnotation(t), } +} + +func addSaturatingArithmeticFunctions(t SaturatingArithmeticType, members map[string]MemberResolver) { addArithmeticFunction := func(name string, docString string) { members[name] = MemberResolver{ Kind: common.DeclarationKindFunction, - Resolve: func(memoryGauge common.MemoryGauge, identifier string, targetRange ast.Range, report func(error)) *Member { + Resolve: func(memoryGauge common.MemoryGauge, _ string, _ ast.Range, _ func(error)) *Member { return NewPublicFunctionMember( - memoryGauge, t, name, arithmeticFunctionType, docString) + memoryGauge, + t, + name, + SaturatingArithmeticTypeFunctionTypes[t], + docString, + ) }, } } @@ -965,20 +974,24 @@ func addSaturatingArithmeticFunctions(t SaturatingArithmeticType, members map[st } } +type SaturatingArithmeticSupport struct { + Add bool + Subtract bool + Multiply bool + Divide bool +} + // NumericType represent all the types in the integer range // and non-fractional ranged types. type NumericType struct { - minInt *big.Int - maxInt *big.Int - memberResolvers map[string]MemberResolver - name string - tag TypeTag - memberResolversOnce sync.Once - supportsSaturatingAdd bool - supportsSaturatingSubtract bool - supportsSaturatingMultiply bool - supportsSaturatingDivide bool - isSuperType bool + minInt *big.Int + maxInt *big.Int + memberResolvers map[string]MemberResolver + name string + tag TypeTag + memberResolversOnce sync.Once + saturatingArithmetic SaturatingArithmeticSupport + isSuperType bool } var _ Type = &NumericType{} @@ -1004,40 +1017,28 @@ func (t *NumericType) WithIntRange(min *big.Int, max *big.Int) *NumericType { return t } -func (t *NumericType) WithSaturatingAdd() *NumericType { - t.supportsSaturatingAdd = true - return t -} +func (t *NumericType) WithSaturatingFunctions(saturatingArithmetic SaturatingArithmeticSupport) *NumericType { + t.saturatingArithmetic = saturatingArithmetic -func (t *NumericType) WithSaturatingSubtract() *NumericType { - t.supportsSaturatingSubtract = true - return t -} - -func (t *NumericType) WithSaturatingMultiply() *NumericType { - t.supportsSaturatingMultiply = true - return t -} + registerSaturatingArithmeticType(t) -func (t *NumericType) WithSaturatingDivide() *NumericType { - t.supportsSaturatingDivide = true return t } func (t *NumericType) SupportsSaturatingAdd() bool { - return t.supportsSaturatingAdd + return t.saturatingArithmetic.Add } func (t *NumericType) SupportsSaturatingSubtract() bool { - return t.supportsSaturatingSubtract + return t.saturatingArithmetic.Subtract } func (t *NumericType) SupportsSaturatingMultiply() bool { - return t.supportsSaturatingMultiply + return t.saturatingArithmetic.Multiply } func (t *NumericType) SupportsSaturatingDivide() bool { - return t.supportsSaturatingDivide + return t.saturatingArithmetic.Divide } func (*NumericType) IsType() {} @@ -1143,20 +1144,17 @@ func (t *NumericType) IsSuperType() bool { // FixedPointNumericType represents all the types in the fixed-point range. type FixedPointNumericType struct { - maxFractional *big.Int - minFractional *big.Int - memberResolvers map[string]MemberResolver - minInt *big.Int - maxInt *big.Int - name string - tag TypeTag - scale uint - memberResolversOnce sync.Once - supportsSaturatingAdd bool - supportsSaturatingDivide bool - supportsSaturatingMultiply bool - supportsSaturatingSubtract bool - isSuperType bool + maxFractional *big.Int + minFractional *big.Int + memberResolvers map[string]MemberResolver + minInt *big.Int + maxInt *big.Int + name string + tag TypeTag + scale uint + memberResolversOnce sync.Once + saturatingArithmetic SaturatingArithmeticSupport + isSuperType bool } var _ Type = &FixedPointNumericType{} @@ -1200,40 +1198,28 @@ func (t *FixedPointNumericType) WithScale(scale uint) *FixedPointNumericType { return t } -func (t *FixedPointNumericType) WithSaturatingAdd() *FixedPointNumericType { - t.supportsSaturatingAdd = true - return t -} - -func (t *FixedPointNumericType) WithSaturatingSubtract() *FixedPointNumericType { - t.supportsSaturatingSubtract = true - return t -} +func (t *FixedPointNumericType) WithSaturatingFunctions(saturatingArithmetic SaturatingArithmeticSupport) *FixedPointNumericType { + t.saturatingArithmetic = saturatingArithmetic -func (t *FixedPointNumericType) WithSaturatingMultiply() *FixedPointNumericType { - t.supportsSaturatingMultiply = true - return t -} + registerSaturatingArithmeticType(t) -func (t *FixedPointNumericType) WithSaturatingDivide() *FixedPointNumericType { - t.supportsSaturatingDivide = true return t } func (t *FixedPointNumericType) SupportsSaturatingAdd() bool { - return t.supportsSaturatingAdd + return t.saturatingArithmetic.Add } func (t *FixedPointNumericType) SupportsSaturatingSubtract() bool { - return t.supportsSaturatingSubtract + return t.saturatingArithmetic.Subtract } func (t *FixedPointNumericType) SupportsSaturatingMultiply() bool { - return t.supportsSaturatingMultiply + return t.saturatingArithmetic.Multiply } func (t *FixedPointNumericType) SupportsSaturatingDivide() bool { - return t.supportsSaturatingDivide + return t.saturatingArithmetic.Divide } func (*FixedPointNumericType) IsType() {} @@ -1381,115 +1367,141 @@ var ( Int8Type = NewNumericType(Int8TypeName). WithTag(Int8TypeTag). WithIntRange(Int8TypeMinInt, Int8TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // Int16Type represents the 16-bit signed integer type `Int16` Int16Type = NewNumericType(Int16TypeName). WithTag(Int16TypeTag). WithIntRange(Int16TypeMinInt, Int16TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // Int32Type represents the 32-bit signed integer type `Int32` Int32Type = NewNumericType(Int32TypeName). WithTag(Int32TypeTag). WithIntRange(Int32TypeMinInt, Int32TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // Int64Type represents the 64-bit signed integer type `Int64` Int64Type = NewNumericType(Int64TypeName). WithTag(Int64TypeTag). WithIntRange(Int64TypeMinInt, Int64TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // Int128Type represents the 128-bit signed integer type `Int128` Int128Type = NewNumericType(Int128TypeName). WithTag(Int128TypeTag). WithIntRange(Int128TypeMinIntBig, Int128TypeMaxIntBig). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // Int256Type represents the 256-bit signed integer type `Int256` Int256Type = NewNumericType(Int256TypeName). WithTag(Int256TypeTag). WithIntRange(Int256TypeMinIntBig, Int256TypeMaxIntBig). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // UIntType represents the arbitrary-precision unsigned integer type `UInt` UIntType = NewNumericType(UIntTypeName). WithTag(UIntTypeTag). WithIntRange(UIntTypeMin, nil). - WithSaturatingSubtract() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Subtract: true, + }) // UInt8Type represents the 8-bit unsigned integer type `UInt8` // which checks for overflow and underflow UInt8Type = NewNumericType(UInt8TypeName). WithTag(UInt8TypeTag). WithIntRange(UInt8TypeMinInt, UInt8TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // UInt16Type represents the 16-bit unsigned integer type `UInt16` // which checks for overflow and underflow UInt16Type = NewNumericType(UInt16TypeName). WithTag(UInt16TypeTag). WithIntRange(UInt16TypeMinInt, UInt16TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // UInt32Type represents the 32-bit unsigned integer type `UInt32` // which checks for overflow and underflow UInt32Type = NewNumericType(UInt32TypeName). WithTag(UInt32TypeTag). WithIntRange(UInt32TypeMinInt, UInt32TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // UInt64Type represents the 64-bit unsigned integer type `UInt64` // which checks for overflow and underflow UInt64Type = NewNumericType(UInt64TypeName). WithTag(UInt64TypeTag). WithIntRange(UInt64TypeMinInt, UInt64TypeMaxInt). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // UInt128Type represents the 128-bit unsigned integer type `UInt128` // which checks for overflow and underflow UInt128Type = NewNumericType(UInt128TypeName). WithTag(UInt128TypeTag). WithIntRange(UInt128TypeMinIntBig, UInt128TypeMaxIntBig). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // UInt256Type represents the 256-bit unsigned integer type `UInt256` // which checks for overflow and underflow UInt256Type = NewNumericType(UInt256TypeName). WithTag(UInt256TypeTag). WithIntRange(UInt256TypeMinIntBig, UInt256TypeMaxIntBig). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) // Word8Type represents the 8-bit unsigned integer type `Word8` // which does NOT check for overflow and underflow @@ -1544,10 +1556,12 @@ var ( WithIntRange(Fix64TypeMinIntBig, Fix64TypeMaxIntBig). WithFractionalRange(Fix64TypeMinFractionalBig, Fix64TypeMaxFractionalBig). WithScale(Fix64Scale). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply(). - WithSaturatingDivide() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + Divide: true, + }) // UFix64Type represents the 64-bit unsigned decimal fixed-point type `UFix64` // which has a scale of 1E9, and checks for overflow and underflow @@ -1556,9 +1570,11 @@ var ( WithIntRange(UFix64TypeMinIntBig, UFix64TypeMaxIntBig). WithFractionalRange(UFix64TypeMinFractionalBig, UFix64TypeMaxFractionalBig). WithScale(Fix64Scale). - WithSaturatingAdd(). - WithSaturatingSubtract(). - WithSaturatingMultiply() + WithSaturatingFunctions(SaturatingArithmeticSupport{ + Add: true, + Subtract: true, + Multiply: true, + }) ) // Numeric type ranges @@ -3124,37 +3140,37 @@ var BaseTypeActivation = NewVariableActivation(nil) func init() { - types := AllNumberTypes[:] - - types = append( - types, - MetaType, - VoidType, - AnyStructType, - AnyStructAttachmentType, - AnyResourceType, - AnyResourceAttachmentType, - NeverType, - BoolType, - CharacterType, - StringType, - TheAddressType, - AuthAccountType, - PublicAccountType, - PathType, - StoragePathType, - CapabilityPathType, - PrivatePathType, - PublicPathType, - &CapabilityType{}, - DeployedContractType, - BlockType, - AccountKeyType, - PublicKeyType, - SignatureAlgorithmType, - HashAlgorithmType, - StorageCapabilityControllerType, - AccountCapabilityControllerType, + types := common.Concat( + AllNumberTypes, + []Type{ + MetaType, + VoidType, + AnyStructType, + AnyStructAttachmentType, + AnyResourceType, + AnyResourceAttachmentType, + NeverType, + BoolType, + CharacterType, + StringType, + TheAddressType, + AuthAccountType, + PublicAccountType, + PathType, + StoragePathType, + CapabilityPathType, + PrivatePathType, + PublicPathType, + &CapabilityType{}, + DeployedContractType, + BlockType, + AccountKeyType, + PublicKeyType, + SignatureAlgorithmType, + HashAlgorithmType, + StorageCapabilityControllerType, + AccountCapabilityControllerType, + }, ) for _, ty := range types { @@ -3202,13 +3218,13 @@ var AllUnsignedFixedPointTypes = []Type{ UFix64Type, } -var AllFixedPointTypes = append( - append( - AllUnsignedFixedPointTypes[:], - AllSignedFixedPointTypes..., - ), - FixedPointType, - SignedFixedPointType, +var AllFixedPointTypes = common.Concat( + AllUnsignedFixedPointTypes, + AllSignedFixedPointTypes, + []Type{ + FixedPointType, + SignedFixedPointType, + }, ) var AllSignedIntegerTypes = []Type{ @@ -3239,22 +3255,22 @@ var AllUnsignedIntegerTypes = []Type{ Word256Type, } -var AllIntegerTypes = append( - append( - AllUnsignedIntegerTypes[:], - AllSignedIntegerTypes..., - ), - IntegerType, - SignedIntegerType, +var AllIntegerTypes = common.Concat( + AllUnsignedIntegerTypes, + AllSignedIntegerTypes, + []Type{ + IntegerType, + SignedIntegerType, + }, ) -var AllNumberTypes = append( - append( - AllIntegerTypes[:], - AllFixedPointTypes..., - ), - NumberType, - SignedNumberType, +var AllNumberTypes = common.Concat( + AllIntegerTypes, + AllFixedPointTypes, + []Type{ + NumberType, + SignedNumberType, + }, ) const NumberTypeMinFieldName = "min" diff --git a/runtime/tests/checker/builtinfunctions_test.go b/runtime/tests/checker/builtinfunctions_test.go index 4d38f49938..bf8c135c41 100644 --- a/runtime/tests/checker/builtinfunctions_test.go +++ b/runtime/tests/checker/builtinfunctions_test.go @@ -25,6 +25,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/sema" ) @@ -32,9 +33,11 @@ func TestCheckToString(t *testing.T) { t.Parallel() - for _, numberOrAddressType := range append( - sema.AllNumberTypes[:], - sema.TheAddressType, + for _, numberOrAddressType := range common.Concat( + sema.AllNumberTypes, + []sema.Type{ + sema.TheAddressType, + }, ) { ty := numberOrAddressType diff --git a/runtime/tests/checker/events_test.go b/runtime/tests/checker/events_test.go index 4ad1b2b798..2dc3b87258 100644 --- a/runtime/tests/checker/events_test.go +++ b/runtime/tests/checker/events_test.go @@ -107,7 +107,8 @@ func TestCheckEventDeclaration(t *testing.T) { t.Parallel() - validTypes := append( + validTypes := common.Concat( + sema.AllNumberTypes, []sema.Type{ sema.StringType, sema.CharacterType, @@ -120,7 +121,6 @@ func TestCheckEventDeclaration(t *testing.T) { sema.PrivatePathType, sema.CapabilityPathType, }, - sema.AllNumberTypes..., ) tests := validTypes[:] diff --git a/runtime/tests/checker/integer_test.go b/runtime/tests/checker/integer_test.go index 1079c2e3f0..c07a7b6163 100644 --- a/runtime/tests/checker/integer_test.go +++ b/runtime/tests/checker/integer_test.go @@ -26,12 +26,15 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/sema" ) -var allIntegerTypesAndAddressType = append( - sema.AllIntegerTypes[:], - sema.TheAddressType, +var allIntegerTypesAndAddressType = common.Concat( + sema.AllIntegerTypes, + []sema.Type{ + sema.TheAddressType, + }, ) func TestCheckIntegerLiteralTypeConversionInVariableDeclaration(t *testing.T) { diff --git a/runtime/tests/checker/operations_test.go b/runtime/tests/checker/operations_test.go index 7c4766b4a2..8f9f9d3091 100644 --- a/runtime/tests/checker/operations_test.go +++ b/runtime/tests/checker/operations_test.go @@ -426,9 +426,9 @@ func TestCheckSaturatedArithmeticFunctions(t *testing.T) { }, } - for _, ty := range append( - sema.AllSignedIntegerTypes[:], - sema.AllSignedFixedPointTypes..., + for _, ty := range common.Concat( + sema.AllSignedIntegerTypes, + sema.AllSignedFixedPointTypes, ) { if ty == sema.IntType { @@ -444,9 +444,9 @@ func TestCheckSaturatedArithmeticFunctions(t *testing.T) { }) } - for _, ty := range append( - sema.AllUnsignedIntegerTypes[:], - sema.AllUnsignedFixedPointTypes..., + for _, ty := range common.Concat( + sema.AllUnsignedIntegerTypes, + sema.AllUnsignedFixedPointTypes, ) { if ty == sema.UIntType || strings.HasPrefix(ty.String(), "Word") { diff --git a/runtime/tests/interpreter/arithmetic_test.go b/runtime/tests/interpreter/arithmetic_test.go index d05273f1be..d108ca90b1 100644 --- a/runtime/tests/interpreter/arithmetic_test.go +++ b/runtime/tests/interpreter/arithmetic_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/require" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" . "github.com/onflow/cadence/runtime/tests/utils" @@ -723,9 +724,9 @@ func TestInterpretSaturatedArithmeticFunctions(t *testing.T) { // Verify all test cases exist - for _, ty := range append( - sema.AllSignedIntegerTypes[:], - sema.AllSignedFixedPointTypes..., + for _, ty := range common.Concat( + sema.AllSignedIntegerTypes, + sema.AllSignedFixedPointTypes, ) { testCase, ok := testCases[ty] @@ -749,9 +750,9 @@ func TestInterpretSaturatedArithmeticFunctions(t *testing.T) { } } - for _, ty := range append( - sema.AllUnsignedIntegerTypes[:], - sema.AllUnsignedFixedPointTypes..., + for _, ty := range common.Concat( + sema.AllUnsignedIntegerTypes, + sema.AllUnsignedFixedPointTypes, ) { if strings.HasPrefix(ty.String(), "Word") { From 0e6d04aef5b971e192394bd0363fec9c5bfdfe27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 6 Jul 2023 12:38:13 -0700 Subject: [PATCH 8/8] use diff command to generate diff --- .../compatibility-check-template.yml | 3 +- .../cmd/check_diff/main.go | 75 ------------------- tools/compatibility-check/go.mod | 2 +- tools/compatibility-check/go.sum | 19 ++--- 4 files changed, 10 insertions(+), 89 deletions(-) delete mode 100644 tools/compatibility-check/cmd/check_diff/main.go diff --git a/.github/workflows/compatibility-check-template.yml b/.github/workflows/compatibility-check-template.yml index d406cc9db7..85879a62d3 100644 --- a/.github/workflows/compatibility-check-template.yml +++ b/.github/workflows/compatibility-check-template.yml @@ -113,6 +113,5 @@ jobs: # Check Diff - name: Check diff - working-directory: ./tools/compatibility-check run: | - go run ./cmd/check_diff/main.go ../../tmp/output-old.txt ../../tmp/output-new.txt + diff -u --color ./tmp/output-old.txt ./tmp/output-new.txt diff --git a/tools/compatibility-check/cmd/check_diff/main.go b/tools/compatibility-check/cmd/check_diff/main.go deleted file mode 100644 index c1e7188e60..0000000000 --- a/tools/compatibility-check/cmd/check_diff/main.go +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Cadence - The resource-oriented smart contract programming language - * - * Copyright Dapper Labs, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package main - -import ( - "fmt" - "os" - - "github.com/rs/zerolog/log" - - "github.com/sergi/go-diff/diffmatchpatch" -) - -func main() { - if len(os.Args) < 2 { - log.Error().Msg("not enough arguments. Usage: old_checking_results new_checking_results") - return - } - - oldResultsPath := os.Args[1] - newResultsPath := os.Args[2] - - oldResultsFile, err := os.ReadFile(oldResultsPath) - if err != nil { - log.Err(err).Msgf("failed to open file: %s", oldResultsPath) - return - } - - newResultsFile, err := os.ReadFile(newResultsPath) - if err != nil { - log.Err(err).Msgf("failed to open file: %s", newResultsPath) - return - } - - compareBytes(oldResultsFile, newResultsFile) -} - -func compareBytes(old, new []byte) { - dmp := diffmatchpatch.New() - - diffs := dmp.DiffMain(string(old), string(new), false) - - changes := make([]diffmatchpatch.Diff, 0) - - // Filter out only the diff chunks with changes. - // No need to print the equal chunks. - for _, diff := range diffs { - if diff.Type == diffmatchpatch.DiffEqual { - continue - } - changes = append(changes, diff) - } - - fmt.Println(dmp.DiffPrettyText(changes)) - - if len(changes) > 0 { - log.Fatal().Msg("found differences") - } -} diff --git a/tools/compatibility-check/go.mod b/tools/compatibility-check/go.mod index e9d3b6135c..9cb961cde1 100644 --- a/tools/compatibility-check/go.mod +++ b/tools/compatibility-check/go.mod @@ -5,7 +5,6 @@ go 1.19 require ( github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121 github.com/rs/zerolog v1.26.1 - github.com/sergi/go-diff v1.2.0 github.com/stretchr/testify v1.7.3 ) @@ -15,6 +14,7 @@ require ( github.com/fxamacker/cbor/v2 v2.4.1-0.20220515183430-ad2eae63303f // indirect github.com/fxamacker/circlehash v0.3.0 // indirect github.com/klauspost/cpuid/v2 v2.0.14 // indirect + github.com/kr/pretty v0.3.1 // indirect github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect github.com/onflow/atree v0.4.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/tools/compatibility-check/go.sum b/tools/compatibility-check/go.sum index cbc3f58844..765ad9dce2 100644 --- a/tools/compatibility-check/go.sum +++ b/tools/compatibility-check/go.sum @@ -1,6 +1,7 @@ github.com/bits-and-blooms/bitset v1.2.2 h1:J5gbX05GpMdBjCvQ9MteIg2KKDExr7DrgK+Yc15FvIk= github.com/bits-and-blooms/bitset v1.2.2/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -14,11 +15,10 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.14 h1:QRqdp6bb9M9S5yyKeYteXKuoKE4p0tGlra81fKOpWH8= github.com/klauspost/cpuid/v2 v2.0.14/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs= github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= @@ -26,20 +26,20 @@ github.com/onflow/atree v0.4.0 h1:+TbNisavAkukAKhgQ4plWnvR9o5+SkwPIsi3jaeAqKs= github.com/onflow/atree v0.4.0/go.mod h1:7Qe1xaW0YewvouLXrugzMFUYXNoRQ8MT/UsVAWx1Ndo= github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121 h1:pOJOFoX1fEwoXyzhU9Q8VtGUlZUnMCj4LcuOJdBnLgk= github.com/onflow/cadence v0.31.2-0.20230207221811-9eb6e7fe4121/go.mod h1:hhktaaXlJmxnfLgH2HG0cftcUWScdfjO/CTZkzaom/g= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a h1:s7GrsqeorVkFR1vGmQ6WVL9nup0eyQCC+YVUeSQLH/Q= github.com/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.3 h1:dAm0YRdRQlWojc3CrCRgPBzG5f941d0zvAKu7qY4e+I= github.com/stretchr/testify v1.7.3/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -98,9 +98,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=