Skip to content

Commit

Permalink
Merge pull request #3164 from onflow/bastian/merge-intersections
Browse files Browse the repository at this point in the history
Handle legacy type getting converted to intersection type
  • Loading branch information
turbolent authored Mar 11, 2024
2 parents dc4fa63 + d0c593e commit ac10fc9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 3 deletions.
24 changes: 21 additions & 3 deletions migrations/statictypes/statictype_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,16 +247,31 @@ func (m *StaticTypeMigration) maybeConvertStaticType(staticType, parentType inte

legacyType := rewrittenIntersectionType.LegacyType

var mergedIntersections bool

var convertedLegacyType interpreter.StaticType
if legacyType != nil {
convertedLegacyType = m.maybeConvertStaticType(legacyType, rewrittenIntersectionType)
switch convertedLegacyType.(type) {
switch ty := convertedLegacyType.(type) {
case nil,
*interpreter.CompositeStaticType,
interpreter.PrimitiveStaticType:
// valid
break

case *interpreter.IntersectionStaticType:
// If the legacy type was converted to an intersection type,
// then merge it into the resulting intersection type

legacyType = nil
convertedLegacyType = nil

convertedInterfaceTypes = append(
convertedInterfaceTypes,
ty.Types...,
)
mergedIntersections = true

default:
panic(fmt.Errorf(
"invalid non-composite/primitive replacement for legacy type in intersection type %s:"+
Expand All @@ -273,13 +288,16 @@ func (m *StaticTypeMigration) maybeConvertStaticType(staticType, parentType inte
// If the interface set has at least two items,
// then force it to be re-stored/re-encoded,
// even if the interface types in the set have not changed.
if len(rewrittenIntersectionType.Types) >= 2 || convertedInterfaceType || convertedLegacyType != nil {
if len(rewrittenIntersectionType.Types) >= 2 ||
convertedInterfaceType ||
convertedLegacyType != nil ||
mergedIntersections {

result := interpreter.NewIntersectionStaticType(nil, convertedInterfaceTypes)

if convertedLegacyType != nil {
result.LegacyType = convertedLegacyType
} else {
} else if legacyType != nil {
result.LegacyType = legacyType
}

Expand Down
87 changes: 87 additions & 0 deletions migrations/statictypes/statictype_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,93 @@ func TestStaticTypeMigration(t *testing.T) {
})

})

t.Run("merge converted legacy type when intersection", func(t *testing.T) {

t.Parallel()

const compositeQualifiedIdentifier = "S"
compositeType := interpreter.NewCompositeStaticType(
nil,
utils.TestLocation,
compositeQualifiedIdentifier,
utils.TestLocation.TypeID(nil, compositeQualifiedIdentifier),
)

const interface1QualifiedIdentifier = "SI1"
interfaceType1 := interpreter.NewInterfaceStaticType(
nil,
utils.TestLocation,
interface1QualifiedIdentifier,
utils.TestLocation.TypeID(nil, interface1QualifiedIdentifier),
)

const interface2QualifiedIdentifier = "SI2"
interfaceType2 := interpreter.NewInterfaceStaticType(
nil,
utils.TestLocation,
interface2QualifiedIdentifier,
utils.TestLocation.TypeID(nil, interface2QualifiedIdentifier),
)

intersectionType := interpreter.NewIntersectionStaticType(
nil,
[]*interpreter.InterfaceStaticType{
interfaceType1,
},
)
// NOTE: the legacy type is a composite type,
// but it will get rewritten to an intersection type

intersectionType.LegacyType = compositeType

staticTypeMigration := NewStaticTypeMigration().WithCompositeTypeConverter(
func(staticType *interpreter.CompositeStaticType) interpreter.StaticType {
if staticType.TypeID != compositeType.TypeID {
return nil
}

return interpreter.NewIntersectionStaticType(
nil,
[]*interpreter.InterfaceStaticType{
interfaceType2,
},
)
},
)

storedValue := interpreter.NewTypeValue(
nil,
interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
intersectionType,
),
)

actual := migrate(t,
staticTypeMigration,
storedValue,
true,
)

expected := interpreter.NewTypeValue(
nil,
interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.NewIntersectionStaticType(
nil,
[]*interpreter.InterfaceStaticType{
interfaceType1,
interfaceType2,
},
),
),
)

assert.Equal(t, expected, actual)
})
}

func TestMigratingNestedContainers(t *testing.T) {
Expand Down

0 comments on commit ac10fc9

Please sign in to comment.