New diagnostic error for ambiguous object expression type

This commit is contained in:
Mikhael Bogdanov
2013-02-18 18:31:40 +04:00
parent 1b2da6b558
commit 1662c5cb75
9 changed files with 395 additions and 19 deletions
@@ -229,6 +229,8 @@ public interface Errors {
DiagnosticFactory2<PsiElement, JetClassOrObject, CallableMemberDescriptor> MANY_IMPL_MEMBER_NOT_IMPLEMENTED =
DiagnosticFactory2.create(ERROR);
DiagnosticFactory1<JetNamedDeclaration, Collection<JetType>> AMBIGUOUS_ANONYMOUS_TYPE_INFERRED = DiagnosticFactory1.create(ERROR, NAMED_ELEMENT);
// Property-specific
DiagnosticFactory2<JetProperty, PropertyDescriptor, PropertyDescriptor> VAR_OVERRIDDEN_BY_VAL =
@@ -441,6 +441,8 @@ public class DefaultErrorMessages {
"Names of the parameter #{1} conflict in the following members of supertypes: ''{0}''" +
"This may cause problems when calling this function with named arguments.", commaSeparated(TO_STRING), TO_STRING);
MAP.put(AMBIGUOUS_ANONYMOUS_TYPE_INFERRED, "Right-hand side has anonymous type. Please specify type explicitly", TO_STRING);
MAP.setImmutable();
for (Field field : Errors.class.getFields()) {
@@ -245,10 +245,10 @@ public class DescriptorResolver {
@NotNull
public SimpleFunctionDescriptor resolveFunctionDescriptor(
DeclarationDescriptor containingDescriptor,
final JetScope scope,
final JetNamedFunction function,
final BindingTrace trace
@NotNull DeclarationDescriptor containingDescriptor,
@NotNull final JetScope scope,
@NotNull final JetNamedFunction function,
@NotNull final BindingTrace trace
) {
final SimpleFunctionDescriptorImpl functionDescriptor = new SimpleFunctionDescriptorImpl(
containingDescriptor,
@@ -296,7 +296,8 @@ public class DescriptorResolver {
@Override
protected JetType compute() {
//JetFlowInformationProvider flowInformationProvider = computeFlowData(function, bodyExpression);
return expressionTypingServices.inferFunctionReturnType(scope, function, functionDescriptor, trace);
JetType type = expressionTypingServices.inferFunctionReturnType(scope, function, functionDescriptor, trace);
return transformAnonymousTypeIfNeeded(functionDescriptor, function, type, trace);
}
});
}
@@ -736,7 +737,7 @@ public class DescriptorResolver {
);
JetType type =
getVariableType(scope, variable, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
getVariableType(propertyDescriptor, scope, variable, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
ReceiverParameterDescriptor receiverParameter = ((ScriptDescriptor) containingDeclaration).getThisAsReceiverParameter();
propertyDescriptor.setType(type, Collections.<TypeParameterDescriptor>emptyList(), receiverParameter, (JetType) null);
@@ -748,7 +749,7 @@ public class DescriptorResolver {
resolveLocalVariableDescriptorWithType(containingDeclaration, variable, null, trace);
JetType type =
getVariableType(scope, variable, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
getVariableType(variableDescriptor, scope, variable, dataFlowInfo, false, trace); // For a local variable the type must not be deferred
variableDescriptor.setOutType(type);
return variableDescriptor;
}
@@ -948,7 +949,7 @@ public class DescriptorResolver {
JetScope propertyScope = getPropertyDeclarationInnerScope(propertyDescriptor, scope, typeParameterDescriptors,
NO_RECEIVER_PARAMETER, trace);
JetType type = getVariableType(propertyScope, property, DataFlowInfo.EMPTY, true, trace);
JetType type = getVariableType(propertyDescriptor, propertyScope, property, DataFlowInfo.EMPTY, true, trace);
propertyDescriptor.setType(type, typeParameterDescriptors, getExpectedThisObjectIfNeeded(containingDeclaration),
receiverDescriptor);
@@ -980,6 +981,7 @@ public class DescriptorResolver {
@NotNull
private JetType getVariableType(
@NotNull final VariableDescriptor variableDescriptor,
@NotNull final JetScope scope,
@NotNull final JetVariableDeclaration variable,
@NotNull final DataFlowInfo dataFlowInfo,
@@ -997,17 +999,18 @@ public class DescriptorResolver {
return ErrorUtils.createErrorType("No type, no body");
}
else {
RecursionIntolerantLazyValue<JetType> lazyValue = new RecursionIntolerantLazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override
protected JetType compute() {
return expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace);
}
};
if (notLocal) {
return DeferredType.create(trace, lazyValue);
return DeferredType.create(trace, new RecursionIntolerantLazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
@Override
protected JetType compute() {
JetType type = resolveInitializerType(scope, initializer, dataFlowInfo, trace);
return transformAnonymousTypeIfNeeded(variableDescriptor, variable, type, trace);
}
});
}
else {
return lazyValue.get();
return resolveInitializerType(scope, initializer, dataFlowInfo, trace);
}
}
}
@@ -1016,6 +1019,46 @@ public class DescriptorResolver {
}
}
@Nullable
private JetType transformAnonymousTypeIfNeeded(
@NotNull DeclarationDescriptorWithVisibility descriptor,
@NotNull JetNamedDeclaration declaration,
@NotNull JetType type,
@NotNull final BindingTrace trace
) {
ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor();
boolean isAnonymous = classifierDescriptor != null && classifierDescriptor.getName().isSpecial() && !ErrorUtils.isErrorType(type);
if (!isAnonymous) {
return type;
}
boolean definedInClass = DescriptorUtils.getParentOfType(descriptor, ClassDescriptor.class) != null;
boolean isLocal = descriptor.getContainingDeclaration() instanceof CallableDescriptor;
Visibility visibility = descriptor.getVisibility();
boolean transformNeeded = !isLocal && !visibility.isPublicAPI()
&& !(definedInClass && Visibilities.PRIVATE.equals(visibility));
if (transformNeeded) {
if (type.getConstructor().getSupertypes().size() == 1) {
assert type.getArguments().isEmpty() : "Object expression couldn't have any type parameters!";
return type.getConstructor().getSupertypes().iterator().next();
}
else {
trace.report(AMBIGUOUS_ANONYMOUS_TYPE_INFERRED.on(declaration, type.getConstructor().getSupertypes()));
}
}
return type;
}
@NotNull
private JetType resolveInitializerType(
@NotNull JetScope scope,
@NotNull JetExpression initializer,
@NotNull final DataFlowInfo dataFlowInfo,
@NotNull BindingTrace trace
) {
return expressionTypingServices.safeGetType(scope, initializer, TypeUtils.NO_EXPECTED_TYPE, dataFlowInfo, trace);
}
@Nullable
private PropertySetterDescriptor resolvePropertySetterDescriptor(
@NotNull JetScope scope,
@@ -46,6 +46,7 @@ public class DeferredType implements JetType {
return lazyValue.isComputed();
}
@NotNull
public JetType getActualType() {
return lazyValue.get();
}
@@ -117,6 +117,7 @@ public class ExpressionTypingServices {
this.typeResolver = typeResolver;
}
@NotNull
public JetType safeGetType(@NotNull JetScope scope, @NotNull JetExpression expression, @NotNull JetType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) {
JetType type = getType(scope, expression, expectedType, dataFlowInfo, trace);
if (type != null) {
@@ -0,0 +1,117 @@
trait MyTrait {
fun f1() {}
}
open class MyClass {
fun f2() {}
}
class Foo {
private val privateProperty = object : MyClass(), MyTrait {}
{
privateProperty.f1()
privateProperty.f2()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected val protectedProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>val internalProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal val internal2Property<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val publicProperty<!> = object : MyClass(), MyTrait {}
private fun privateFunction() = object : MyClass(), MyTrait {}
{
privateFunction().f1()
privateFunction().f2()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected fun protectedFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>fun internalFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal fun internal2Function()<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun publicFunction()<!> = object : MyClass(), MyTrait {}
class FooInner {
private val privatePropertyInner = object : MyClass(), MyTrait {}
{
privatePropertyInner.f1()
privatePropertyInner.f2()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected val protectedProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>val internalProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal val internal2Property<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val publicProperty<!> = object : MyClass(), MyTrait {}
private fun privateFunctionInner() = object : MyClass(), MyTrait {}
{
privateFunctionInner().f1()
privateFunctionInner().f2()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected fun protectedFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>fun internalFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal fun internal2Function()<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun publicFunction()<!> = object : MyClass(), MyTrait {}
}
fun foo() {
val localVar = object : MyClass(), MyTrait {}
localVar.f1()
localVar.f2()
fun foo2() = object : MyClass(), MyTrait {}
foo2().f1()
foo2().f2()
}
}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>private val packagePrivateProperty<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!><!PACKAGE_MEMBER_CANNOT_BE_PROTECTED!>protected<!> val packageProtectedProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>val packageInternalProperty<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal val packageInternal2Property<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val packagePublicProperty<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!><!PACKAGE_MEMBER_CANNOT_BE_PROTECTED!>protected<!> fun packageProtectedFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>fun packageInternalFunction()<!> = object : MyClass(), MyTrait {}
<!AMBIGUOUS_ANONYMOUS_TYPE_INFERRED!>internal fun packageInternal2Function()<!> = object : MyClass(), MyTrait {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun packagePublicFunction()<!> = object : MyClass(), MyTrait {}
fun fooPackage() {
val packageLocalVar = object : MyClass(), MyTrait {}
packageLocalVar.f1()
packageLocalVar.f2()
fun fooPackageLocal() = object : MyClass(), MyTrait {}
fooPackageLocal().f1()
fooPackageLocal().f2()
}
@@ -0,0 +1,200 @@
open class MyClass {
fun f1() {}
}
class Foo {
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected val protectedProperty<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val publicProperty<!> = object : MyClass() {}
protected val protected2Property : MyClass = object : MyClass() {fun invisible() {}}
public val public2Property : MyClass = object : MyClass() {fun invisible() {}}
private val privateProperty = object : MyClass() {fun visible() {}}
val internalProperty = object : MyClass() { fun invisible() {}}
internal val internal2Property = object : MyClass() {fun invisible() {}}
fun testProperties() {
privateProperty.f1()
internalProperty.f1()
internal2Property.f1()
protected2Property.f1()
public2Property.f1()
privateProperty.visible()
protected2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
public2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
internalProperty.<!UNRESOLVED_REFERENCE!>invisible<!>()
internal2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected fun protectedFunction()<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun publicFunction()<!> = object : MyClass() {}
protected fun protected2Function(): MyClass = object : MyClass() {fun visible() {}}
public fun public2Function(): MyClass = object : MyClass() {fun visible() {}}
private fun privateFunction() = object : MyClass() {fun visible() {}}
fun internalFunction() = object : MyClass() {fun invisible() {}}
internal fun internal2Function() = object : MyClass() {fun invisible() {}}
fun testFunctions() {
privateFunction().f1()
internalFunction().f1()
internal2Function().f1()
public2Function().f1()
protected2Function().f1()
privateFunction().visible()
internalFunction().<!UNRESOLVED_REFERENCE!>invisible<!>()
internal2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
public2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
protected2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
}
class FooInner {
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val publicProperty<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected val protectedProperty<!> = object : MyClass() {}
protected val protected2Property : MyClass = object : MyClass() {fun invisible() {}}
public val public2Property : MyClass = object : MyClass() {fun invisible() {}}
private val privateProperty = object : MyClass() {fun visible() {}}
val internalProperty = object : MyClass() { fun invisible() {}}
internal val internal2Property = object : MyClass() {fun invisible() {}}
fun testProperties() {
privateProperty.f1()
internalProperty.f1()
internal2Property.f1()
protected2Property.f1()
public2Property.f1()
privateProperty.visible()
protected2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
public2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
internalProperty.<!UNRESOLVED_REFERENCE!>invisible<!>()
internal2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>protected fun protectedFunction()<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun publicFunction()<!> = object : MyClass() {}
protected fun protected2Function(): MyClass = object : MyClass() {fun visible() {}}
public fun public2Function(): MyClass = object : MyClass() {fun visible() {}}
private fun privateFunction() = object : MyClass() {fun visible() {}}
fun internalFunction() = object : MyClass() {fun invisible() {}}
internal fun internal2Function() = object : MyClass() {fun invisible() {}}
fun testFunctions() {
privateFunction().f1()
internalFunction().f1()
internal2Function().f1()
public2Function().f1()
protected2Function().f1()
privateFunction().visible()
internalFunction().<!UNRESOLVED_REFERENCE!>invisible<!>()
internal2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
public2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
protected2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
}
}
fun foo() {
val localVar = object : MyClass() {}
localVar.f1()
fun foo2() = object : MyClass() {}
foo2().f1()
}
}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!><!PACKAGE_MEMBER_CANNOT_BE_PROTECTED!>protected<!> val packageProtectedProperty<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public val packagePublicProperty<!> = object : MyClass() {}
public val packagePublic2Property : MyClass = object : MyClass() {fun invisible() {}}
private val packagePrivateProperty = object : MyClass() {fun invisible() {}}
val packageInternalProperty = object : MyClass() {fun invisible() {}}
internal val packageInternal2Property = object : MyClass() {fun invisible() {}}
fun testProperties() {
packagePrivateProperty.f1()
packageInternalProperty.f1()
packageInternal2Property.f1()
packagePublic2Property.f1()
packagePrivateProperty.<!UNRESOLVED_REFERENCE!>invisible<!>()
packageInternalProperty.<!UNRESOLVED_REFERENCE!>invisible<!>()
packageInternal2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
packagePublic2Property.<!UNRESOLVED_REFERENCE!>invisible<!>()
}
private fun privateFunction() = object : MyClass() {fun invisible() {}}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!><!PACKAGE_MEMBER_CANNOT_BE_PROTECTED!>protected<!> fun protectedFunction()<!> = object : MyClass() {}
<!PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE!>public fun publicFunction()<!> = object : MyClass() {}
public fun public2Function() : MyClass = object : MyClass() {fun invisible() {}}
fun internalFunction() = object : MyClass() {fun invisible() {}}
internal fun internal2Function() = object : MyClass() {fun invisible() {}}
fun testFunctions() {
privateFunction().f1()
internalFunction().f1()
internal2Function().f1()
public2Function().f1()
privateFunction().<!UNRESOLVED_REFERENCE!>invisible<!>()
internalFunction().<!UNRESOLVED_REFERENCE!>invisible<!>()
internal2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
public2Function().<!UNRESOLVED_REFERENCE!>invisible<!>()
}
fun fooPackage() {
val packageLocalVar = object : MyClass() {fun visible() {}}
packageLocalVar.f1()
packageLocalVar.visible()
fun fooPackageLocal() = object : MyClass() {fun visible() {}}
fooPackageLocal().f1()
fooPackageLocal().visible()
}
@@ -1453,6 +1453,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/declarationChecks"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("ambiguousObjectExpressionType.kt")
public void testAmbiguousObjectExpressionType() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/ambiguousObjectExpressionType.kt");
}
@TestMetadata("ComponentFunctionReturnTypeMismatch.kt")
public void testComponentFunctionReturnTypeMismatch() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt");
@@ -1548,6 +1553,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/declarationChecks/RedeclarationsInMultiDecl.kt");
}
@TestMetadata("unambiguousObjectExpressionType.kt")
public void testUnambiguousObjectExpressionType() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/unambiguousObjectExpressionType.kt");
}
@TestMetadata("valVarFunctionParameter.kt")
public void testValVarFunctionParameter() throws Exception {
doTest("compiler/testData/diagnostics/tests/declarationChecks/valVarFunctionParameter.kt");
@@ -92,15 +92,15 @@ public class OuterClassGenTest extends CodegenTestCase {
private void checkInfo(ClassReader kotlinReader, ClassReader javaReader) {
String [] kotlinInfo = getOuterClasInfo(kotlinReader);
String [] javaInfo = getOuterClasInfo(javaReader);
String [] kotlinInfo = getOuterClassInfo(kotlinReader);
String [] javaInfo = getOuterClassInfo(javaReader);
for (int i = 0; i < kotlinInfo.length; i++) {
String info = kotlinInfo[i];
assertEquals("Error in enclosingMethodInfo info for: " + kotlinReader.getClassName() + " class in " + INFO_PARTS[i] + " part", javaInfo[i], info);
}
}
public String [] getOuterClasInfo(ClassReader reader) {
public String [] getOuterClassInfo(ClassReader reader) {
final String [] info = new String [3];
reader.accept(new ClassVisitor(Opcodes.ASM4) {
@Override