diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 222c921b0e4..460832afc0e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2210,6 +2210,7 @@ public class ExpressionCodegen extends JetVisitor implem throw new UnsupportedOperationException(); } + @NotNull public StackValue generateThisOrOuter(@NotNull ClassDescriptor calleeContainingClass, boolean isSuper) { boolean isSingleton = calleeContainingClass.getKind().isSingleton(); if (isSingleton) { @@ -2227,8 +2228,12 @@ public class ExpressionCodegen extends JetVisitor implem boolean inStartConstructorContext = cur instanceof ConstructorContext; while (cur != null) { ClassDescriptor thisDescriptor = cur.getThisDescriptor(); - if (!isSuper && thisDescriptor.equals(calleeContainingClass) - || isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { + + if (!isSuper && thisDescriptor == calleeContainingClass) { + return result; + } + + if (isSuper && DescriptorUtils.isSubclass(thisDescriptor, calleeContainingClass)) { return castToRequiredTypeOfInterfaceIfNeeded(result, thisDescriptor, calleeContainingClass); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 6f727d4b077..1d346890698 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -142,7 +142,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { endVisit(mv, null, origin); - generateBridgeIfNeeded(owner, state, v, functionDescriptor); + generateBridgeIfNeeded(functionDescriptor); methodContext.recordSyntheticAccessorIfNeeded(functionDescriptor, bindingContext); } @@ -404,12 +404,7 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { return bytecode; } - static void generateBridgeIfNeeded( - CodegenContext owner, - GenerationState state, - ClassBuilder v, - FunctionDescriptor functionDescriptor - ) { + private void generateBridgeIfNeeded(@NotNull FunctionDescriptor functionDescriptor) { if (owner.getContextKind() == OwnerKind.TRAIT_IMPL) { return; } @@ -775,6 +770,6 @@ public class FunctionCodegen extends ParentCodegenAwareImpl { endVisit(mv, "Delegate method " + functionDescriptor + " to " + jvmOverriddenMethodSignature, descriptorToDeclaration(bindingContext, functionDescriptor.getContainingDeclaration())); - generateBridgeIfNeeded(owner, state, v, functionDescriptor); + generateBridgeIfNeeded(functionDescriptor); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index bffe0e757ce..1e055444d87 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -20,7 +20,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Pair; -import com.intellij.psi.PsiElement; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,7 +63,6 @@ import static org.jetbrains.jet.codegen.AsmUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*; import static org.jetbrains.jet.codegen.binding.CodegenBinding.*; import static org.jetbrains.jet.descriptors.serialization.NameSerializationUtil.createNameResolver; -import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE; @@ -1464,21 +1462,28 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } private void generateTraitMethods() { - if (JetPsiUtil.isTrait(myClass)) { - return; - } + if (JetPsiUtil.isTrait(myClass)) return; - for (Pair needDelegates : getTraitImplementations(descriptor)) { - if (needDelegates.second instanceof SimpleFunctionDescriptor) { - generateDelegationToTraitImpl((FunctionDescriptor) needDelegates.second, (FunctionDescriptor) needDelegates.first); + for (Pair pair : getTraitImplementations(descriptor)) { + CallableMemberDescriptor inheritedMember = pair.first; + CallableMemberDescriptor traitMember = pair.second; + + assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + pair; + + // inheritedMember can be abstract here. In order for FunctionCodegen to generate the method body, we're creating a copy here + // with traitMember's modality + CallableMemberDescriptor copy = + inheritedMember.copy(inheritedMember.getContainingDeclaration(), traitMember.getModality(), Visibilities.PUBLIC, + CallableMemberDescriptor.Kind.DECLARATION, true); + + if (traitMember instanceof SimpleFunctionDescriptor) { + generateDelegationToTraitImpl((FunctionDescriptor) traitMember, (FunctionDescriptor) copy); } - else if (needDelegates.second instanceof PropertyDescriptor) { - PropertyDescriptor property = (PropertyDescriptor) needDelegates.second; - List inheritedAccessors = ((PropertyDescriptor) needDelegates.first).getAccessors(); - for (PropertyAccessorDescriptor accessor : property.getAccessors()) { - for (PropertyAccessorDescriptor inheritedAccessor : inheritedAccessors) { - if (inheritedAccessor.getClass() == accessor.getClass()) { // same accessor kind - generateDelegationToTraitImpl(accessor, inheritedAccessor); + else if (traitMember instanceof PropertyDescriptor) { + for (PropertyAccessorDescriptor traitAccessor : ((PropertyDescriptor) traitMember).getAccessors()) { + for (PropertyAccessorDescriptor inheritedAccessor : ((PropertyDescriptor) copy).getAccessors()) { + if (inheritedAccessor.getClass() == traitAccessor.getClass()) { // same accessor kind + generateDelegationToTraitImpl(traitAccessor, inheritedAccessor); } } } @@ -1486,58 +1491,42 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } + private void generateDelegationToTraitImpl(@NotNull final FunctionDescriptor traitFun, @NotNull FunctionDescriptor inheritedFun) { + functionCodegen.generateMethod( + descriptorToDeclaration(bindingContext, traitFun), + typeMapper.mapSignature(inheritedFun), + inheritedFun, + new FunctionGenerationStrategy.CodegenBased(state, inheritedFun) { + @Override + public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) { + DeclarationDescriptor containingDeclaration = traitFun.getContainingDeclaration(); + if (!(containingDeclaration instanceof ClassDescriptor)) return; + ClassDescriptor containingTrait = (ClassDescriptor) containingDeclaration; + if (containingTrait.getKind() != ClassKind.TRAIT) return; - private void generateDelegationToTraitImpl(@NotNull FunctionDescriptor fun, @NotNull FunctionDescriptor inheritedFun) { - DeclarationDescriptor containingDeclaration = fun.getContainingDeclaration(); - if (!(containingDeclaration instanceof ClassDescriptor)) { - return; - } + Method traitMethod = typeMapper.mapSignature(traitFun.getOriginal()).getAsmMethod(); - ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration; - if (containingClass.getKind() != ClassKind.TRAIT) { - return; - } + Type[] argTypes = signature.getAsmMethod().getArgumentTypes(); + Type[] originalArgTypes = traitMethod.getArgumentTypes(); - int flags = ACC_PUBLIC; // TODO. + InstructionAdapter iv = codegen.v; + iv.load(0, OBJECT_TYPE); + for (int i = 0, reg = 1; i < argTypes.length; i++) { + StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); + //noinspection AssignmentToForLoopParameter + reg += argTypes[i].getSize(); + } - Method methodToGenerate = typeMapper.mapSignature(fun).getAsmMethod(); - Method methodInTrait = typeMapper.mapSignature(fun.getOriginal()).getAsmMethod(); + Type type = getTraitImplThisParameterType(containingTrait, typeMapper); + String desc = traitMethod.getDescriptor().replace("(", "(" + type.getDescriptor()); - PsiElement origin = descriptorToDeclaration(bindingContext, fun); - MethodVisitor mv = v.newMethod(origin, flags, methodToGenerate.getName(), methodToGenerate.getDescriptor(), null, - CodegenUtil.getExceptions(fun, typeMapper)); - AnnotationCodegen.forMethod(mv, typeMapper).genAnnotations(fun); + iv.invokestatic(typeMapper.mapTraitImpl(containingTrait).getInternalName(), traitMethod.getName(), desc); - if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { - Type returnType = methodToGenerate.getReturnType(); - - mv.visitCode(); - FrameMap frameMap = context.prepareFrame(typeMapper); - ExpressionCodegen codegen = new ExpressionCodegen(mv, frameMap, returnType, context.intoFunction(inheritedFun), state, this); - codegen.generateThisOrOuter(descriptor, false); // ??? wouldn't it be addClosureToConstructorParameters good idea to put it? - - Type[] argTypes = methodToGenerate.getArgumentTypes(); - Type[] originalArgTypes = methodInTrait.getArgumentTypes(); - - InstructionAdapter iv = new InstructionAdapter(mv); - iv.load(0, OBJECT_TYPE); - for (int i = 0, reg = 1; i < argTypes.length; i++) { - StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv); - //noinspection AssignmentToForLoopParameter - reg += argTypes[i].getSize(); + Type returnType = signature.getReturnType(); + StackValue.onStack(traitMethod.getReturnType()).put(returnType, iv); + iv.areturn(returnType); } - - Type type = getTraitImplThisParameterType(containingClass, typeMapper); - String functionDescriptor = methodInTrait.getDescriptor().replace("(", "(" + type.getDescriptor()); - - iv.invokestatic(typeMapper.mapTraitImpl(containingClass).getInternalName(), methodToGenerate.getName(), functionDescriptor); - StackValue.onStack(methodInTrait.getReturnType()).put(returnType, iv); - iv.areturn(returnType); - - FunctionCodegen.endVisit(iv, "trait method", callableDescriptorToDeclaration(bindingContext, fun)); - } - - FunctionCodegen.generateBridgeIfNeeded(context, state, v, fun); + }); } private void generateDelegatorToConstructorCall( diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java index b6eab7913d5..65fd28c7898 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DelegationResolver.java @@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.base.Predicate; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,10 +31,7 @@ import org.jetbrains.jet.lang.psi.JetTypeReference; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED; import static org.jetbrains.jet.lang.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; @@ -162,11 +158,11 @@ public final class DelegationResolver { @NotNull private Collection generateDelegationCandidates(@NotNull JetType delegatedTraitType) { Collection descriptorsToDelegate = overridableMembersNotFromSuperClassOfTrait(delegatedTraitType); - Collection result = Lists.newArrayList(); + Collection result = new ArrayList(descriptorsToDelegate.size()); for (T memberDescriptor : descriptorsToDelegate) { - Modality modality = DescriptorUtils.convertModality(memberDescriptor.getModality(), true); + Modality newModality = memberDescriptor.getModality() == Modality.ABSTRACT ? Modality.OPEN : memberDescriptor.getModality(); @SuppressWarnings("unchecked") - T copy = (T) memberDescriptor.copy(ownerDescriptor, modality, memberDescriptor.getVisibility(), + T copy = (T) memberDescriptor.copy(ownerDescriptor, newModality, memberDescriptor.getVisibility(), CallableMemberDescriptor.Kind.DELEGATION, false); result.add(copy); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/PropertyDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/PropertyDescriptorImpl.java index e834df75652..0af85feacba 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/PropertyDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/PropertyDescriptorImpl.java @@ -23,7 +23,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.Annotations; import org.jetbrains.jet.lang.resolve.DescriptorFactory; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.OverridingUtil; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.DescriptorSubstitutor; @@ -243,16 +242,17 @@ public class PropertyDescriptorImpl extends VariableDescriptorImpl implements Pr substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedExpectedThisObject, substitutedReceiverType); PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl( - substitutedDescriptor, getter.getAnnotations(), - DescriptorUtils.convertModality(getter.getModality(), false), convertVisibility(getter.getVisibility(), newVisibility), - getter.hasBody(), getter.isDefault(), kind, getter.getOriginal()); + substitutedDescriptor, getter.getAnnotations(), newModality, convertVisibility(getter.getVisibility(), newVisibility), + getter.hasBody(), getter.isDefault(), kind, getter.getOriginal() + ); if (newGetter != null) { JetType returnType = getter.getReturnType(); newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null); } PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl( - substitutedDescriptor, setter.getAnnotations(), DescriptorUtils.convertModality(setter.getModality(), false), - convertVisibility(setter.getVisibility(), newVisibility), setter.hasBody(), setter.isDefault(), kind, setter.getOriginal()); + substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility), + setter.hasBody(), setter.isDefault(), kind, setter.getOriginal() + ); if (newSetter != null) { List substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(newSetter, setter, substitutor); if (substitutedValueParameters == null) { diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index 2b83e48a081..52172210b1c 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -57,12 +57,6 @@ public class DescriptorUtils { return substitutedFunction; } - @NotNull - public static Modality convertModality(@NotNull Modality modality, boolean makeNonAbstract) { - if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN; - return modality; - } - @Nullable public static ReceiverParameterDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) { if (containingDeclaration instanceof ClassDescriptor) {