diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 2894a507a60..d750ac7eaf2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -233,6 +233,9 @@ public interface Errors { DiagnosticFactory0 REIFIED_TYPE_PARAMETER_NO_INLINE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 TYPE_PARAMETERS_NOT_ALLOWED + = DiagnosticFactory0.create(ERROR, TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE); + // Members DiagnosticFactory0 PACKAGE_MEMBER_CANNOT_BE_PROTECTED = @@ -339,6 +342,10 @@ public interface Errors { DiagnosticFactory0 NO_TAIL_CALLS_FOUND = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); + DiagnosticFactory0 FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR, PARAMETER_DEFAULT_VALUE); + + DiagnosticFactory0 USELESS_VARARG_ON_PARAMETER = DiagnosticFactory0.create(WARNING); + // Named parameters DiagnosticFactory0 DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE = DiagnosticFactory0.create(ERROR, PARAMETER_DEFAULT_VALUE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt index a1154f712ae..857caff2bb2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/PositioningStrategies.kt @@ -168,6 +168,18 @@ public object PositioningStrategies { } } + public val TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE: PositioningStrategy = object : PositioningStrategy() { + override fun mark(element: JetDeclaration): List { + if (element is JetTypeParameterListOwner) { + val jetTypeParameterList = element.getTypeParameterList() + if (jetTypeParameterList != null) { + return markElement(jetTypeParameterList) + } + } + return DECLARATION_SIGNATURE.mark(element) + } + } + public val ABSTRACT_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.ABSTRACT_KEYWORD) public val INNER_MODIFIER: PositioningStrategy = modifierSetPosition(JetTokens.INNER_KEYWORD) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7aa8cba5515..b6672d7504c 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -229,6 +229,9 @@ public class DefaultErrorMessages { MAP.put(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE, "Public or protected member should have specified type"); + MAP.put(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE, "A function expression is not allowed to specify default values for its parameters"); + MAP.put(USELESS_VARARG_ON_PARAMETER, "Vararg on this parameter is useless"); + MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); MAP.put(SUPERTYPE_NOT_INITIALIZED, "This type has a constructor, and thus must be initialized here"); MAP.put(NOTHING_TO_OVERRIDE, "''{0}'' overrides nothing", NAME); @@ -570,6 +573,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_PARAMETER_AS_REIFIED, "Cannot use ''{0}'' as reified type parameter. Use a class instead.", NAME); MAP.put(REIFIED_TYPE_PARAMETER_NO_INLINE, "Only type parameters of inline functions can be reified"); MAP.put(REIFIED_TYPE_FORBIDDEN_SUBSTITUTION, "Cannot use ''{0}'' as reified type parameter", RENDER_TYPE); + MAP.put(TYPE_PARAMETERS_NOT_ALLOWED, "Type parameters are not allowed here"); MAP.put(SUPERTYPES_FOR_ANNOTATION_CLASS, "Annotation class cannot have supertypes"); MAP.put(MISSING_VAL_ON_ANNOTATION_PARAMETER, "'val' keyword is missing on annotation parameter"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 60fd7aba81f..8bf40a7c4d6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -241,7 +241,7 @@ public class DescriptorResolver { } @NotNull - public SimpleFunctionDescriptor resolveAnonymousFunctionDescriptor( + public SimpleFunctionDescriptor resolveFunctionExpressionDescriptor( @NotNull DeclarationDescriptor containingDescriptor, @NotNull JetScope scope, @NotNull JetNamedFunction function, diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 1e0f838d615..86557104066 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -20,6 +20,8 @@ import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import kotlin.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,6 +31,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor; import org.jetbrains.kotlin.diagnostics.Diagnostic; +import org.jetbrains.kotlin.diagnostics.DiagnosticUtils; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; @@ -1302,22 +1305,78 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { boolean isStatement, @Nullable WritableScope statementScope // must be not null if isStatement ) { - SimpleFunctionDescriptor functionDescriptor = components.expressionTypingServices.getDescriptorResolver(). - resolveFunctionDescriptorWithAnnotationArguments( - context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo); + if (!isStatement) { // function expression + if (!function.getTypeParameters().isEmpty()) { + context.trace.report(TYPE_PARAMETERS_NOT_ALLOWED.on(function)); + } + for (JetParameter parameter : function.getValueParameters()) { + if (parameter.hasDefaultValue()) { + context.trace.report(FUNCTION_EXPRESSION_PARAMETER_WITH_DEFAULT_VALUE.on(parameter)); + } + if (parameter.isVarArg()) { + context.trace.report(USELESS_VARARG_ON_PARAMETER.on(parameter)); + } + } + } + + ExpressionTypingServices services = components.expressionTypingServices; + + SimpleFunctionDescriptor functionDescriptor; + if (isStatement) { + functionDescriptor = services.getDescriptorResolver(). + resolveFunctionDescriptorWithAnnotationArguments( + context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo); + assert statementScope != null : "statementScope must be not null for function: " + + function.getName() + + " at location " + + DiagnosticUtils.atLocation(function); + statementScope.addFunctionDescriptor(functionDescriptor); + } + else { + functionDescriptor = services.getDescriptorResolver().resolveFunctionExpressionDescriptor( + context.scope.getContainingDeclaration(), context.scope, function, context.trace, context.dataFlowInfo); + } - statementScope.addFunctionDescriptor(functionDescriptor); JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); - components.expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace); + services.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo, null, context.trace); - components.expressionTypingServices.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(), - context.scope, context.dataFlowInfo, context.trace); + services.resolveValueParameters(function.getValueParameters(), functionDescriptor.getValueParameters(), context.scope, + context.dataFlowInfo, context.trace); - ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function, functionDescriptor); + ModifiersChecker.create(context.trace, components.additionalCheckerProvider).checkModifiersForLocalDeclaration(function, + functionDescriptor); if (!function.hasBody()) { context.trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); } - return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo); + + if (isStatement) { + return DataFlowUtils.checkStatementType(function, context, context.dataFlowInfo); + } + else { + return DataFlowUtils.checkType(createFunctionType(functionDescriptor), function, context, context.dataFlowInfo); + } + } + + @Nullable + private JetType createFunctionType(@NotNull SimpleFunctionDescriptor functionDescriptor) { + JetType receiverType = functionDescriptor.getExtensionReceiverParameter() != null + ? functionDescriptor.getExtensionReceiverParameter().getType() + : null; + + JetType returnType = functionDescriptor.getReturnType(); + if (returnType == null) { + return null; + } + + List parameters = + ContainerUtil.map(functionDescriptor.getValueParameters(), new Function() { + @Override + public JetType fun(ValueParameterDescriptor descriptor) { + return descriptor.getType(); + } + }); + + return components.builtIns.getFunctionType(Annotations.EMPTY, receiverType, parameters, returnType); } @Override diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/Common.kt b/compiler/testData/diagnostics/tests/functionAsExpression/Common.kt new file mode 100644 index 00000000000..134b0e17edf --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/Common.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +annotation class ann(val name: String) +val ok = "OK" + +class A + +val withName = fun name() {} +val extensionWithName = fun A.name() {} +val withoutName = fun () {} +val extensionWithoutName = fun A.() {} + +fun withAnnotation() = [ann(ok)] fun () {} +val withReturn = fun (): Int { return 5} +val withExpression = fun() = 5 +val funfun = fun() = fun() = 5 + +val parentesized = (fun () {}) +val parentesizedWithType = (fun () {}) : () -> Unit +val withType = (fun () {}) : () -> Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/Common.txt b/compiler/testData/diagnostics/tests/functionAsExpression/Common.txt new file mode 100644 index 00000000000..2ac715e9b26 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/Common.txt @@ -0,0 +1,29 @@ +package + +internal val extensionWithName: A.() -> kotlin.Unit +internal val extensionWithoutName: A.() -> kotlin.Unit +internal val funfun: () -> () -> kotlin.Int +internal val ok: kotlin.String = "OK" +internal val parentesized: () -> kotlin.Unit +internal val parentesizedWithType: () -> kotlin.Unit +internal val withExpression: () -> kotlin.Int +internal val withName: () -> kotlin.Unit +internal val withReturn: () -> kotlin.Int +internal val withType: () -> kotlin.Unit +internal val withoutName: () -> kotlin.Unit +internal fun withAnnotation(): () -> kotlin.Unit + +internal final class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final annotation class ann : kotlin.Annotation { + public constructor ann(/*0*/ name: kotlin.String) + internal final val name: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.kt b/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.kt new file mode 100644 index 00000000000..85b94c9bd5d --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.kt @@ -0,0 +1,27 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE + +fun test() { + fun bar() { + val bas = fun() { + return@bar + } + } + + val bar = fun() { + return@test + } +} + +fun foo() { + val bal = @bag fun () { + val bar = fun() { + return@bag + } + return@bag + } + val bag = fun name() { + val bar = fun () { + return@name + } + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.txt b/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.txt new file mode 100644 index 00000000000..bdb11ff5fa8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.txt @@ -0,0 +1,4 @@ +package + +internal fun foo(): kotlin.Unit +internal fun test(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.kt b/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.kt new file mode 100644 index 00000000000..48517ffcc6d --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.kt @@ -0,0 +1,31 @@ +// !CHECK_TYPE +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +fun testReturnType(foo: String) { + val bar = fun () = foo + + bar.checkType { it : _<() -> String> } + + val bas: () -> String = fun () = foo + + val bag: () -> Int = fun () = foo +} + +fun testParamType() { + val bar = fun (bal: String){} + + bar.checkType { it : _<(String) -> Unit> } + + val bas: (String) -> Unit = fun (param: String) {} + val bag: (Int) -> Unit = fun (param: String) {} +} + +fun testReceiverType() { + val bar = fun String.() {} + + bar.checkType { it : _ Unit> } + + val bas: String.() -> Unit = fun String.() {} + + val bag: Int.() -> Unit = fun String.() {} +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.txt b/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.txt new file mode 100644 index 00000000000..b67af8e0032 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.txt @@ -0,0 +1,5 @@ +package + +internal fun testParamType(): kotlin.Unit +internal fun testReceiverType(): kotlin.Unit +internal fun testReturnType(/*0*/ foo: kotlin.String): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.kt b/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.kt new file mode 100644 index 00000000000..b018c444f65 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +val bar = fun name() {} +val bas = fun name() {} + +fun gar(p: Any?) = fun name() {} +fun gas(p: Any?) = fun name() {} + +fun outer() { + val bar = fun name() {} + val bas = fun name() {} + + fun gar(p: Any?) = fun name() {} + fun gas(p: Any?) = fun name() {} + + gar(fun name() {}) + gar(fun name() {}) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.txt b/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.txt new file mode 100644 index 00000000000..92329d6ba5f --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.txt @@ -0,0 +1,7 @@ +package + +internal val bar: () -> kotlin.Unit +internal val bas: () -> kotlin.Unit +internal fun gar(/*0*/ p: kotlin.Any?): () -> kotlin.Unit +internal fun gas(/*0*/ p: kotlin.Any?): () -> kotlin.Unit +internal fun outer(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.kt b/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.kt new file mode 100644 index 00000000000..8b42597b6d2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +val bar = fun(p: Int = 3) {} +val bas = fun(vararg p: Int) {} + +fun gar() = fun(p: Int = 3) {} +fun gas() = fun(vararg p: Int) {} + +fun outer(b: Any?) { + val bar = fun(p: Int = 3) {} + val bas = fun(vararg p: Int) {} + + fun gar() = fun(p: Int = 3) {} + fun gas() = fun(vararg p: Int) {} + + outer(fun(p: Int = 3) {}) + outer(fun(vararg p: Int) {}) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.txt b/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.txt new file mode 100644 index 00000000000..3607b3c76b9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/Parameters.txt @@ -0,0 +1,7 @@ +package + +internal val bar: (kotlin.Int) -> kotlin.Unit +internal val bas: (kotlin.IntArray) -> kotlin.Unit +internal fun gar(): (kotlin.Int) -> kotlin.Unit +internal fun gas(): (kotlin.IntArray) -> kotlin.Unit +internal fun outer(/*0*/ b: kotlin.Any?): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.kt b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.kt new file mode 100644 index 00000000000..a3012dac7de --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.kt @@ -0,0 +1,13 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE + +val label_fun = @label fun () { + return@label +} + +val parenthesized_label_fun = (@label fun () { + return@label +}) + +val fun_with_name = fun name() { + return@name +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.txt b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.txt new file mode 100644 index 00000000000..ac8c8eb23c6 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.txt @@ -0,0 +1,5 @@ +package + +internal val fun_with_name: () -> kotlin.Unit +internal val label_fun: () -> kotlin.Unit +internal val parenthesized_label_fun: () -> kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.kt b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.kt new file mode 100644 index 00000000000..4aa91b35e10 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.kt @@ -0,0 +1,9 @@ +val foo = fun(a: Int): String { + if (a == 1) return "4" + when (a) { + 5 -> return "2" + 3 -> return null + 2 -> return 2 + } + return "" +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.txt b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.txt new file mode 100644 index 00000000000..92218499c94 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.txt @@ -0,0 +1,3 @@ +package + +internal val foo: (kotlin.Int) -> kotlin.String diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.kt b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.kt new file mode 100644 index 00000000000..108e658e5c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -UNUSED_VARIABLE + +trait B { + fun b_fun() {} +} + +fun test(param: String) { + + val local_val = 4 + val bar = fun B.(fun_param: Int) { + param.length() + b_fun() + val inner_bar = local_val + fun_param + + bar + } + + inner_bar + fun_param +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.txt b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.txt new file mode 100644 index 00000000000..0aefb08664b --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.txt @@ -0,0 +1,10 @@ +package + +internal fun test(/*0*/ param: kotlin.String): kotlin.Unit + +internal trait B { + internal open fun b_fun(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.kt b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.kt new file mode 100644 index 00000000000..8b9a0ddef15 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +trait A +fun devNull(a: Any?){} + +val generic_fun = fun(t: T): T = null!! +val extension_generic_fun = funT.(t: T): T = null!! + +fun fun_with_where() = fun T.(t: T): T where T: A {} + + +fun outer() { + devNull(fun () {}) + devNull(fun T.name() {}) + devNull(fun name(): T = null!!) + devNull(fun name(t: T) {}) + devNull(fun name() where T:A {}) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.txt b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.txt new file mode 100644 index 00000000000..b61c89d6898 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.txt @@ -0,0 +1,13 @@ +package + +internal val extension_generic_fun: [ERROR : T].(T) -> T +internal val generic_fun: (T) -> T +internal fun devNull(/*0*/ a: kotlin.Any?): kotlin.Unit +internal fun fun_with_where(): [ERROR : T].(T) -> T +internal fun outer(): kotlin.Unit + +internal trait A { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.kt b/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.kt new file mode 100644 index 00000000000..ae58e457603 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.kt @@ -0,0 +1,31 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE + +fun parameter() = fun (t: T) = t +fun receiver() = fun T.() = this +fun returnType() = fun (): T = null!! + +val T.fromVal: () -> T get() = fun (): T = this@fromVal + +fun devNull(a: Any?){} + +fun outer() { + fun parameter() = fun (t: T) = t + fun receiver() = fun T.() = this + fun returnType() = fun (): T = null!! + + devNull(fun (t: O) = t) + devNull(fun O.() = this) + devNull(fun (): O = null!!) +} + +class Outer { + fun parameter() = fun (t: T) = t + fun receiver() = fun T.() = this + fun returnType() = fun (): T = null!! + + init { + devNull(fun (t: O) = t) + devNull(fun O.() = this) + devNull(fun (): O = null!!) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.txt b/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.txt new file mode 100644 index 00000000000..0ae124cecd4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.txt @@ -0,0 +1,18 @@ +package + +internal val T.fromVal: () -> T +internal fun devNull(/*0*/ a: kotlin.Any?): kotlin.Unit +internal fun outer(): kotlin.Unit +internal fun parameter(): (T) -> T +internal fun receiver(): T.() -> T +internal fun returnType(): () -> T + +internal final class Outer { + public constructor Outer() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + internal final fun parameter(): (T) -> T + internal final fun receiver(): T.() -> T + internal final fun returnType(): () -> T + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.kt b/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.kt new file mode 100644 index 00000000000..f4e887edb4d --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.kt @@ -0,0 +1,12 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +annotation class ann +val bas = fun () + +fun bar(a: Any) = fun name() + +fun outer() { + bar(fun ()) + bar(fun name()) + bar([ann] fun name()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.txt b/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.txt new file mode 100644 index 00000000000..d0260cb3578 --- /dev/null +++ b/compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.txt @@ -0,0 +1,12 @@ +package + +internal val bas: () -> kotlin.Unit +internal fun bar(/*0*/ a: kotlin.Any): () -> kotlin.Unit +internal fun outer(): kotlin.Unit + +internal final annotation class ann : kotlin.Annotation { + public constructor ann() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 73c44d338ac..95b0e404e73 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -58,6 +58,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, + Tests.FunctionAsExpression.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, @@ -4607,6 +4608,81 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } } + @TestMetadata("compiler/testData/diagnostics/tests/functionAsExpression") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class FunctionAsExpression extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInFunctionAsExpression() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/functionAsExpression"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Common.kt") + public void testCommon() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/Common.kt"); + doTest(fileName); + } + + @TestMetadata("ForbiddenNonLocalReturn.kt") + public void testForbiddenNonLocalReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/ForbiddenNonLocalReturn.kt"); + doTest(fileName); + } + + @TestMetadata("FunctionType.kt") + public void testFunctionType() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/FunctionType.kt"); + doTest(fileName); + } + + @TestMetadata("NoOverloadError.kt") + public void testNoOverloadError() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/NoOverloadError.kt"); + doTest(fileName); + } + + @TestMetadata("Parameters.kt") + public void testParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/Parameters.kt"); + doTest(fileName); + } + + @TestMetadata("ReturnAndLabels.kt") + public void testReturnAndLabels() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/ReturnAndLabels.kt"); + doTest(fileName); + } + + @TestMetadata("ReturnTypeCheck.kt") + public void testReturnTypeCheck() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/ReturnTypeCheck.kt"); + doTest(fileName); + } + + @TestMetadata("ScopeCheck.kt") + public void testScopeCheck() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.kt"); + doTest(fileName); + } + + @TestMetadata("WithGenericParameters.kt") + public void testWithGenericParameters() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/WithGenericParameters.kt"); + doTest(fileName); + } + + @TestMetadata("WithOuterGeneric.kt") + public void testWithOuterGeneric() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/WithOuterGeneric.kt"); + doTest(fileName); + } + + @TestMetadata("WithoutBody.kt") + public void testWithoutBody() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionAsExpression/WithoutBody.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/functionLiterals") @TestDataPath("$PROJECT_ROOT") @InnerTestClasses({