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);
|
||||
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;
|
||||
|
||||
+15
@@ -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();
|
||||
|
||||
|
||||
+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.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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user