KT-743 Wrong type inference
This commit is contained in:
@@ -226,11 +226,10 @@ public abstract class CodegenContext {
|
|||||||
pd.getModality(),
|
pd.getModality(),
|
||||||
pd.getVisibility(),
|
pd.getVisibility(),
|
||||||
pd.isVar(),
|
pd.isVar(),
|
||||||
pd.getExpectedThisObject(),
|
|
||||||
pd.getName() + "$bridge$" + accessors.size()
|
pd.getName() + "$bridge$" + accessors.size()
|
||||||
);
|
);
|
||||||
JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null;
|
JetType receiverType = pd.getReceiverParameter().exists() ? pd.getReceiverParameter().getType() : null;
|
||||||
myAccessor.setType(pd.getInType(), pd.getOutType(), Collections.<TypeParameterDescriptor>emptyList(), receiverType);
|
myAccessor.setType(pd.getInType(), pd.getOutType(), Collections.<TypeParameterDescriptor>emptyList(), pd.getExpectedThisObject(), receiverType);
|
||||||
|
|
||||||
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
PropertyGetterDescriptor pgd = new PropertyGetterDescriptor(
|
||||||
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
myAccessor, Collections.<AnnotationDescriptor>emptyList(), myAccessor.getModality(),
|
||||||
|
|||||||
@@ -16,6 +16,19 @@ import java.util.*;
|
|||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class FunctionDescriptorUtil {
|
public class FunctionDescriptorUtil {
|
||||||
|
private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create(new TypeSubstitutor.TypeSubstitution() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TypeProjection get(TypeConstructor key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
|
public static Map<TypeConstructor, TypeProjection> createSubstitutionContext(@NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) {
|
||||||
if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
|
if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap();
|
||||||
|
|
||||||
@@ -93,4 +106,8 @@ public class FunctionDescriptorUtil {
|
|||||||
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
|
JetStandardClasses.getReturnTypeFromFunctionType(functionType),
|
||||||
Modality.FINAL, Visibility.LOCAL);
|
Modality.FINAL, Visibility.LOCAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) {
|
||||||
|
return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||||
|
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
|
||||||
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 org.jetbrains.jet.lang.types.Variance;
|
import org.jetbrains.jet.lang.types.Variance;
|
||||||
@@ -17,6 +18,8 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
@@ -25,10 +28,10 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
private final Modality modality;
|
private final Modality modality;
|
||||||
private final Visibility visibility;
|
private final Visibility visibility;
|
||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final ReceiverDescriptor expectedThisObject;
|
|
||||||
private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet();
|
private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet();
|
||||||
private final PropertyDescriptor original;
|
private final PropertyDescriptor original;
|
||||||
|
|
||||||
|
private ReceiverDescriptor expectedThisObject;
|
||||||
private ReceiverDescriptor receiver;
|
private ReceiverDescriptor receiver;
|
||||||
private List<TypeParameterDescriptor> typeParemeters;
|
private List<TypeParameterDescriptor> typeParemeters;
|
||||||
private PropertyGetterDescriptor getter;
|
private PropertyGetterDescriptor getter;
|
||||||
@@ -41,14 +44,11 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
@NotNull Modality modality,
|
@NotNull Modality modality,
|
||||||
@NotNull Visibility visibility,
|
@NotNull Visibility visibility,
|
||||||
boolean isVar,
|
boolean isVar,
|
||||||
@NotNull ReceiverDescriptor expectedThisObject,
|
|
||||||
@NotNull String name) {
|
@NotNull String name) {
|
||||||
super(containingDeclaration, annotations, name);
|
super(containingDeclaration, annotations, name);
|
||||||
// assert outType != null;
|
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
this.modality = modality;
|
this.modality = modality;
|
||||||
this.visibility = visibility;
|
this.visibility = visibility;
|
||||||
this.expectedThisObject = expectedThisObject;
|
|
||||||
this.original = original == null ? this : original.getOriginal();
|
this.original = original == null ? this : original.getOriginal();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +58,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
@NotNull Modality modality,
|
@NotNull Modality modality,
|
||||||
@NotNull Visibility visibility,
|
@NotNull Visibility visibility,
|
||||||
boolean isVar,
|
boolean isVar,
|
||||||
@NotNull ReceiverDescriptor expectedThisObject,
|
|
||||||
@NotNull String name) {
|
@NotNull String name) {
|
||||||
this(null, containingDeclaration, annotations, modality, visibility, isVar, expectedThisObject, name);
|
this(null, containingDeclaration, annotations, modality, visibility, isVar, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyDescriptor(
|
public PropertyDescriptor(
|
||||||
@@ -74,10 +73,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
@NotNull String name,
|
@NotNull String name,
|
||||||
@Nullable JetType inType,
|
@Nullable JetType inType,
|
||||||
@NotNull JetType outType
|
@NotNull JetType outType
|
||||||
)
|
) {
|
||||||
{
|
this(containingDeclaration, annotations, modality, visibility, isVar, name);
|
||||||
this(containingDeclaration, annotations, modality, visibility, isVar, expectedThisObject, name);
|
setType(inType, outType, Collections.<TypeParameterDescriptor>emptyList(), expectedThisObject, receiverType);
|
||||||
setType(inType, outType, Collections.<TypeParameterDescriptor>emptyList(), receiverType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private PropertyDescriptor(
|
private PropertyDescriptor(
|
||||||
@@ -86,8 +84,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
@NotNull ReceiverDescriptor expectedThisObject,
|
@NotNull ReceiverDescriptor expectedThisObject,
|
||||||
@Nullable JetType inType,
|
@Nullable JetType inType,
|
||||||
@NotNull JetType outType
|
@NotNull JetType outType
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
this(
|
this(
|
||||||
original,
|
original,
|
||||||
original.getContainingDeclaration(),
|
original.getContainingDeclaration(),
|
||||||
@@ -95,26 +92,19 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
original.getModality(),
|
original.getModality(),
|
||||||
original.getVisibility(),
|
original.getVisibility(),
|
||||||
original.isVar,
|
original.isVar,
|
||||||
expectedThisObject,
|
|
||||||
original.getName()
|
original.getName()
|
||||||
);
|
);
|
||||||
setType(inType, outType, Collections.<TypeParameterDescriptor>emptyList(), receiverType);
|
setType(inType, outType, Collections.<TypeParameterDescriptor>emptyList(), expectedThisObject, receiverType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(@Nullable JetType inType, @NotNull JetType outType,
|
public void setType(@Nullable JetType inType, @NotNull JetType outType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @Nullable JetType receiverType) {
|
||||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
|
||||||
@Nullable JetType receiverType
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ReceiverDescriptor receiver = receiverType == null
|
ReceiverDescriptor receiver = receiverType == null
|
||||||
? ReceiverDescriptor.NO_RECEIVER
|
? NO_RECEIVER
|
||||||
: new ExtensionReceiver(this, receiverType);
|
: new ExtensionReceiver(this, receiverType);
|
||||||
setType(inType, outType, typeParameters, receiver);
|
setType(inType, outType, typeParameters, expectedThisObject, receiver);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setType(@Nullable JetType inType, @NotNull JetType outType,
|
public void setType(@Nullable JetType inType, @NotNull JetType outType, @NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor expectedThisObject, @NotNull ReceiverDescriptor receiver) {
|
||||||
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull ReceiverDescriptor receiver)
|
|
||||||
{
|
|
||||||
assert !isVar || inType != null;
|
assert !isVar || inType != null;
|
||||||
setInType(inType);
|
setInType(inType);
|
||||||
setOutType(outType);
|
setOutType(outType);
|
||||||
@@ -122,11 +112,10 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
this.typeParemeters = typeParameters;
|
this.typeParemeters = typeParameters;
|
||||||
|
|
||||||
this.receiver = receiver;
|
this.receiver = receiver;
|
||||||
|
this.expectedThisObject = expectedThisObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(
|
public void initialize(@Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter) {
|
||||||
@Nullable PropertyGetterDescriptor getter, @Nullable PropertySetterDescriptor setter)
|
|
||||||
{
|
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
}
|
}
|
||||||
@@ -191,7 +180,15 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PropertyDescriptor substitute(TypeSubstitutor substitutor) {
|
public PropertyDescriptor substitute(TypeSubstitutor originalSubstitutor) {
|
||||||
|
if (originalSubstitutor.isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
PropertyDescriptor substitutedDescriptor = new PropertyDescriptor(this, getContainingDeclaration(), getAnnotations(), getModality(), getVisibility(), isVar(), getName());
|
||||||
|
|
||||||
|
List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
|
||||||
|
TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
|
||||||
|
|
||||||
JetType originalInType = getInType();
|
JetType originalInType = getInType();
|
||||||
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
|
JetType inType = originalInType == null ? null : substitutor.substitute(originalInType, Variance.IN_VARIANCE);
|
||||||
JetType originalOutType = getOutType();
|
JetType originalOutType = getOutType();
|
||||||
@@ -199,6 +196,16 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
if (inType == null && outType == null) {
|
if (inType == null && outType == null) {
|
||||||
return null; // TODO : tell the user that the property was projected out
|
return null; // TODO : tell the user that the property was projected out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReceiverDescriptor substitutedExpectedThisObject;
|
||||||
|
if (expectedThisObject.exists()) {
|
||||||
|
JetType substitutedExpectedThisObjectType = substitutor.substitute(getExpectedThisObject().getType(), Variance.INVARIANT);
|
||||||
|
substitutedExpectedThisObject = new TransientReceiver(substitutedExpectedThisObjectType);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
substitutedExpectedThisObject = NO_RECEIVER;
|
||||||
|
}
|
||||||
|
|
||||||
JetType substitutedReceiverType;
|
JetType substitutedReceiverType;
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
substitutedReceiverType = substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE);
|
substitutedReceiverType = substitutor.substitute(receiver.getType(), Variance.IN_VARIANCE);
|
||||||
@@ -207,13 +214,10 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
else {
|
else {
|
||||||
substitutedReceiverType = null;
|
substitutedReceiverType = null;
|
||||||
}
|
}
|
||||||
return new PropertyDescriptor(
|
|
||||||
this,
|
substitutedDescriptor.setType(inType, outType, substitutedTypeParameters, substitutedExpectedThisObject, substitutedReceiverType);
|
||||||
substitutedReceiverType,
|
|
||||||
expectedThisObject.exists() ? new TransientReceiver(substitutor.substitute(expectedThisObject.getType(), Variance.IN_VARIANCE)) : expectedThisObject,
|
return substitutedDescriptor;
|
||||||
inType,
|
|
||||||
outType
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,10 +248,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
newOwner,
|
newOwner,
|
||||||
Lists.newArrayList(getAnnotations()),
|
Lists.newArrayList(getAnnotations()),
|
||||||
DescriptorUtils.convertModality(modality, makeNonAbstract), visibility, isVar,
|
DescriptorUtils.convertModality(modality, makeNonAbstract), visibility, isVar,
|
||||||
expectedThisObject,
|
|
||||||
getName());
|
getName());
|
||||||
|
|
||||||
propertyDescriptor.setType(getInType(), getOutType(), DescriptorUtils.copyTypeParameters(propertyDescriptor, getTypeParameters()), receiver.exists() ? receiver.getType() : null);
|
propertyDescriptor.setType(getInType(), getOutType(), DescriptorUtils.copyTypeParameters(propertyDescriptor, getTypeParameters()), expectedThisObject, receiver.exists() ? receiver.getType() : null);
|
||||||
|
|
||||||
PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor(
|
PropertyGetterDescriptor newGetter = getter == null ? null : new PropertyGetterDescriptor(
|
||||||
propertyDescriptor, Lists.newArrayList(getter.getAnnotations()),
|
propertyDescriptor, Lists.newArrayList(getter.getAnnotations()),
|
||||||
|
|||||||
@@ -475,11 +475,10 @@ public class DescriptorResolver {
|
|||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
resolveVisibilityFromModifiers(objectDeclaration.getModifierList()),
|
resolveVisibilityFromModifiers(objectDeclaration.getModifierList()),
|
||||||
false,
|
false,
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
|
|
||||||
JetPsiUtil.safeName(objectDeclaration.getName())
|
JetPsiUtil.safeName(objectDeclaration.getName())
|
||||||
);
|
);
|
||||||
|
|
||||||
propertyDescriptor.setType(null, classDescriptor.getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(), ReceiverDescriptor.NO_RECEIVER);
|
propertyDescriptor.setType(null, classDescriptor.getDefaultType(), Collections.<TypeParameterDescriptor>emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), ReceiverDescriptor.NO_RECEIVER);
|
||||||
propertyDescriptor.initialize(null, null);
|
propertyDescriptor.initialize(null, null);
|
||||||
|
|
||||||
JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration();
|
JetObjectDeclarationName nameAsDeclaration = objectDeclaration.getNameAsDeclaration();
|
||||||
@@ -518,7 +517,6 @@ public class DescriptorResolver {
|
|||||||
resolveModalityFromModifiers(property.getModifierList(), defaultModality),
|
resolveModalityFromModifiers(property.getModifierList(), defaultModality),
|
||||||
resolveVisibilityFromModifiers(property.getModifierList()),
|
resolveVisibilityFromModifiers(property.getModifierList()),
|
||||||
isVar,
|
isVar,
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
|
|
||||||
JetPsiUtil.safeName(property.getName())
|
JetPsiUtil.safeName(property.getName())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -555,7 +553,7 @@ public class DescriptorResolver {
|
|||||||
JetType type = getVariableType(scope2, property, true);
|
JetType type = getVariableType(scope2, property, true);
|
||||||
|
|
||||||
JetType inType = isVar ? type : null;
|
JetType inType = isVar ? type : null;
|
||||||
propertyDescriptor.setType(inType, type, typeParameterDescriptors, receiverDescriptor);
|
propertyDescriptor.setType(inType, type, typeParameterDescriptors, DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), receiverDescriptor);
|
||||||
|
|
||||||
PropertyGetterDescriptor getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor);
|
PropertyGetterDescriptor getter = resolvePropertyGetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor);
|
||||||
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor);
|
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(scopeWithTypeParameters, property, propertyDescriptor);
|
||||||
@@ -838,14 +836,13 @@ public class DescriptorResolver {
|
|||||||
resolveModalityFromModifiers(parameter.getModifierList(), Modality.FINAL),
|
resolveModalityFromModifiers(parameter.getModifierList(), Modality.FINAL),
|
||||||
resolveVisibilityFromModifiers(parameter.getModifierList()),
|
resolveVisibilityFromModifiers(parameter.getModifierList()),
|
||||||
isMutable,
|
isMutable,
|
||||||
DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor),
|
|
||||||
name == null ? "<no name>" : name
|
name == null ? "<no name>" : name
|
||||||
);
|
);
|
||||||
PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor);
|
PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor);
|
||||||
PropertySetterDescriptor setter = createDefaultSetter(propertyDescriptor);
|
PropertySetterDescriptor setter = createDefaultSetter(propertyDescriptor);
|
||||||
|
|
||||||
JetType inType = isMutable ? type : null;
|
JetType inType = isMutable ? type : null;
|
||||||
propertyDescriptor.setType(inType, type, Collections.<TypeParameterDescriptor>emptyList(), ReceiverDescriptor.NO_RECEIVER);
|
propertyDescriptor.setType(inType, type, Collections.<TypeParameterDescriptor>emptyList(), DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), ReceiverDescriptor.NO_RECEIVER);
|
||||||
propertyDescriptor.initialize(getter, setter);
|
propertyDescriptor.initialize(getter, setter);
|
||||||
getter.initialize(propertyDescriptor.getOutType());
|
getter.initialize(propertyDescriptor.getOutType());
|
||||||
|
|
||||||
|
|||||||
@@ -433,15 +433,25 @@ public class CallResolver {
|
|||||||
|
|
||||||
ConstraintSystem constraintSystem = new ConstraintSystemImpl(new DebugConstraintResolutionListener(debugInfo));
|
ConstraintSystem constraintSystem = new ConstraintSystemImpl(new DebugConstraintResolutionListener(debugInfo));
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : candidate.getTypeParameters()) {
|
// If the call is recursive, e.g.
|
||||||
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO
|
// fun foo<T>(t : T) : T = foo(t)
|
||||||
|
// we can't use same descriptor objects for T's as actual type values and same T's as unknowns,
|
||||||
|
// because constraints become trivial (T :< T), and inference fails
|
||||||
|
//
|
||||||
|
// Thus, we replace the parameters of our descriptor with fresh objects (perform alpha-conversion)
|
||||||
|
CallableDescriptor candidateWithFreshVariables = FunctionDescriptorUtil.alphaConvertTypeParameters(candidate);
|
||||||
|
|
||||||
|
|
||||||
|
for (TypeParameterDescriptor typeParameterDescriptor : candidateWithFreshVariables.getTypeParameters()) {
|
||||||
|
constraintSystem.registerTypeVariable(typeParameterDescriptor, Variance.INVARIANT); // TODO: variance of the occurrences
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidate.getTypeParameters(), DONT_CARE);
|
TypeSubstitutor substituteDontCare = ConstraintSystemImpl.makeConstantSubstitutor(candidateWithFreshVariables.getTypeParameters(), DONT_CARE);
|
||||||
|
|
||||||
|
// Value parameters
|
||||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
|
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
|
||||||
ResolvedValueArgument valueArgument = entry.getValue();
|
ResolvedValueArgument valueArgument = entry.getValue();
|
||||||
ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
|
ValueParameterDescriptor valueParameterDescriptor = candidateWithFreshVariables.getValueParameters().get(entry.getKey().getIndex());
|
||||||
|
|
||||||
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
|
JetType effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor);
|
||||||
|
|
||||||
@@ -463,25 +473,29 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Receiver
|
||||||
// Error is already reported if something is missing
|
// Error is already reported if something is missing
|
||||||
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
||||||
ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = candidateWithFreshVariables.getReceiverParameter();
|
||||||
if (receiverArgument.exists() && receiverParameter.exists()) {
|
if (receiverArgument.exists() && receiverParameter.exists()) {
|
||||||
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
|
constraintSystem.addSubtypingConstraint(receiverArgument.getType(), receiverParameter.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return type
|
||||||
if (expectedType != NO_EXPECTED_TYPE) {
|
if (expectedType != NO_EXPECTED_TYPE) {
|
||||||
constraintSystem.addSubtypingConstraint(candidate.getReturnType(), expectedType);
|
constraintSystem.addSubtypingConstraint(candidateWithFreshVariables.getReturnType(), expectedType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Solution
|
||||||
ConstraintSystemSolution solution = constraintSystem.solve();
|
ConstraintSystemSolution solution = constraintSystem.solve();
|
||||||
if (solution.getStatus().isSuccessful()) {
|
if (solution.getStatus().isSuccessful()) {
|
||||||
D substitute = (D) candidate.substitute(solution.getSubstitutor());
|
D substitute = (D) candidateWithFreshVariables.substitute(solution.getSubstitutor());
|
||||||
assert substitute != null;
|
assert substitute != null;
|
||||||
replaceValueParametersWithSubstitutedOnes(candidateCall, substitute);
|
replaceValueParametersWithSubstitutedOnes(candidateCall, substitute);
|
||||||
candidateCall.setResultingDescriptor(substitute);
|
candidateCall.setResultingDescriptor(substitute);
|
||||||
|
|
||||||
for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : candidateCall.getCandidateDescriptor().getTypeParameters()) {
|
||||||
candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(typeParameterDescriptor));
|
candidateCall.recordTypeArgument(typeParameterDescriptor, solution.getValue(candidateWithFreshVariables.getTypeParameters().get(typeParameterDescriptor.getIndex())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we type check the arguments with inferred types expected
|
// Here we type check the arguments with inferred types expected
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
//KT-743 Wrong type inference
|
||||||
|
// +JDK
|
||||||
|
class List<T>(val head: T, val tail: List<T>? = null)
|
||||||
|
|
||||||
|
fun <T, Q> List<T>.map(f: fun(T): Q): List<T>? = tail.sure<List<T>>().map(f)
|
||||||
|
fun foo<T>(t : T) : T = foo(t)
|
||||||
Reference in New Issue
Block a user