Merge branch 'master' of ssh://git.labs.intellij.net/jet
This commit is contained in:
@@ -1813,23 +1813,25 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
JetType jetType = bindingContext.get(BindingContext.TYPE, typeReference);
|
||||
assert jetType != null;
|
||||
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
|
||||
if (!(descriptor instanceof ClassDescriptor)) {
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
||||
}
|
||||
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
||||
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
|
||||
Label isInstance = new Label();
|
||||
v.ifne(isInstance);
|
||||
v.pop();
|
||||
if (opToken == JetTokens.AS_SAFE) {
|
||||
v.aconst(null);
|
||||
if (descriptor instanceof ClassDescriptor || descriptor instanceof TypeParameterDescriptor) {
|
||||
Type type = JetTypeMapper.boxType(typeMapper.mapType(jetType));
|
||||
generateInstanceOf(StackValue.expression(OBJECT_TYPE, expression.getLeft(), this), jetType, true);
|
||||
Label isInstance = new Label();
|
||||
v.ifne(isInstance);
|
||||
v.pop();
|
||||
if (opToken == JetTokens.AS_SAFE) {
|
||||
v.aconst(null);
|
||||
}
|
||||
else {
|
||||
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
|
||||
}
|
||||
v.mark(isInstance);
|
||||
v.checkcast(type);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
else {
|
||||
throwNewException(CLASS_TYPE_CAST_EXCEPTION);
|
||||
throw new UnsupportedOperationException("don't know how to handle non-class types in as/as?");
|
||||
}
|
||||
v.mark(isInstance);
|
||||
v.checkcast(type);
|
||||
return StackValue.onStack(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1962,7 +1964,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateTypeInfo(JetType jetType) {
|
||||
void generateTypeInfo(JetType jetType) {
|
||||
String knownTypeInfo = typeMapper.isKnownTypeInfo(jetType);
|
||||
if(knownTypeInfo != null) {
|
||||
v.getstatic("jet/typeinfo/TypeInfo", knownTypeInfo, "Ljet/typeinfo/TypeInfo;");
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeProjection;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
@@ -109,7 +110,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
protected void getSuperClass() {
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||
|
||||
if(myClass instanceof JetClass && ((JetClass)myClass).isTrait())
|
||||
if(myClass instanceof JetClass && ((JetClass) myClass).isTrait())
|
||||
return;
|
||||
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
@@ -150,6 +151,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
generateGetTypeInfo();
|
||||
//genGetSuperTypesTypeInfo();
|
||||
}
|
||||
|
||||
private void generateFieldForTypeInfo() {
|
||||
@@ -240,6 +242,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
final InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, Type.VOID_TYPE, context, state);
|
||||
|
||||
for(int slot = 0; slot != frameMap.getTypeParameterCount(); ++slot) {
|
||||
codegen.addTypeParameter(constructorDescriptor.getTypeParameters().get(slot), StackValue.local(frameMap.getFirstTypeParameter() + slot, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
String classname = state.getTypeMapper().jvmName(descriptor, kind);
|
||||
final Type classType = Type.getType("L" + classname + ";");
|
||||
|
||||
@@ -348,7 +354,15 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
reg += argType.getSize();
|
||||
}
|
||||
|
||||
String fdescriptor = function.getDescriptor().replace("(","(L" + state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(),OwnerKind.IMPLEMENTATION) + ";");
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) fun.getContainingDeclaration();
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, state.getBindingContext());
|
||||
Type type = state.getTypeMapper().mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = containingDeclaration.getDefaultType();
|
||||
type = state.getTypeMapper().mapType(jetType);
|
||||
}
|
||||
|
||||
String fdescriptor = function.getDescriptor().replace("(","(" + type.getDescriptor());
|
||||
iv.invokestatic(state.getTypeMapper().jvmName((ClassDescriptor) fun.getContainingDeclaration(), OwnerKind.TRAIT_IMPL), function.getName(), fdescriptor);
|
||||
iv.areturn(function.getReturnType());
|
||||
mv.visitMaxs(0, 0);
|
||||
@@ -530,7 +544,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
iv.dup();
|
||||
iv.iconst(i);
|
||||
iv.load(firstTypeParameter + i, JetTypeMapper.TYPE_OBJECT);
|
||||
ExpressionCodegen.genTypeInfoToProjection(iv, Variance.INVARIANT);
|
||||
iv.checkcast(JetTypeMapper.TYPE_TYPEINFOPROJECTION);
|
||||
iv.astore(JetTypeMapper.TYPE_OBJECT);
|
||||
}
|
||||
iv.invokestatic("jet/typeinfo/TypeInfo", "getTypeInfo", "(Ljava/lang/Class;Z[Ljet/typeinfo/TypeInfoProjection;)Ljet/typeinfo/TypeInfo;");
|
||||
@@ -648,4 +662,50 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generateClassObject(JetClassObject declaration) {
|
||||
state.forClass().generate(context, declaration.getObjectDeclaration());
|
||||
}
|
||||
|
||||
private void genGetSuperTypesTypeInfo() {
|
||||
if(!(myClass instanceof JetClass) || ((JetClass)myClass).isTrait()) {
|
||||
return;
|
||||
}
|
||||
|
||||
String sig = getGetSuperTypesTypeInfoSignature(descriptor.getDefaultType());
|
||||
|
||||
final MethodVisitor mv = v.visitMethod(Opcodes.ACC_PUBLIC|Opcodes.ACC_STATIC,
|
||||
"$$getSuperTypesTypeInfo",
|
||||
sig,
|
||||
null /* TODO */,
|
||||
null);
|
||||
mv.visitCode();
|
||||
InstructionAdapter v = new InstructionAdapter(mv);
|
||||
|
||||
ExpressionCodegen codegen = new ExpressionCodegen(v, new FrameMap(), Type.VOID_TYPE, context, state);
|
||||
|
||||
v.load(0, JetTypeMapper.TYPE_OBJECT);
|
||||
|
||||
int k = 1;
|
||||
for (TypeParameterDescriptor parameterDescriptor : descriptor.getTypeConstructor().getParameters()) {
|
||||
codegen.addTypeParameter(parameterDescriptor, StackValue.local(k++, JetTypeMapper.TYPE_TYPEINFO));
|
||||
}
|
||||
|
||||
for(JetType superType : descriptor.getTypeConstructor().getSupertypes()) {
|
||||
for (TypeProjection typeProjection : superType.getArguments()) {
|
||||
codegen.generateTypeInfo(typeProjection.getType());
|
||||
}
|
||||
v.invokestatic(state.getTypeMapper().mapType(superType).getInternalName(), "$$getSuperTypesTypeInfo", getGetSuperTypesTypeInfoSignature(superType));
|
||||
}
|
||||
|
||||
v.areturn(Type.VOID_TYPE);
|
||||
mv.visitMaxs(0, 0);
|
||||
mv.visitEnd();
|
||||
}
|
||||
|
||||
private static String getGetSuperTypesTypeInfoSignature(JetType type) {
|
||||
List<TypeParameterDescriptor> typeParameters = type.getConstructor().getParameters();
|
||||
StringBuilder sb = new StringBuilder("(Ljava/util/Set;");
|
||||
for(TypeParameterDescriptor tp : typeParameters)
|
||||
sb.append("Ljet/typeinfo/TypeInfo;");
|
||||
sb.append(")V");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,8 +439,13 @@ public class JetTypeMapper {
|
||||
}
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(BindingContext.FUNCTION, f);
|
||||
if(kind == OwnerKind.TRAIT_IMPL) {
|
||||
JetType jetType = ((ClassDescriptor)functionDescriptor.getContainingDeclaration()).getDefaultType();
|
||||
final Type type = mapType(jetType);
|
||||
ClassDescriptor containingDeclaration = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
|
||||
JetType jetType = TraitImplBodyCodegen.getSuperClass(containingDeclaration, bindingContext);
|
||||
Type type = mapType(jetType);
|
||||
if(type.getInternalName().equals("java/lang/Object")) {
|
||||
jetType = containingDeclaration.getDefaultType();
|
||||
type = mapType(jetType);
|
||||
}
|
||||
valueParameterTypes.add(type);
|
||||
parameterTypes.add(type);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclaration;
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.objectweb.asm.ClassVisitor;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -16,6 +18,33 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
super(aClass, context, v, state);
|
||||
}
|
||||
|
||||
//todo not needed when frontend will be able to calculate properly
|
||||
static JetType getSuperClass(ClassDescriptor myClassDescr, BindingContext bindingContext) {
|
||||
JetClassOrObject myClass = (JetClassOrObject) bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, myClassDescr);
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = myClass.getDelegationSpecifiers();
|
||||
|
||||
for (JetDelegationSpecifier specifier : delegationSpecifiers) {
|
||||
if (specifier instanceof JetDelegatorToSuperClass || specifier instanceof JetDelegatorToSuperCall) {
|
||||
JetType superType = bindingContext.get(BindingContext.TYPE, specifier.getTypeReference());
|
||||
ClassDescriptor superClassDescriptor = (ClassDescriptor) superType.getConstructor().getDeclarationDescriptor();
|
||||
final PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, superClassDescriptor);
|
||||
if (declaration != null) {
|
||||
if (declaration instanceof PsiClass) {
|
||||
if (!((PsiClass) declaration).isInterface()) {
|
||||
return superClassDescriptor.getDefaultType();
|
||||
}
|
||||
}
|
||||
else if(declaration instanceof JetClass) {
|
||||
if(!((JetClass) declaration).isTrait()) {
|
||||
return superClassDescriptor.getDefaultType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
v.visit(Opcodes.V1_6,
|
||||
|
||||
@@ -26,6 +26,11 @@ public interface FunctionGroup extends Named {
|
||||
public Set<FunctionDescriptor> getFunctionDescriptors() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "EMPTY";
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -42,7 +42,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
super(containingDeclaration);
|
||||
this.scopeForMemberLookup = new WritableScopeImpl(JetScope.EMPTY, this, trace.getErrorHandler()).setDebugName("MemberLookup");
|
||||
this.scopeForSupertypeResolution = new WritableScopeImpl(outerScope, this, trace.getErrorHandler()).setDebugName("SupertypeResolution");
|
||||
this.scopeForMemberResolution = new WritableScopeImpl(new ChainedScope(this, scopeForMemberLookup, scopeForSupertypeResolution), this, trace.getErrorHandler()).setDebugName("MemberResolution");
|
||||
this.scopeForMemberResolution = new WritableScopeImpl(scopeForSupertypeResolution, this, trace.getErrorHandler()).setDebugName("MemberResolution");
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
properties.add(propertyDescriptor);
|
||||
scopeForMemberLookup.addVariableDescriptor(propertyDescriptor);
|
||||
scopeForMemberResolution.addVariableDescriptor(propertyDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -98,6 +99,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
|
||||
functions.add(functionDescriptor);
|
||||
scopeForMemberLookup.addFunctionDescriptor(functionDescriptor);
|
||||
scopeForMemberResolution.addFunctionDescriptor(functionDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -118,6 +120,7 @@ public class MutableClassDescriptor extends MutableDeclarationDescriptor impleme
|
||||
@Override
|
||||
public void addClassifierDescriptor(@NotNull MutableClassDescriptor classDescriptor) {
|
||||
scopeForMemberLookup.addClassifierDescriptor(classDescriptor);
|
||||
scopeForMemberResolution.addClassifierDescriptor(classDescriptor);
|
||||
}
|
||||
|
||||
public void addSupertype(@NotNull JetType supertype) {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package org.jetbrains.jet.lang.parsing;
|
||||
|
||||
import com.intellij.lang.java.parser.JavaParserUtil.PsiBuilderAdapter;
|
||||
import com.intellij.lang.impl.PsiBuilderAdapter;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ package org.jetbrains.jet.lang.parsing;
|
||||
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.java.parser.JavaParserUtil.PsiBuilderAdapter;
|
||||
import com.intellij.lang.impl.PsiBuilderAdapter;
|
||||
import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
@@ -41,89 +41,6 @@ public class ClassDescriptorResolver {
|
||||
this.annotationResolver = new AnnotationResolver(semanticServices, trace);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor resolveClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement) {
|
||||
final ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
|
||||
scope.getContainingDeclaration(),
|
||||
annotationResolver.resolveAnnotations(scope, classElement.getModifierList()),
|
||||
JetPsiUtil.safeName(classElement.getName()));
|
||||
|
||||
trace.record(BindingContext.CLASS, classElement, classDescriptor);
|
||||
|
||||
final WritableScope parameterScope = new WritableScopeImpl(scope, classDescriptor, trace.getErrorHandler());
|
||||
|
||||
// This call has side-effects on the parameterScope (fills it in)
|
||||
List<TypeParameterDescriptor> typeParameters
|
||||
= resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters());
|
||||
resolveGenericBounds(classElement, parameterScope, typeParameters);
|
||||
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = classElement.getDelegationSpecifiers();
|
||||
// TODO : assuming that the hierarchy is acyclic
|
||||
Collection<JetType> supertypes = delegationSpecifiers.isEmpty()
|
||||
? Collections.singleton(JetStandardClasses.getAnyType())
|
||||
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
|
||||
// for (JetType supertype: supertypes) {
|
||||
// if (supertype.getConstructor().isSealed()) {
|
||||
// trace.getErrorHandler().genericError(classElement.getNameAsDeclaration().getNode(), "Class " + classElement.getName() + " can not extend final type " + supertype);
|
||||
// }
|
||||
// }
|
||||
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
|
||||
|
||||
final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, trace.getErrorHandler());
|
||||
|
||||
List<JetDeclaration> declarations = classElement.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitProperty(JetProperty property) {
|
||||
if (property.getPropertyTypeRef() != null) {
|
||||
memberDeclarations.addVariableDescriptor(resolvePropertyDescriptor(classDescriptor, parameterScope, property));
|
||||
} else {
|
||||
// TODO : Caution: a cyclic dependency possible
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(JetNamedFunction function) {
|
||||
if (function.getReturnTypeRef() != null) {
|
||||
memberDeclarations.addFunctionDescriptor(resolveFunctionDescriptor(classDescriptor, parameterScope, function));
|
||||
} else {
|
||||
// TODO : Caution: a cyclic dependency possible
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
throw new UnsupportedOperationException(element.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
||||
classDescriptor.initialize(
|
||||
!open,
|
||||
typeParameters,
|
||||
supertypes,
|
||||
memberDeclarations,
|
||||
constructors,
|
||||
null
|
||||
);
|
||||
for (JetConstructor constructor : classElement.getSecondaryConstructors()) {
|
||||
ConstructorDescriptorImpl functionDescriptor = resolveSecondaryConstructorDescriptor(memberDeclarations, classDescriptor, constructor);
|
||||
functionDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
constructors.addFunction(functionDescriptor);
|
||||
}
|
||||
ConstructorDescriptorImpl primaryConstructorDescriptor = resolvePrimaryConstructorDescriptor(scope, classDescriptor, classElement);
|
||||
if (primaryConstructorDescriptor != null) {
|
||||
primaryConstructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
constructors.addFunction(primaryConstructorDescriptor);
|
||||
classDescriptor.setPrimaryConstructor(primaryConstructorDescriptor);
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
public void resolveMutableClassDescriptor(@NotNull JetClass classElement, @NotNull MutableClassDescriptor descriptor) {
|
||||
// TODO : Where-clause
|
||||
List<TypeParameterDescriptor> typeParameters = Lists.newArrayList();
|
||||
@@ -398,7 +315,7 @@ public class ClassDescriptorResolver {
|
||||
return jetType;
|
||||
}
|
||||
|
||||
private Collection<JetType> resolveDelegationSpecifiers(JetScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers, @NotNull TypeResolver resolver) {
|
||||
public Collection<JetType> resolveDelegationSpecifiers(JetScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers, @NotNull TypeResolver resolver) {
|
||||
if (delegationSpecifiers.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -15,7 +18,9 @@ public class SubstitutingScope implements JetScope {
|
||||
|
||||
private final JetScope workerScope;
|
||||
private final TypeSubstitutor substitutor;
|
||||
private Collection<DeclarationDescriptor> allDescriptors;
|
||||
|
||||
private Map<String, FunctionGroup> functionGroups = null;
|
||||
private Collection<DeclarationDescriptor> allDescriptors = null;
|
||||
|
||||
public SubstitutingScope(JetScope workerScope, @NotNull TypeSubstitutor substitutor) {
|
||||
this.workerScope = workerScope;
|
||||
@@ -58,11 +63,27 @@ public class SubstitutingScope implements JetScope {
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionGroup getFunctionGroup(@NotNull String name) {
|
||||
FunctionGroup functionGroup = workerScope.getFunctionGroup(name);
|
||||
if (substitutor.isEmpty() || functionGroup.isEmpty()) {
|
||||
return functionGroup;
|
||||
if (substitutor.isEmpty()) {
|
||||
return workerScope.getFunctionGroup(name);
|
||||
}
|
||||
return new LazySubstitutingFunctionGroup(substitutor, functionGroup);
|
||||
if (functionGroups == null) {
|
||||
functionGroups = Maps.newHashMap();
|
||||
}
|
||||
FunctionGroup cachedGroup = functionGroups.get(name);
|
||||
if (cachedGroup != null) {
|
||||
return cachedGroup;
|
||||
}
|
||||
|
||||
FunctionGroup functionGroup = workerScope.getFunctionGroup(name);
|
||||
FunctionGroup result;
|
||||
if (functionGroup.isEmpty()) {
|
||||
result = FunctionGroup.EMPTY;
|
||||
}
|
||||
else {
|
||||
result = new LazySubstitutingFunctionGroup(substitutor, functionGroup);
|
||||
}
|
||||
functionGroups.put(name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -291,7 +291,4 @@ public class TypeHierarchyResolver {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -472,17 +472,9 @@ public class CallResolver {
|
||||
|
||||
@NotNull
|
||||
private <Descriptor extends CallableDescriptor> OverloadResolutionResult<Descriptor> computeResultAndReportErrors(BindingTrace trace, TracingStrategy tracing, Map<Descriptor, Descriptor> successfulCandidates, Set<Descriptor> failedCandidates, Set<Descriptor> dirtyCandidates, Map<Descriptor, TemporaryBindingTrace> traces) {
|
||||
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
|
||||
if (successfulCandidates.size() > 0) {
|
||||
if (successfulCandidates.size() == 1) {
|
||||
Map.Entry<Descriptor, Descriptor> entry = successfulCandidates.entrySet().iterator().next();
|
||||
Descriptor functionDescriptor = entry.getKey();
|
||||
Descriptor result = entry.getValue();
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.success(result);
|
||||
}
|
||||
else {
|
||||
if (successfulCandidates.size() != 1) {
|
||||
Map<Descriptor, Descriptor> cleanCandidates = Maps.newLinkedHashMap(successfulCandidates);
|
||||
cleanCandidates.keySet().removeAll(dirtyCandidates);
|
||||
if (cleanCandidates.isEmpty()) {
|
||||
@@ -498,37 +490,41 @@ public class CallResolver {
|
||||
return OverloadResolutionResult.success(maximallySpecificGenericsDiscriminated);
|
||||
}
|
||||
|
||||
Set<Descriptor> noOverrides = filterOverrides(successfulCandidates.keySet());
|
||||
if (dirtyCandidates.isEmpty()) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Descriptor functionDescriptor : successfulCandidates.keySet()) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append(" ");
|
||||
}
|
||||
|
||||
tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: " + stringBuilder);
|
||||
tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: "
|
||||
+ makeErrorMessageForMultipleDescriptors(noOverrides));
|
||||
}
|
||||
|
||||
tracing.recordAmbiguity(trace, successfulCandidates.keySet());
|
||||
|
||||
return OverloadResolutionResult.ambiguity(successfulCandidates.keySet());
|
||||
|
||||
tracing.recordAmbiguity(trace, noOverrides);
|
||||
|
||||
return OverloadResolutionResult.ambiguity(noOverrides);
|
||||
}
|
||||
else {
|
||||
Map.Entry<Descriptor, Descriptor> entry = successfulCandidates.entrySet().iterator().next();
|
||||
Descriptor functionDescriptor = entry.getKey();
|
||||
Descriptor result = entry.getValue();
|
||||
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.success(result);
|
||||
}
|
||||
}
|
||||
else if (!failedCandidates.isEmpty()) {
|
||||
if (failedCandidates.size() == 1) {
|
||||
Descriptor functionDescriptor = failedCandidates.iterator().next();
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.singleFailedCandidate(failedCandidates.iterator().next());
|
||||
}
|
||||
else {
|
||||
StringBuilder stringBuilder = new StringBuilder("\n");
|
||||
for (Descriptor functionDescriptor : failedCandidates) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append("\n");
|
||||
if (failedCandidates.size() != 1) {
|
||||
Set<Descriptor> noOverrides = filterOverrides(failedCandidates);
|
||||
if (noOverrides.size() != 1) {
|
||||
tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: "
|
||||
+ makeErrorMessageForMultipleDescriptors(noOverrides));
|
||||
tracing.recordAmbiguity(trace, noOverrides);
|
||||
return OverloadResolutionResult.manyFailedCandidates(noOverrides);
|
||||
}
|
||||
|
||||
tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: " + stringBuilder);
|
||||
tracing.recordAmbiguity(trace, failedCandidates);
|
||||
return OverloadResolutionResult.manyFailedCandidates(failedCandidates);
|
||||
failedCandidates = noOverrides;
|
||||
}
|
||||
Descriptor functionDescriptor = failedCandidates.iterator().next();
|
||||
TemporaryBindingTrace temporaryTrace = traces.get(functionDescriptor);
|
||||
temporaryTrace.commit();
|
||||
return OverloadResolutionResult.singleFailedCandidate(failedCandidates.iterator().next());
|
||||
}
|
||||
else {
|
||||
tracing.reportUnresolvedReference(trace);
|
||||
@@ -536,6 +532,28 @@ public class CallResolver {
|
||||
}
|
||||
}
|
||||
|
||||
private <Descriptor extends CallableDescriptor> StringBuilder makeErrorMessageForMultipleDescriptors(Set<Descriptor> candidates) {
|
||||
StringBuilder stringBuilder = new StringBuilder("\n");
|
||||
for (Descriptor functionDescriptor : candidates) {
|
||||
stringBuilder.append(DescriptorRenderer.TEXT.render(functionDescriptor)).append("\n");
|
||||
}
|
||||
return stringBuilder;
|
||||
}
|
||||
|
||||
private <Descriptor extends CallableDescriptor> Set<Descriptor> filterOverrides(Set<Descriptor> candidateSet) {
|
||||
Set<Descriptor> candidates = Sets.newLinkedHashSet();
|
||||
outerLoop:
|
||||
for (Descriptor me : candidateSet) {
|
||||
for (Descriptor other : candidateSet) {
|
||||
if (OverloadingConflictResolver.overrides(other, me)) {
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
candidates.add(me);
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
private boolean checkValueArgumentTypes(JetScope scope, JetTypeInferrer.Services temporaryServices, Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters, Flag dirty, Function<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap) {
|
||||
boolean result = true;
|
||||
for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
||||
|
||||
+2
-2
@@ -120,7 +120,7 @@ import java.util.Set;
|
||||
return false;
|
||||
}
|
||||
|
||||
private <Descriptor extends CallableDescriptor> boolean overrides(@NotNull Descriptor f, @NotNull Descriptor g) {
|
||||
public static <Descriptor extends CallableDescriptor> boolean overrides(@NotNull Descriptor f, @NotNull Descriptor g) {
|
||||
Set<CallableDescriptor> overriddenDescriptors = Sets.newHashSet();
|
||||
getAllOverriddenDescriptors(f.getOriginal(), overriddenDescriptors);
|
||||
CallableDescriptor originalG = g.getOriginal();
|
||||
@@ -130,7 +130,7 @@ import java.util.Set;
|
||||
return false;
|
||||
}
|
||||
|
||||
private void getAllOverriddenDescriptors(@NotNull CallableDescriptor current, @NotNull Set<CallableDescriptor> overriddenDescriptors) {
|
||||
private static void getAllOverriddenDescriptors(@NotNull CallableDescriptor current, @NotNull Set<CallableDescriptor> overriddenDescriptors) {
|
||||
if (overriddenDescriptors.contains(current)) return;
|
||||
for (CallableDescriptor descriptor : current.getOriginal().getOverriddenDescriptors()) {
|
||||
getAllOverriddenDescriptors(descriptor, overriddenDescriptors);
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
class A() {}
|
||||
class B<T>() {
|
||||
open class B<T>() {
|
||||
fun isT (a : Any?) : Boolean {
|
||||
return a is T
|
||||
}
|
||||
}
|
||||
|
||||
class C() : B<String>() {
|
||||
}
|
||||
|
||||
class D<T>() : B<B<T>>() {
|
||||
}
|
||||
|
||||
fun t1() : Boolean {
|
||||
val a = A()
|
||||
if(a !is A) return false
|
||||
@@ -148,6 +154,18 @@ fun t24 () : Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun t25 () : Boolean {
|
||||
val c = C()
|
||||
if(!c.isT("aaa")) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun t26 () : Boolean {
|
||||
val d = D<String>()
|
||||
if(!d.isT(B<String>())) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
if(!t1()) {
|
||||
return "t1 failed"
|
||||
@@ -221,5 +239,11 @@ fun box() : String {
|
||||
if(!t24()) {
|
||||
return "t24 failed"
|
||||
}
|
||||
if(!t25()) {
|
||||
return "t25 failed"
|
||||
}
|
||||
if(!t26()) {
|
||||
return "t26 failed"
|
||||
}
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// KT-297 Overload resolution ambiguity with required in trait
|
||||
trait ALE<T> : java.util.ArrayList<T> {
|
||||
fun getOrValue(index: Int, value : T) : T = if(index >= 0 && index < size()) get(index) else value
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
trait AL {
|
||||
fun get(index: Int) : Any? = null
|
||||
}
|
||||
|
||||
trait ALE<T> : AL {
|
||||
fun getOrNull(index: Int, value : T) = get(index) as? T ?: value
|
||||
}
|
||||
|
||||
class SmartArrayList() : ALE<String> {
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
val c = SmartArrayList()
|
||||
return if("239" == c.getOrNull(0, "239")) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
open class AL<T> {
|
||||
fun get(index: Int) : T? = null
|
||||
}
|
||||
|
||||
trait ALE<T> : AL<T> {
|
||||
fun getOrValue(index: Int, value : T) : T = get(index) ?: value
|
||||
}
|
||||
|
||||
class SmartArrayList() : ALE<String>, AL<String> {
|
||||
}
|
||||
|
||||
fun box() : String {
|
||||
val c = SmartArrayList()
|
||||
return if("239" == c.getOrValue(0, "239")) "OK" else "fail"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// KT-300 Overload ambiguity while accessing range
|
||||
|
||||
class MyRange() : Range<Int> {
|
||||
~in~override fun contains(item: Int) = true
|
||||
}
|
||||
|
||||
fun foo(x: Int?, range: MyRange) {
|
||||
x `in`in range // Int? found, but Int expected
|
||||
}
|
||||
@@ -10,4 +10,14 @@ public class TraitsTest extends CodegenTestCase {
|
||||
blackBoxFile("traits/simple.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testWithRequired () throws Exception {
|
||||
blackBoxFile("traits/withRequired.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
public void testMultiple () throws Exception {
|
||||
// blackBoxFile("traits/multiple.jet");
|
||||
// System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ public class TypeInfoTest extends CodegenTestCase {
|
||||
|
||||
public void testKt259() throws Exception {
|
||||
blackBoxFile("regressions/kt259.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,19 +6,20 @@ import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetTestCaseBase;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.lang.ErrorHandler;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.JetChangeUtil;
|
||||
import org.jetbrains.jet.lang.psi.JetClass;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaPackageScope;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaSemanticServices;
|
||||
import org.jetbrains.jet.lang.types.*;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.parsing.JetParsingTest;
|
||||
|
||||
import java.io.File;
|
||||
@@ -34,6 +35,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
private ClassDefinitions classDefinitions;
|
||||
private ClassDescriptorResolver classDescriptorResolver;
|
||||
private JetScope scopeWithImports;
|
||||
private TypeResolver typeResolver;
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
@@ -43,6 +45,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
classDefinitions = new ClassDefinitions();
|
||||
classDescriptorResolver = semanticServices.getClassDescriptorResolver(JetTestUtils.DUMMY_TRACE);
|
||||
scopeWithImports = addImports(classDefinitions.BASIC_SCOPE);
|
||||
typeResolver = new TypeResolver(semanticServices, JetTestUtils.DUMMY_TRACE, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -592,7 +595,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
if (CLASSES.isEmpty()) {
|
||||
for (String classDeclaration : CLASS_DECLARATIONS) {
|
||||
JetClass classElement = JetChangeUtil.createClass(getProject(), classDeclaration);
|
||||
ClassDescriptor classDescriptor = classDescriptorResolver.resolveClassDescriptor(this, classElement);
|
||||
ClassDescriptor classDescriptor = resolveClassDescriptor(this, classElement);
|
||||
CLASSES.put(classDescriptor.getName(), classDescriptor);
|
||||
}
|
||||
}
|
||||
@@ -622,5 +625,91 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
return writableFunctionGroup;
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
public ClassDescriptor resolveClassDescriptor(@NotNull JetScope scope, @NotNull JetClass classElement) {
|
||||
final ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
|
||||
scope.getContainingDeclaration(),
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
JetPsiUtil.safeName(classElement.getName()));
|
||||
|
||||
BindingTrace trace = JetTestUtils.DUMMY_TRACE;
|
||||
|
||||
trace.record(BindingContext.CLASS, classElement, classDescriptor);
|
||||
|
||||
final WritableScope parameterScope = new WritableScopeImpl(scope, classDescriptor, trace.getErrorHandler());
|
||||
|
||||
// This call has side-effects on the parameterScope (fills it in)
|
||||
List<TypeParameterDescriptor> typeParameters
|
||||
= classDescriptorResolver.resolveTypeParameters(classDescriptor, parameterScope, classElement.getTypeParameters());
|
||||
classDescriptorResolver.resolveGenericBounds(classElement, parameterScope, typeParameters);
|
||||
|
||||
List<JetDelegationSpecifier> delegationSpecifiers = classElement.getDelegationSpecifiers();
|
||||
// TODO : assuming that the hierarchy is acyclic
|
||||
Collection<JetType> supertypes = delegationSpecifiers.isEmpty()
|
||||
? Collections.singleton(JetStandardClasses.getAnyType())
|
||||
: classDescriptorResolver.resolveDelegationSpecifiers(parameterScope, delegationSpecifiers, typeResolver);
|
||||
// for (JetType supertype: supertypes) {
|
||||
// if (supertype.getConstructor().isSealed()) {
|
||||
// trace.getErrorHandler().genericError(classElement.getNameAsDeclaration().getNode(), "Class " + classElement.getName() + " can not extend final type " + supertype);
|
||||
// }
|
||||
// }
|
||||
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
|
||||
|
||||
final WritableScope memberDeclarations = new WritableScopeImpl(JetScope.EMPTY, classDescriptor, trace.getErrorHandler());
|
||||
|
||||
List<JetDeclaration> declarations = classElement.getDeclarations();
|
||||
for (JetDeclaration declaration : declarations) {
|
||||
declaration.accept(new JetVisitorVoid() {
|
||||
@Override
|
||||
public void visitProperty(JetProperty property) {
|
||||
if (property.getPropertyTypeRef() != null) {
|
||||
memberDeclarations.addVariableDescriptor(classDescriptorResolver.resolvePropertyDescriptor(classDescriptor, parameterScope, property));
|
||||
} else {
|
||||
// TODO : Caution: a cyclic dependency possible
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNamedFunction(JetNamedFunction function) {
|
||||
if (function.getReturnTypeRef() != null) {
|
||||
memberDeclarations.addFunctionDescriptor(classDescriptorResolver.resolveFunctionDescriptor(classDescriptor, parameterScope, function));
|
||||
} else {
|
||||
// TODO : Caution: a cyclic dependency possible
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement element) {
|
||||
throw new UnsupportedOperationException(element.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
WritableFunctionGroup constructors = new WritableFunctionGroup("<init>");
|
||||
classDescriptor.initialize(
|
||||
!open,
|
||||
typeParameters,
|
||||
supertypes,
|
||||
memberDeclarations,
|
||||
constructors,
|
||||
null
|
||||
);
|
||||
for (JetConstructor constructor : classElement.getSecondaryConstructors()) {
|
||||
ConstructorDescriptorImpl functionDescriptor = classDescriptorResolver.resolveSecondaryConstructorDescriptor(memberDeclarations, classDescriptor, constructor);
|
||||
functionDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
constructors.addFunction(functionDescriptor);
|
||||
}
|
||||
ConstructorDescriptorImpl primaryConstructorDescriptor = classDescriptorResolver.resolvePrimaryConstructorDescriptor(scope, classDescriptor, classElement);
|
||||
if (primaryConstructorDescriptor != null) {
|
||||
primaryConstructorDescriptor.setReturnType(classDescriptor.getDefaultType());
|
||||
constructors.addFunction(primaryConstructorDescriptor);
|
||||
classDescriptor.setPrimaryConstructor(primaryConstructorDescriptor);
|
||||
}
|
||||
return classDescriptor;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user