From af5f75d87faef807dbea98981b793fe0b0406d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 25 Jul 2024 14:09:01 -0700 Subject: [PATCH 1/3] add reproducer for invalid transfer error with invalid expected type --- runtime/tests/interpreter/interpreter_test.go | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/runtime/tests/interpreter/interpreter_test.go b/runtime/tests/interpreter/interpreter_test.go index 384ee93d1d..babfae0416 100644 --- a/runtime/tests/interpreter/interpreter_test.go +++ b/runtime/tests/interpreter/interpreter_test.go @@ -11684,6 +11684,42 @@ func TestInterpretNilCoalesceReference(t *testing.T) { ) } +func TestInterpretNilCoalesceAnyResourceAndPanic(t *testing.T) { + + t.Parallel() + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(stdlib.PanicFunction) + + baseActivation := activations.NewActivation(nil, interpreter.BaseActivation) + interpreter.Declare(baseActivation, stdlib.PanicFunction) + + _, err := parseCheckAndInterpretWithOptions(t, + ` + resource R {} + + fun f(): @AnyResource? { + return <-create R() + } + + let y <- f() ?? panic("no R") + `, + ParseCheckAndInterpretOptions{ + CheckerConfig: &sema.Config{ + BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { + return baseValueActivation + }, + }, + Config: &interpreter.Config{ + BaseActivationHandler: func(_ common.Location) *interpreter.VariableActivation { + return baseActivation + }, + }, + }, + ) + require.NoError(t, err) +} + func TestInterpretDictionaryDuplicateKey(t *testing.T) { t.Parallel() From 6fa876badec5f6b5418429b74d66a9d4250ccec5 Mon Sep 17 00:00:00 2001 From: Supun Setunga Date: Thu, 25 Jul 2024 14:48:54 -0700 Subject: [PATCH 2/3] Report invalid types in least-common-supertype calculation --- runtime/sema/check_array_expression.go | 10 +--------- runtime/sema/check_binary_expression.go | 2 +- runtime/sema/check_conditional.go | 2 +- runtime/sema/check_dictionary_expression.go | 17 ++++++----------- runtime/sema/checker.go | 15 +++++++++++++++ runtime/tests/checker/conditional_test.go | 3 ++- 6 files changed, 26 insertions(+), 23 deletions(-) diff --git a/runtime/sema/check_array_expression.go b/runtime/sema/check_array_expression.go index 2da9858d0c..fa1b5c544c 100644 --- a/runtime/sema/check_array_expression.go +++ b/runtime/sema/check_array_expression.go @@ -80,16 +80,8 @@ func (checker *Checker) VisitArrayExpression(arrayExpression *ast.ArrayExpressio if elementType == nil { // Contextually expected type is not available. // Therefore, find the least common supertype of the elements. - elementType = LeastCommonSuperType(argumentTypes...) - + elementType = checker.leastCommonSuperType(arrayExpression, argumentTypes...) if elementType == InvalidType { - checker.report( - &TypeAnnotationRequiredError{ - Cause: "cannot infer type from array literal:", - Pos: arrayExpression.StartPos, - }, - ) - return InvalidType } diff --git a/runtime/sema/check_binary_expression.go b/runtime/sema/check_binary_expression.go index e15d1894a0..2980478306 100644 --- a/runtime/sema/check_binary_expression.go +++ b/runtime/sema/check_binary_expression.go @@ -468,5 +468,5 @@ func (checker *Checker) checkBinaryExpressionNilCoalescing( } } - return LeastCommonSuperType(leftOptional.Type, rightType) + return checker.leastCommonSuperType(expression, leftOptional.Type, rightType) } diff --git a/runtime/sema/check_conditional.go b/runtime/sema/check_conditional.go index 152c489e46..9c4da9cd52 100644 --- a/runtime/sema/check_conditional.go +++ b/runtime/sema/check_conditional.go @@ -128,7 +128,7 @@ func (checker *Checker) VisitConditionalExpression(expression *ast.ConditionalEx return thenType } - return LeastCommonSuperType(thenType, elseType) + return checker.leastCommonSuperType(expression, thenType, elseType) } // checkConditionalBranches checks two conditional branches. diff --git a/runtime/sema/check_dictionary_expression.go b/runtime/sema/check_dictionary_expression.go index 94a4758913..77f2c5fd78 100644 --- a/runtime/sema/check_dictionary_expression.go +++ b/runtime/sema/check_dictionary_expression.go @@ -69,18 +69,13 @@ func (checker *Checker) VisitDictionaryExpression(expression *ast.DictionaryExpr if keyType == nil && valueType == nil { // Contextually expected type is not available. // Therefore, find the least common supertype of the keys and values. - keyType = LeastCommonSuperType(keyTypes...) - valueType = LeastCommonSuperType(valueTypes...) - - if keyType == InvalidType || - valueType == InvalidType { - checker.report( - &TypeAnnotationRequiredError{ - Cause: "cannot infer type from dictionary literal:", - Pos: expression.StartPos, - }, - ) + keyType = checker.leastCommonSuperType(expression, keyTypes...) + if keyType == InvalidType { + return InvalidType + } + valueType = checker.leastCommonSuperType(expression, valueTypes...) + if valueType == InvalidType { return InvalidType } } diff --git a/runtime/sema/checker.go b/runtime/sema/checker.go index e44c8c5603..a03655e0ac 100644 --- a/runtime/sema/checker.go +++ b/runtime/sema/checker.go @@ -2766,3 +2766,18 @@ func (checker *Checker) checkNativeModifier(isNative bool, position ast.HasPosit ) } } + +func (checker *Checker) leastCommonSuperType(pos ast.HasPosition, types ...Type) Type { + elementType := LeastCommonSuperType(types...) + + if elementType == InvalidType { + checker.report( + &TypeAnnotationRequiredError{ + Cause: "cannot infer type:", + Pos: pos.StartPosition(), + }, + ) + } + + return elementType +} diff --git a/runtime/tests/checker/conditional_test.go b/runtime/tests/checker/conditional_test.go index 6078d12fd0..86e918a018 100644 --- a/runtime/tests/checker/conditional_test.go +++ b/runtime/tests/checker/conditional_test.go @@ -66,9 +66,10 @@ func TestCheckInvalidConditionalExpressionElse(t *testing.T) { let x = true ? 2 : y `) - errs := RequireCheckerErrors(t, err, 1) + errs := RequireCheckerErrors(t, err, 2) assert.IsType(t, &sema.NotDeclaredError{}, errs[0]) + assert.IsType(t, &sema.TypeAnnotationRequiredError{}, errs[1]) xType := RequireGlobalValue(t, checker.Elaboration, "x") assert.Equal(t, sema.InvalidType, xType) From 5e772b064910c55b68e83de3e86153900f848ace Mon Sep 17 00:00:00 2001 From: Supun Setunga Date: Thu, 25 Jul 2024 15:04:23 -0700 Subject: [PATCH 3/3] Ignore 'Never' type in super-type calculation for hetergeneous types --- runtime/sema/type_tags.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/runtime/sema/type_tags.go b/runtime/sema/type_tags.go index 1990b0b9c9..f82e46f884 100644 --- a/runtime/sema/type_tags.go +++ b/runtime/sema/type_tags.go @@ -997,6 +997,11 @@ func commonSuperTypeOfHeterogeneousTypes(types []Type) Type { var hasStructs, hasResources, allHashableStructs bool allHashableStructs = true for _, typ := range types { + // Ignore 'Never' type as it doesn't affect the supertype. + if typ == NeverType { + continue + } + isResource := typ.IsResourceType() hasResources = hasResources || isResource hasStructs = hasStructs || !isResource