diff --git a/src/language/helpers/safe-ds-node-mapper.ts b/src/language/helpers/safe-ds-node-mapper.ts index abe432af7..c371a80bc 100644 --- a/src/language/helpers/safe-ds-node-mapper.ts +++ b/src/language/helpers/safe-ds-node-mapper.ts @@ -23,10 +23,10 @@ import { argumentsOrEmpty, parametersOrEmpty, typeArgumentsOrEmpty, typeParamete import { isNamedArgument, isNamedTypeArgument } from './checks.js'; export class SafeDsNodeMapper { - private readonly typeComputer: SafeDsTypeComputer; + private readonly typeComputer: () => SafeDsTypeComputer; constructor(services: SafeDsServices) { - this.typeComputer = new SafeDsTypeComputer(services); + this.typeComputer = () => services.types.TypeComputer; } /** @@ -36,7 +36,7 @@ export class SafeDsNodeMapper { if (isSdsAnnotationCall(node)) { return node.annotation?.ref; } else if (isSdsCall(node)) { - const receiverType = this.typeComputer.computeType(node.receiver); + const receiverType = this.typeComputer().computeType(node.receiver); if (receiverType instanceof CallableType) { return receiverType.sdsCallable; } else if (receiverType instanceof StaticType) { diff --git a/src/language/typing/safe-ds-type-computer.ts b/src/language/typing/safe-ds-type-computer.ts index 0869cde13..79108af60 100644 --- a/src/language/typing/safe-ds-type-computer.ts +++ b/src/language/typing/safe-ds-type-computer.ts @@ -79,16 +79,19 @@ import { resultsOrEmpty, typeArgumentsOrEmpty, } from '../helpers/shortcuts.js'; +import { SafeDsNodeMapper } from '../helpers/safe-ds-node-mapper.js'; export class SafeDsTypeComputer { - readonly astNodeLocator: AstNodeLocator; - readonly coreClasses: SafeDsCoreClasses; + private readonly astNodeLocator: AstNodeLocator; + private readonly coreClasses: SafeDsCoreClasses; + private readonly nodeMapper: SafeDsNodeMapper; readonly typeCache: WorkspaceCache; constructor(readonly services: SafeDsServices) { this.astNodeLocator = services.workspace.AstNodeLocator; this.coreClasses = services.builtins.CoreClasses; + this.nodeMapper = services.helpers.NodeMapper; this.typeCache = new WorkspaceCache(services.shared); } @@ -214,20 +217,20 @@ export class SafeDsTypeComputer { const containerOfLambda = containingCallable.$container; // Lambda passed as argument - /* c8 ignore start */ if (isSdsArgument(containerOfLambda)) { - // val containerType = when (val container = callable.eContainer()) { - // is SdsArgument -> container.parameterOrNull()?.inferType(context) - // } - // - // return when (containerType) { - // is CallableType -> containerType.parameters.getOrElse(thisIndex) { Any(context) } - // else -> Any(context) - // } + const parameter = this.nodeMapper.argumentToParameterOrUndefined(containerOfLambda); + if (!parameter) { + return UnknownType; + } - return NotImplementedType; + const parameterType = this.computeType(parameter?.type); + if (!(parameterType instanceof CallableType)) { + return UnknownType; + } + + const parameterPosition = node.$containerIndex ?? -1; + return parameterType.getParameterTypeByPosition(parameterPosition) ?? UnknownType; } - /* c8 ignore stop */ // Yielded lambda else if (isSdsAssignment(containerOfLambda)) { diff --git a/tests/resources/typing/expressions/block lambdas/that are passed as arguments/main.sdstest b/tests/resources/typing/expressions/block lambdas/that are passed as arguments/main.sdstest index 8734f2b8c..a3cb6ad35 100644 --- a/tests/resources/typing/expressions/block lambdas/that are passed as arguments/main.sdstest +++ b/tests/resources/typing/expressions/block lambdas/that are passed as arguments/main.sdstest @@ -3,6 +3,7 @@ package tests.typing.expressions.blockLambdas.thatArePassedAsArguments fun higherOrderFunction1(param: (p: String) -> (r: Int, s: String)) fun higherOrderFunction2(param: () -> ()) fun normalFunction(param: Int) +fun parameterlessFunction() segment mySegment() { // $TEST$ serialization (p: String) -> (r: Int, s: String) @@ -37,4 +38,9 @@ segment mySegment() { normalFunction(param = »(p) { yield r, yield s = 1; }«); + + // $TEST$ serialization (p: $Unknown) -> (r: Int, s: $Unknown) + parameterlessFunction(»(p) { + yield r, yield s = 1; + }«); } diff --git a/tests/resources/typing/expressions/expression lambdas/that are passed as arguments/main.sdstest b/tests/resources/typing/expressions/expression lambdas/that are passed as arguments/main.sdstest index 449bc0f99..8e9eff78f 100644 --- a/tests/resources/typing/expressions/expression lambdas/that are passed as arguments/main.sdstest +++ b/tests/resources/typing/expressions/expression lambdas/that are passed as arguments/main.sdstest @@ -3,6 +3,7 @@ package tests.typing.expressions.expressionLambdas.thatArePassedAsArguments fun higherOrderFunction1(param: (p: String) -> (r: Int)) fun higherOrderFunction2(param: () -> ()) fun normalFunction(param: Int) +fun parameterlessFunction() segment mySegment() { // $TEST$ serialization (p: String) -> (result: Int) @@ -22,4 +23,7 @@ segment mySegment() { // $TEST$ serialization (p: $Unknown) -> (result: Int) normalFunction(param = »(p) -> 1«); + + // $TEST$ serialization (p: $Unknown) -> (result: Int) + parameterlessFunction(»(p) -> 1«); }