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:
Andrey Breslav
2012-04-27 19:30:40 +04:00
parent d3ceaf7656
commit 5453598b2f
5 changed files with 71 additions and 35 deletions
@@ -159,7 +159,7 @@ public class FunctionCodegen {
JetValueParameterAnnotationWriter av = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i + start);
ValueParameterDescriptor parameterDescriptor = paramDescrs.get(i);
av.writeName(parameterDescriptor.getName());
av.writeHasDefaultValue(parameterDescriptor.hasDefaultValue());
av.writeHasDefaultValue(parameterDescriptor.declaresDefaultValue());
av.writeNullable(parameterDescriptor.getType().isNullable());
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(i) != null) {
av.writeType(jvmSignature.getKotlinParameterTypes().get(i + start).getKotlinSignature());
@@ -312,7 +312,7 @@ public class FunctionCodegen {
boolean needed = false;
if(functionDescriptor != null) {
for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
if(parameterDescriptor.hasDefaultValue()) {
if(parameterDescriptor.declaresDefaultValue()) {
needed = true;
break;
}
@@ -398,7 +398,7 @@ public class FunctionCodegen {
Type t = argumentTypes[extra + index];
Label endArg = null;
if (parameterDescriptor.hasDefaultValue()) {
if (parameterDescriptor.declaresDefaultValue()) {
iv.load(maskIndex, Type.INT_TYPE);
iv.iconst(1 << index);
iv.and(Type.INT_TYPE);
@@ -418,7 +418,7 @@ public class FunctionCodegen {
iv.load(var, t);
var += t.getSize();
if (parameterDescriptor.hasDefaultValue()) {
if (parameterDescriptor.declaresDefaultValue()) {
iv.mark(endArg);
}
}
@@ -551,7 +551,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
for (ValueParameterDescriptor valueParameter : constructorDescriptor.getValueParameters()) {
JetValueParameterAnnotationWriter jetValueParameterAnnotation = JetValueParameterAnnotationWriter.visitParameterAnnotation(mv, i);
jetValueParameterAnnotation.writeName(valueParameter.getName());
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.hasDefaultValue());
jetValueParameterAnnotation.writeHasDefaultValue(valueParameter.declaresDefaultValue());
jetValueParameterAnnotation.writeType(constructorMethod.getKotlinParameterType(i));
jetValueParameterAnnotation.visitEnd();
++i;
@@ -33,7 +33,22 @@ public interface ValueParameterDescriptor extends VariableDescriptor, Annotated
* @return the parameter index
*/
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();
/**
* 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();
@Nullable JetType getVarargElementType();
@@ -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.TypeSubstitutor;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -31,12 +32,17 @@ import java.util.Set;
* @author abreslav
*/
public class ValueParameterDescriptorImpl extends VariableDescriptorImpl implements MutableValueParameterDescriptor {
private final boolean hasDefaultValue;
private Boolean hasDefaultValue;
private final boolean declaresDefaultValue;
private final JetType varargElementType;
private final boolean isVar;
private final int index;
private final ValueParameterDescriptor original;
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(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -45,12 +51,12 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
@NotNull String name,
boolean isVar,
@NotNull JetType outType,
boolean hasDefaultValue,
boolean declaresDefaultValue,
@Nullable JetType varargElementType) {
super(containingDeclaration, annotations, name, outType);
this.original = this;
this.index = index;
this.hasDefaultValue = hasDefaultValue;
this.declaresDefaultValue = declaresDefaultValue;
this.varargElementType = varargElementType;
this.isVar = isVar;
}
@@ -66,7 +72,7 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
super(containingDeclaration, annotations, original.getName(), outType);
this.original = original;
this.index = original.getIndex();
this.hasDefaultValue = original.hasDefaultValue();
this.declaresDefaultValue = original.declaresDefaultValue();
this.varargElementType = varargElementType;
this.isVar = isVar;
}
@@ -83,9 +89,32 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
@Override
public boolean hasDefaultValue() {
computeDefaultValuePresence();
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
public boolean isRef() {
throw new UnsupportedOperationException(); // TODO
@@ -138,11 +167,13 @@ public class ValueParameterDescriptorImpl extends VariableDescriptorImpl impleme
@NotNull
@Override
public Set<? extends ValueParameterDescriptor> getOverriddenDescriptors() {
return overriddenDescriptors;
return readOnlyOverriddenDescriptors;
}
@Override
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);
}
}
@@ -83,18 +83,7 @@ public class OverrideResolver {
checkVisibility();
checkOverrides(invisibleOverriddenDescriptors);
checkParameterOverrides();
}
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);
}
}
checkParameterOverridesForAllClasses();
}
/**
@@ -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) {
boolean fakeOverride = declared.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
if (!fakeOverride) {
@@ -437,23 +437,13 @@ public class OverrideResolver {
fakeOverride ? null :
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
if (parameterFromSubclass.hasDefaultValue() && !fakeOverride) {
if (parameterFromSubclass.declaresDefaultValue() && !fakeOverride) {
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;
for (ValueParameterDescriptor parameterFromSuperclass : uniqueOverridden) {
if (parameterFromSuperclass.hasDefaultValue()) {
for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
if (parameterFromSuperclass.declaresDefaultValue()) {
if (!superWithDefault) {
superWithDefault = true;
}