KT-6081 Chained generic method calls: wrong type inference
#KT-6081 Fixed
This commit is contained in:
+7
-1
@@ -106,7 +106,13 @@ public class LazySubstitutingClassDescriptor implements ClassDescriptor {
|
||||
@NotNull
|
||||
@Override
|
||||
public JetType getDefaultType() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
List<TypeProjection> typeProjections = TypeUtils.getDefaultTypeProjections(getTypeConstructor().getParameters());
|
||||
return new JetTypeImpl(
|
||||
getAnnotations(),
|
||||
getTypeConstructor(),
|
||||
false,
|
||||
typeProjections,
|
||||
getMemberScope(typeProjections));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -21,11 +21,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lang.types.typeUtil.TypeUtilPackage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class TypeSubstitutor {
|
||||
|
||||
@@ -202,18 +200,41 @@ public class TypeSubstitutor {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The type is not within the substitution range, i.e. Foo, Bar<T> etc.
|
||||
List<TypeProjection> substitutedArguments = substituteTypeArguments(
|
||||
type.getConstructor().getParameters(), type.getArguments(), recursionDepth);
|
||||
// The type is not within the substitution range, i.e. Foo, Bar<T> etc.
|
||||
return substituteCompoundType(type, originalProjectionKind, recursionDepth);
|
||||
}
|
||||
|
||||
JetType substitutedType = new JetTypeImpl(type.getAnnotations(), // Old annotations. This is questionable
|
||||
type.getConstructor(), // The same constructor
|
||||
type.isNullable(), // Same nullability
|
||||
substitutedArguments,
|
||||
new SubstitutingScope(type.getMemberScope(), this));
|
||||
return new TypeProjectionImpl(originalProjectionKind, substitutedType);
|
||||
}
|
||||
private TypeProjection substituteCompoundType(
|
||||
final JetType type,
|
||||
Variance projectionKind,
|
||||
int recursionDepth
|
||||
) throws SubstitutionException {
|
||||
List<TypeProjection> substitutedArguments = substituteTypeArguments(
|
||||
type.getConstructor().getParameters(), type.getArguments(), recursionDepth);
|
||||
|
||||
// Only type parameters of the corresponding class (or captured type parameters of outer declaration) are substituted
|
||||
// e.g. for return type Foo of 'add(..)' in 'class Foo { fun <R> add(bar: Bar<R>): Foo }' R shouldn't be substituted in the scope
|
||||
TypeSubstitution substitutionFilteringTypeParameters = new TypeSubstitution() {
|
||||
private final Collection<TypeConstructor> containedOrCapturedTypeParameters =
|
||||
TypeUtilPackage.getContainedAndCapturedTypeParameterConstructors(type);
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TypeProjection get(TypeConstructor key) {
|
||||
return containedOrCapturedTypeParameters.contains(key) ? substitution.get(key) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return substitution.isEmpty();
|
||||
}
|
||||
};
|
||||
JetType substitutedType = new JetTypeImpl(type.getAnnotations(), // Old annotations. This is questionable
|
||||
type.getConstructor(), // The same constructor
|
||||
type.isNullable(), // Same nullability
|
||||
substitutedArguments,
|
||||
new SubstitutingScope(type.getMemberScope(), create(substitutionFilteringTypeParameters)));
|
||||
return new TypeProjectionImpl(projectionKind, substitutedType);
|
||||
}
|
||||
|
||||
private List<TypeProjection> substituteTypeArguments(
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.types.typeUtil
|
||||
|
||||
import java.util.LinkedHashSet
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.types.Flexibility
|
||||
import org.jetbrains.jet.lang.types.TypeConstructor
|
||||
import org.jetbrains.jet.utils.toReadOnlyList
|
||||
|
||||
fun JetType.getContainedTypeParameters(): Collection<TypeParameterDescriptor> {
|
||||
val declarationDescriptor = getConstructor().getDeclarationDescriptor()
|
||||
if (declarationDescriptor is TypeParameterDescriptor) return listOf(declarationDescriptor)
|
||||
|
||||
val flexibility = getCapability(javaClass<Flexibility>())
|
||||
if (flexibility != null) {
|
||||
return flexibility.lowerBound.getContainedTypeParameters() + flexibility.upperBound.getContainedTypeParameters()
|
||||
}
|
||||
return getArguments().map { it.getType() }.flatMap { it.getContainedTypeParameters() }
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.getCapturedTypeParameters(): Collection<TypeParameterDescriptor> {
|
||||
val result = LinkedHashSet<TypeParameterDescriptor>()
|
||||
val containingDeclaration = this.getContainingDeclaration()
|
||||
|
||||
if (containingDeclaration is ClassDescriptor) {
|
||||
result.addAll(containingDeclaration.getDefaultType().getContainedTypeParameters())
|
||||
}
|
||||
else if (containingDeclaration is CallableDescriptor) {
|
||||
result.addAll(containingDeclaration.getTypeParameters())
|
||||
}
|
||||
if (containingDeclaration != null) {
|
||||
result.addAll(containingDeclaration.getCapturedTypeParameters())
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public fun JetType.getContainedAndCapturedTypeParameterConstructors(): Collection<TypeConstructor> {
|
||||
// todo type arguments (instead of type parameters) of the type of outer class must be considered; KT-6325
|
||||
val typeParameters = getContainedTypeParameters() + getConstructor().getDeclarationDescriptor().getCapturedTypeParameters()
|
||||
return typeParameters.map { it.getTypeConstructor() }.toReadOnlyList()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user