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

Improve type inference #3004

Merged
merged 1 commit into from
Jan 10, 2024
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
42 changes: 33 additions & 9 deletions runtime/sema/check_invocation_expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,29 +578,53 @@

var argumentType Type

if len(functionType.TypeParameters) == 0 {
// If the function doesn't use generic types, then the
// param types can be used to infer the types for arguments.
typeParameterCount := len(functionType.TypeParameters)

// If all type parameters have been bound to a type,
// then resolve the parameter type with the type arguments,
// and propose the parameter type as the expected type for the argument.
if typeParameters.Len() == typeParameterCount {

// Optimization: only resolve if there are type parameters.
// This avoids unnecessary work for non-generic functions.
if typeParameterCount > 0 {
parameterType = parameterType.Resolve(typeParameters)
// If the type parameter could not be resolved, use the invalid type.
if parameterType == nil {
parameterType = InvalidType
}

Check warning on line 595 in runtime/sema/check_invocation_expression.go

View check run for this annotation

Codecov / codecov/patch

runtime/sema/check_invocation_expression.go#L594-L595

Added lines #L594 - L595 were not covered by tests
}

argumentType = checker.VisitExpression(argument.Expression, parameterType)

} else {
// TODO: pass the expected type to support for parameters
// If there are still type parameters that have not been bound to a type,
// then check the argument without an expected type.
//
// We will then have to manually check that the argument type is compatible
// with the parameter type (see below).

argumentType = checker.VisitExpression(argument.Expression, nil)

// Try to unify the parameter type with the argument type.
// If unification fails, fall back to the parameter type for now.

argumentRange := ast.NewRangeFromPositioned(checker.memoryGauge, argument.Expression)
turbolent marked this conversation as resolved.
Show resolved Hide resolved

if parameterType.Unify(argumentType, typeParameters, checker.report, argumentRange) {
if parameterType.Unify(
argumentType,
typeParameters,
checker.report,
checker.memoryGauge,
argument.Expression,
) {
parameterType = parameterType.Resolve(typeParameters)
// If the type parameter could not be resolved, use the invalid type.
if parameterType == nil {
parameterType = InvalidType
}
}

// Check that the type of the argument matches the type of the parameter.

// TODO: remove this once type inferring support for parameters is added
checker.checkInvocationArgumentParameterTypeCompatibility(
argument.Expression,
argumentType,
Expand Down Expand Up @@ -695,7 +719,7 @@
// If the type parameter corresponding to the type argument has a type bound,
// then check that the argument is a subtype of the type bound.

err := typeParameter.checkTypeBound(ty, ast.NewRangeFromPositioned(checker.memoryGauge, rawTypeArgument))
err := typeParameter.checkTypeBound(ty, checker.memoryGauge, rawTypeArgument)
checker.report(err)

// Bind the type argument to the type parameter
Expand Down
3 changes: 2 additions & 1 deletion runtime/sema/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -2475,7 +2475,8 @@ func (checker *Checker) convertInstantiationType(t *ast.InstantiationType) Type

err := typeParameter.checkTypeBound(
typeArgument,
ast.NewRangeFromPositioned(checker.memoryGauge, rawTypeArgument),
checker.memoryGauge,
rawTypeArgument,
)
checker.report(err)
}
Expand Down
8 changes: 7 additions & 1 deletion runtime/sema/simple_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,13 @@ func (t *SimpleType) RewriteWithIntersectionTypes() (Type, bool) {
return t, false
}

func (*SimpleType) Unify(_ Type, _ *TypeParameterTypeOrderedMap, _ func(err error), _ ast.Range) bool {
func (*SimpleType) Unify(
_ Type,
_ *TypeParameterTypeOrderedMap,
_ func(err error),
_ common.MemoryGauge,
_ ast.HasPosition,
) bool {
return false
}

Expand Down
Loading
Loading