diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 7c73081a3de..e99ea7f7d38 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -201,6 +201,7 @@ public interface Errors { SimpleDiagnosticFactory NO_THIS = SimpleDiagnosticFactory.create(ERROR, "'this' is not defined in this context"); SimpleDiagnosticFactory SUPER_NOT_AVAILABLE = SimpleDiagnosticFactory.create(ERROR, "No supertypes are accessible in this context"); SimpleDiagnosticFactory AMBIGUOUS_SUPER = SimpleDiagnosticFactory.create(ERROR, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super'"); + SimpleDiagnosticFactory ABSTRACT_SUPER_CALL = SimpleDiagnosticFactory.create(ERROR, "Abstarct member cannot be accessed directly"); SimpleDiagnosticFactory NOT_A_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "Not a supertype"); SimpleDiagnosticFactory TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = SimpleDiagnosticFactory.create(WARNING, "Type arguments do not need to be specified in a 'super' qualifier"); SimpleDiagnosticFactory NO_WHEN_ENTRIES = SimpleDiagnosticFactory.create(ERROR, "Entries are required for when-expression"); // TODO : Scope, and maybe this should not be an error diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 1bb016f799e..7c9d7bf03ba 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -579,7 +579,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { public JetType getSelectorReturnType(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression selectorExpression, @NotNull ExpressionTypingContext context) { if (selectorExpression instanceof JetCallExpression) { JetCallExpression callExpression = (JetCallExpression) selectorExpression; - return context.resolveCall(receiver, callOperationNode, callExpression); + FunctionDescriptor functionDescriptor = context.resolveCall(receiver, callOperationNode, callExpression); + checkSuper(receiver, functionDescriptor, context.trace, selectorExpression); + return functionDescriptor != null ? functionDescriptor.getReturnType() : null; } else if (selectorExpression instanceof JetSimpleNameExpression) { JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) selectorExpression; @@ -588,7 +590,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { OverloadResolutionResults resolutionResult = context.replaceBindingTrace(temporaryTrace).resolveSimpleProperty(receiver, callOperationNode, nameExpression); if (resolutionResult.isSuccess()) { temporaryTrace.commit(); - return resolutionResult.getResultingDescriptor().getOutType(); + VariableDescriptor resultingDescriptor = resolutionResult.getResultingDescriptor(); + checkSuper(receiver, resultingDescriptor, context.trace, selectorExpression); + return resultingDescriptor.getOutType(); } if (resolutionResult.isAmbiguity()) { temporaryTrace.commit(); @@ -615,10 +619,21 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } return null; } + + private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @Nullable DeclarationDescriptor member, @NotNull BindingTrace trace, @NotNull JetExpression expression) { + if (!(receiverDescriptor instanceof ExpressionReceiver)) return; + JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression(); + if (receiver instanceof JetSuperExpression && member instanceof MemberDescriptor) { + if (((MemberDescriptor) member).getModality() == Modality.ABSTRACT) { + trace.report(ABSTRACT_SUPER_CALL.on(expression)); + } + } + } @Override public JetType visitCallExpression(JetCallExpression expression, ExpressionTypingContext context) { - JetType expressionType = context.resolveCall(NO_RECEIVER, null, expression); + FunctionDescriptor functionDescriptor = context.resolveCall(NO_RECEIVER, null, expression); + JetType expressionType = functionDescriptor != null ? functionDescriptor.getReturnType() : null; return DataFlowUtils.checkType(expressionType, expression, context); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index a6116fc2852..00cd93ac445 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -4,6 +4,7 @@ import com.intellij.lang.ASTNode; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; @@ -182,9 +183,9 @@ import java.util.Map; } @Nullable - public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { + public FunctionDescriptor resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) { OverloadResolutionResults results = getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType); - return results.singleResult() ? results.getResultingDescriptor().getReturnType() : null; + return results.singleResult() ? results.getResultingDescriptor() : null; } @NotNull diff --git a/compiler/testData/diagnostics/tests/declarationChecks/kt559.jet b/compiler/testData/diagnostics/tests/declarationChecks/kt559.jet new file mode 100644 index 00000000000..1512c64bd0d --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/kt559.jet @@ -0,0 +1,30 @@ +//KT-559 Forbid abstract method call through super + +package kt559 + +abstract class A { + abstract val i : Int + + abstract fun foo() : Int + + fun fff() {} +} + +abstract class D(): A() { + override val i : Int = 34 +} + +class C() : D() { + fun test() { + super.i + } +} + +class B() : A() { + override fun foo(): Int { + super.i + + super.fff() //everything is ok + return super.foo() //no error!! + } +} \ No newline at end of file