Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Checker] check and reject composite types with non-storable fields #180

Merged
merged 20 commits into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,7 @@ func validateArgumentParams(
return argumentValues, nil
}

// ParseAndCheckProgram parses the given script and runs type check.
func (r *interpreterRuntime) ParseAndCheckProgram(script []byte, runtimeInterface Interface, location Location) error {
runtimeStorage := newInterpreterRuntimeStorage(runtimeInterface)
functions := r.standardLibraryFunctions(runtimeInterface, runtimeStorage)
Expand Down
31 changes: 31 additions & 0 deletions runtime/sema/check_composite_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,19 @@ func (checker *Checker) declareCompositeMembersAndValue(
checker.declareInterfaceMembers(nestedInterfaceDeclaration)
}

// If this composite declaration has nested composite declaration,
// then recursively declare the members and values of them.
//
// For instance, a structure `S`, defined within a contract `MyContract`,
// as shown in the example code below, is a nested composite declaration
// which has its own members:
// ```
// contract MyContract {
// struct S {
// var v: Int
// }
// }
// ```
for _, nestedCompositeDeclaration := range declaration.CompositeDeclarations {
checker.declareCompositeMembersAndValue(nestedCompositeDeclaration, kind)

Expand Down Expand Up @@ -562,6 +575,23 @@ func (checker *Checker) declareCompositeMembersAndValue(
)
}

// Check if all members' types are allowed.
// A member's type is allowed if it is storable

for _, member := range members {
// If a member has a non-storable type, then report an error

if !member.IsStorable() {
checker.report(
&FieldTypeNotStorableError{
Name: member.Identifier.Identifier,
Type: member.TypeAnnotation.Type,
Pos: member.Identifier.Pos,
},
)
}
}

compositeType.Members = members
checker.memberOrigins[compositeType] = origins
})()
Expand Down Expand Up @@ -1272,6 +1302,7 @@ func (checker *Checker) checkNoInitializerNoFields(
)
}

// checkSpecialFunction checks special functions, like initializers and destructors
func (checker *Checker) checkSpecialFunction(
specialFunction *ast.SpecialFunctionDeclaration,
containerType Type,
Expand Down
27 changes: 27 additions & 0 deletions runtime/sema/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,33 @@ func (e *FieldUninitializedError) EndPosition() ast.Position {
return e.Pos.Shifted(length - 1)
}

// FieldTypeNotStorableError is an error that is reported for
// field of composite types that are not storable.
//
// Field types have to be storable because the storage
// layer needs to know how to store the field, which is not
// possible for all types.
//
// For example, the type `Int` is a storable type,
// whereas a function type is not.

type FieldTypeNotStorableError struct {
// Field's name
Name string
// Field's type
Type Type
// StartPosition of the error
Pos ast.Position
}

func (e *FieldTypeNotStorableError) Error() string {
return fmt.Sprintf(
"field %s has non-storable type: %s",
e.Name,
e.Type,
)
}

// FunctionExpressionInConditionError

type FunctionExpressionInConditionError struct {
Expand Down
Loading