Declared vs inherited default values
A value parameter _declares _a default value when the value is explicitly provided in the declaration of the parameter. A value parameter _has_ a default value when it declares a default value or an overridden function declares it for the same parameter
This commit is contained in:
@@ -159,7 +159,7 @@ public class FunctionCodegen {
|
|||||||
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
|
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
|
||||||
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
|
||||||
av.writeName(parameterDescriptor.getName());
|
av.writeName(parameterDescriptor.getName());
|
||||||
av.writeHasDefaultValue(parameterDescriptor.hasDefaultValue());
|
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
|
||||||
av.writeNullable(parameterDescriptor.getType().isNullable());
|
av.writeNullable(parameterDescriptor.getType().isNullable());
|
||||||
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
|
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
|
||||||
av.writeType(jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
|
av.writeType(jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
|
||||||
@@ -312,7 +312,7 @@ public class FunctionCodegen {
|
|||||||
boolean needed = false;
|
boolean needed = false;
|
||||||
if(functionDescriptor != null) {
|
if(functionDescriptor != null) {
|
||||||
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
|
||||||
if(parameterDescriptor.hasDefaultValue()) {
|
if(parameterDescriptor.declaresDefaultValue()) {
|
||||||
needed = true;
|
needed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -398,7 +398,7 @@ public class FunctionCodegen {
|
|||||||
|
|
||||||
Type t = argumentTypes[extra + index];
|
Type t = argumentTypes[extra + index];
|
||||||
Label endArg = null;
|
Label endArg = null;
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
if (parameterDescriptor.declaresDefaultValue()) {
|
||||||
iv.load(maskIndex, Type.INT_TYPE);
|
iv.load(maskIndex, Type.INT_TYPE);
|
||||||
iv.iconst(1 << index);
|
iv.iconst(1 << index);
|
||||||
iv.and(Type.INT_TYPE);
|
iv.and(Type.INT_TYPE);
|
||||||
@@ -418,7 +418,7 @@ public class FunctionCodegen {
|
|||||||
iv.load(var, t);
|
iv.load(var, t);
|
||||||
var += t.getSize();
|
var += t.getSize();
|
||||||
|
|
||||||
if (parameterDescriptor.hasDefaultValue()) {
|
if (parameterDescriptor.declaresDefaultValue()) {
|
||||||
iv.mark(endArg);
|
iv.mark(endArg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
|
||||||
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
|
||||||
jetValueParameterAnnotation.writeName(valueParameter.getName());
|
jetValueParameterAnnotation.writeName(valueParameter.getName());
|
||||||
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.hasDefaultValue());
|
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
|
||||||
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
|
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
|
||||||
jetValueParameterAnnotation.visitEnd();
|
jetValueParameterAnnotation.visitEnd();
|
||||||
++i;
|
++i;
|
||||||
|
|||||||
+15
@@ -33,7 +33,22 @@ public interface ValueParameterDescriptor extends VariableDescriptor, Annotated
|
|||||||
* @return the parameter index
|
* @return the parameter index
|
||||||
*/
|
*/
|
||||||
int getIndex();
|
int getIndex();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The font-end relies on this property when resolving function calls
|
||||||
|
*
|
||||||
|
* @return {@code true} iff the parameter has a default value, i.e. declares it or inherits
|
||||||
|
* by overriding a parameter in an overridden function.
|
||||||
|
*/
|
||||||
boolean hasDefaultValue();
|
boolean hasDefaultValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The back-end should relies on this property when generating function signatures
|
||||||
|
*
|
||||||
|
* @return {@code true} iff the parameter declares a default value, i.e. explicitly specifies it in the function header
|
||||||
|
*/
|
||||||
|
boolean declaresDefaultValue();
|
||||||
|
|
||||||
boolean isRef();
|
boolean isRef();
|
||||||
@Nullable JetType getVarargElementType();
|
@Nullable JetType getVarargElementType();
|
||||||
|
|
||||||
|
|||||||
+36
-5
@@ -24,6 +24,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
|||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@@ -31,12 +32,17 @@ import java.util.Set;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
|
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
|
||||||
private final boolean hasDefaultValue;
|
private Boolean hasDefaultValue;
|
||||||
|
private final boolean declaresDefaultValue;
|
||||||
|
|
||||||
private final JetType varargElementType;
|
private final JetType varargElementType;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final int index;
|
private final int index;
|
||||||
private final ValueParameterDescriptor original;
|
private final ValueParameterDescriptor original;
|
||||||
|
|
||||||
private final Set<ValueParameterDescriptor> overriddenDescriptors = Sets.newLinkedHashSet(); // Linked is essential
|
private final Set<ValueParameterDescriptor> overriddenDescriptors = Sets.newLinkedHashSet(); // Linked is essential
|
||||||
|
private boolean overriddenDescriptorsLocked = false;
|
||||||
|
private final Set<? extends ValueParameterDescriptor> readOnlyOverriddenDescriptors = Collections.unmodifiableSet(overriddenDescriptors);
|
||||||
|
|
||||||
public ValueParameterDescriptorImpl(
|
public ValueParameterDescriptorImpl(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor containingDeclaration,
|
||||||
@@ -45,12 +51,12 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
boolean isVar,
|
boolean isVar,
|
||||||
@NotNull JetType outType,
|
@NotNull JetType outType,
|
||||||
boolean hasDefaultValue,
|
boolean declaresDefaultValue,
|
||||||
@Nullable JetType varargElementType) {
|
@Nullable JetType varargElementType) {
|
||||||
super(containingDeclaration, annotations, name, outType);
|
super(containingDeclaration, annotations, name, outType);
|
||||||
this.original = this;
|
this.original = this;
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.hasDefaultValue = hasDefaultValue;
|
this.declaresDefaultValue = declaresDefaultValue;
|
||||||
this.varargElementType = varargElementType;
|
this.varargElementType = varargElementType;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
}
|
}
|
||||||
@@ -66,7 +72,7 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
super(containingDeclaration, annotations, original.getName(), outType);
|
super(containingDeclaration, annotations, original.getName(), outType);
|
||||||
this.original = original;
|
this.original = original;
|
||||||
this.index = original.getIndex();
|
this.index = original.getIndex();
|
||||||
this.hasDefaultValue = original.hasDefaultValue();
|
this.declaresDefaultValue = original.declaresDefaultValue();
|
||||||
this.varargElementType = varargElementType;
|
this.varargElementType = varargElementType;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
}
|
}
|
||||||
@@ -83,9 +89,32 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasDefaultValue() {
|
public boolean hasDefaultValue() {
|
||||||
|
computeDefaultValuePresence();
|
||||||
return hasDefaultValue;
|
return hasDefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean declaresDefaultValue() {
|
||||||
|
return declaresDefaultValue && ((CallableMemberDescriptor) getContainingDeclaration()).getKind().isReal();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void computeDefaultValuePresence() {
|
||||||
|
if (hasDefaultValue != null) return;
|
||||||
|
overriddenDescriptorsLocked = true;
|
||||||
|
if (declaresDefaultValue) {
|
||||||
|
hasDefaultValue = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (ValueParameterDescriptor descriptor : overriddenDescriptors) {
|
||||||
|
if (descriptor.hasDefaultValue()) {
|
||||||
|
hasDefaultValue = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hasDefaultValue = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isRef() {
|
public boolean isRef() {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
@@ -138,11 +167,13 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends ValueParameterDescriptor> getOverriddenDescriptors() {
|
public Set<? extends ValueParameterDescriptor> getOverriddenDescriptors() {
|
||||||
return overriddenDescriptors;
|
return readOnlyOverriddenDescriptors;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOverriddenDescriptor(@NotNull ValueParameterDescriptor overridden) {
|
public void addOverriddenDescriptor(@NotNull ValueParameterDescriptor overridden) {
|
||||||
|
assert !overriddenDescriptorsLocked : "Adding more overridden descriptors is not allowed at this point: " +
|
||||||
|
"the presence of the default value has already been calculated";
|
||||||
overriddenDescriptors.add(overridden);
|
overriddenDescriptors.add(overridden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,18 +83,7 @@ public class OverrideResolver {
|
|||||||
|
|
||||||
checkVisibility();
|
checkVisibility();
|
||||||
checkOverrides(invisibleOverriddenDescriptors);
|
checkOverrides(invisibleOverriddenDescriptors);
|
||||||
checkParameterOverrides();
|
checkParameterOverridesForAllClasses();
|
||||||
}
|
|
||||||
|
|
||||||
private void checkParameterOverrides() {
|
|
||||||
List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values());
|
|
||||||
allClasses.addAll(context.getObjects().values());
|
|
||||||
for (MutableClassDescriptor classDescriptor : allClasses) {
|
|
||||||
Collection<CallableMemberDescriptor> members = classDescriptor.getAllCallableMembers();
|
|
||||||
for (CallableMemberDescriptor member : members) {
|
|
||||||
checkOverridesForParameters(member);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -416,6 +405,17 @@ public class OverrideResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkParameterOverridesForAllClasses() {
|
||||||
|
List<MutableClassDescriptor> allClasses = Lists.newArrayList(context.getClasses().values());
|
||||||
|
allClasses.addAll(context.getObjects().values());
|
||||||
|
for (MutableClassDescriptor classDescriptor : allClasses) {
|
||||||
|
Collection<CallableMemberDescriptor> members = classDescriptor.getAllCallableMembers();
|
||||||
|
for (CallableMemberDescriptor member : members) {
|
||||||
|
checkOverridesForParameters(member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkOverridesForParameters(CallableMemberDescriptor declared) {
|
private void checkOverridesForParameters(CallableMemberDescriptor declared) {
|
||||||
boolean fakeOverride = declared.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
|
boolean fakeOverride = declared.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
|
||||||
if (!fakeOverride) {
|
if (!fakeOverride) {
|
||||||
@@ -437,23 +437,13 @@ public class OverrideResolver {
|
|||||||
fakeOverride ? null :
|
fakeOverride ? null :
|
||||||
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
|
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
|
||||||
|
|
||||||
if (parameterFromSubclass.hasDefaultValue() && !fakeOverride) {
|
if (parameterFromSubclass.declaresDefaultValue() && !fakeOverride) {
|
||||||
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
|
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If p1 overrides p2 and p3 and p2 overrides p3, we remove p2 from p1's overridden list
|
|
||||||
Set<ValueParameterDescriptor> uniqueOverridden = Sets.newHashSet(parameterFromSubclass.getOverriddenDescriptors());
|
|
||||||
for (ValueParameterDescriptor p2 : parameterFromSubclass.getOverriddenDescriptors()) {
|
|
||||||
for (ValueParameterDescriptor p3 : p2.getOverriddenDescriptors()) {
|
|
||||||
if (uniqueOverridden.contains(p3)) {
|
|
||||||
uniqueOverridden.remove(p2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean superWithDefault = false;
|
boolean superWithDefault = false;
|
||||||
for (ValueParameterDescriptor parameterFromSuperclass : uniqueOverridden) {
|
for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
|
||||||
if (parameterFromSuperclass.hasDefaultValue()) {
|
if (parameterFromSuperclass.declaresDefaultValue()) {
|
||||||
if (!superWithDefault) {
|
if (!superWithDefault) {
|
||||||
superWithDefault = true;
|
superWithDefault = true;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user