@Nullable public static List<ValueParameterDescriptor> getSubstitutedValueParameters( FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) { List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(); List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i); // TODO : Lazy? JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE); JetType varargElementType = unsubstitutedValueParameter.getVarargElementType(); JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE); if (substitutedType == null) return null; result.add( new ValueParameterDescriptorImpl( substitutedDescriptor, unsubstitutedValueParameter, unsubstitutedValueParameter.getAnnotations(), unsubstitutedValueParameter.isVar(), substitutedType, substituteVarargElementType)); } return result; }
private TypeSubstitutor createTypeSubstitutorWithDefaultForUnknownTypeParameter( @Nullable final TypeProjection defaultTypeProjection) { return TypeSubstitutor.create( new TypeSubstitution() { @Override public TypeProjection get(TypeConstructor key) { DeclarationDescriptor declarationDescriptor = key.getDeclarationDescriptor(); if (declarationDescriptor instanceof TypeParameterDescriptor) { TypeParameterDescriptor descriptor = (TypeParameterDescriptor) declarationDescriptor; JetType value = ConstraintsUtil.getValue(getTypeConstraints(descriptor)); if (value != null && !TypeUtils.dependsOnTypeParameterConstructors( value, Collections.singleton(DONT_CARE.getConstructor()))) { return new TypeProjection(value); } if (typeParameterConstraints.containsKey(descriptor)) { return defaultTypeProjection; } } return null; } @Override public boolean isEmpty() { return false; } @Override public String toString() { return typeParameterConstraints.toString(); } }); }
@Nullable public static FunctionDescriptor substituteFunctionDescriptor( @NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) { Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments); return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext)); }
@NotNull private static FunctionDescriptor substituteSuperFunction( @NotNull Map<ClassDescriptor, JetType> superclassToSupertype, @NotNull FunctionDescriptor superFun) { DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration(); assert superFunContainer instanceof ClassDescriptor : superFunContainer; JetType supertype = superclassToSupertype.get(superFunContainer); assert supertype != null : "Couldn't find super type for super function: " + superFun; TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype); FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor); assert substitutedSuperFun != null; return substitutedSuperFun; }
/** * Remember that we are trying to cast something of type {@code supertype} to {@code subtype}. * * <p>Since at runtime we can only check the class (type constructor), the rest of the subtype * should be known statically, from supertype. This method reconstructs all static information * that can be obtained from supertype. * * <p>Example 1: supertype = Collection<String> subtype = List<...> result = List<String>, all * arguments are inferred * * <p>Example 2: supertype = Any subtype = List<...> result = List<*>, some arguments were not * inferred, replaced with '*' */ public static TypeReconstructionResult findStaticallyKnownSubtype( @NotNull JetType supertype, @NotNull TypeConstructor subtypeConstructor) { assert !supertype.isNullable() : "This method only makes sense for non-nullable types"; // Assume we are casting an expression of type Collection<Foo> to List<Bar> // First, let's make List<T>, where T is a type variable ClassifierDescriptor descriptor = subtypeConstructor.getDeclarationDescriptor(); assert descriptor != null : "Can't create default type for " + subtypeConstructor; JetType subtypeWithVariables = descriptor.getDefaultType(); // Now, let's find a supertype of List<T> that is a Collection of something, // in this case it will be Collection<T> JetType supertypeWithVariables = TypeCheckingProcedure.findCorrespondingSupertype(subtypeWithVariables, supertype); final List<TypeParameterDescriptor> variables = subtypeWithVariables.getConstructor().getParameters(); Map<TypeConstructor, TypeProjection> substitution; if (supertypeWithVariables != null) { // Now, let's try to unify Collection<T> and Collection<Foo> solution is a map from T to Foo TypeUnifier.UnificationResult solution = TypeUnifier.unify( new TypeProjectionImpl(supertype), new TypeProjectionImpl(supertypeWithVariables), new Predicate<TypeConstructor>() { @Override public boolean apply(TypeConstructor typeConstructor) { ClassifierDescriptor descriptor = typeConstructor.getDeclarationDescriptor(); return descriptor instanceof TypeParameterDescriptor && variables.contains(descriptor); } }); substitution = Maps.newHashMap(solution.getSubstitution()); } else { // If there's no corresponding supertype, no variables are determined // This may be OK, e.g. in case 'Any as List<*>' substitution = Maps.newHashMapWithExpectedSize(variables.size()); } // If some of the parameters are not determined by unification, it means that these parameters // are lost, // let's put stars instead, so that we can only cast to something like List<*>, e.g. (a: Any) as // List<*> boolean allArgumentsInferred = true; for (TypeParameterDescriptor variable : variables) { TypeProjection value = substitution.get(variable.getTypeConstructor()); if (value == null) { substitution.put( variable.getTypeConstructor(), SubstitutionUtils.makeStarProjection(variable)); allArgumentsInferred = false; } } // At this point we have values for all type parameters of List // Let's make a type by substituting them: List<T> -> List<Foo> JetType substituted = TypeSubstitutor.create(substitution).substitute(subtypeWithVariables, Variance.INVARIANT); return new TypeReconstructionResult(substituted, allArgumentsInferred); }
public class FunctionDescriptorUtil { private static final TypeSubstitutor MAKE_TYPE_PARAMETERS_FRESH = TypeSubstitutor.create( new TypeSubstitution() { @Override public TypeProjection get(TypeConstructor key) { return null; } @Override public boolean isEmpty() { return false; } @Override public String toString() { return "FunctionDescriptorUtil.MAKE_TYPE_PARAMETERS_FRESH"; } }); public static Map<TypeConstructor, TypeProjection> createSubstitutionContext( @NotNull FunctionDescriptor functionDescriptor, List<JetType> typeArguments) { if (functionDescriptor.getTypeParameters().isEmpty()) return Collections.emptyMap(); Map<TypeConstructor, TypeProjection> result = new HashMap<TypeConstructor, TypeProjection>(); int typeArgumentsSize = typeArguments.size(); List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters(); assert typeArgumentsSize == typeParameters.size(); for (int i = 0; i < typeArgumentsSize; i++) { TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i); JetType typeArgument = typeArguments.get(i); result.put(typeParameterDescriptor.getTypeConstructor(), new TypeProjection(typeArgument)); } return result; } @Nullable public static List<ValueParameterDescriptor> getSubstitutedValueParameters( FunctionDescriptor substitutedDescriptor, @NotNull FunctionDescriptor functionDescriptor, @NotNull TypeSubstitutor substitutor) { List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(); List<ValueParameterDescriptor> unsubstitutedValueParameters = functionDescriptor.getValueParameters(); for (int i = 0, unsubstitutedValueParametersSize = unsubstitutedValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { ValueParameterDescriptor unsubstitutedValueParameter = unsubstitutedValueParameters.get(i); // TODO : Lazy? JetType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE); JetType varargElementType = unsubstitutedValueParameter.getVarargElementType(); JetType substituteVarargElementType = varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE); if (substitutedType == null) return null; result.add( new ValueParameterDescriptorImpl( substitutedDescriptor, unsubstitutedValueParameter, unsubstitutedValueParameter.getAnnotations(), unsubstitutedValueParameter.isVar(), substitutedType, substituteVarargElementType)); } return result; } @Nullable public static JetType getSubstitutedReturnType( @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) { return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE); } @Nullable public static FunctionDescriptor substituteFunctionDescriptor( @NotNull List<JetType> typeArguments, @NotNull FunctionDescriptor functionDescriptor) { Map<TypeConstructor, TypeProjection> substitutionContext = createSubstitutionContext(functionDescriptor, typeArguments); return functionDescriptor.substitute(TypeSubstitutor.create(substitutionContext)); } @NotNull public static JetScope getFunctionInnerScope( @NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) { WritableScope parameterScope = new WritableScopeImpl( outerScope, descriptor, new TraceBasedRedeclarationHandler(trace), "Function inner scope"); ReceiverParameterDescriptor receiver = descriptor.getReceiverParameter(); if (receiver != null) { parameterScope.setImplicitReceiver(receiver); } for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { parameterScope.addTypeParameterDescriptor(typeParameter); } for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) { parameterScope.addVariableDescriptor(valueParameterDescriptor); } parameterScope.addLabeledDeclaration(descriptor); parameterScope.changeLockLevel(WritableScope.LockLevel.READING); return parameterScope; } public static void initializeFromFunctionType( @NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType, @Nullable ReceiverParameterDescriptor expectedThisObject, @NotNull Modality modality, @NotNull Visibility visibility) { assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType); functionDescriptor.initialize( KotlinBuiltIns.getInstance().getReceiverType(functionType), expectedThisObject, Collections.<TypeParameterDescriptorImpl>emptyList(), KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, functionType), KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(functionType), modality, visibility); } public static <D extends CallableDescriptor> D alphaConvertTypeParameters(D candidate) { return (D) candidate.substitute(MAKE_TYPE_PARAMETERS_FRESH); } public static FunctionDescriptor getInvokeFunction(@NotNull JetType functionType) { assert KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(functionType); ClassifierDescriptor classDescriptorForFunction = functionType.getConstructor().getDeclarationDescriptor(); assert classDescriptorForFunction instanceof ClassDescriptor; Collection<FunctionDescriptor> invokeFunctions = ((ClassDescriptor) classDescriptorForFunction) .getMemberScope(functionType.getArguments()) .getFunctions(Name.identifier("invoke")); assert invokeFunctions.size() == 1; return invokeFunctions.iterator().next(); } }
@Nullable public static JetType getSubstitutedReturnType( @NotNull FunctionDescriptor functionDescriptor, TypeSubstitutor substitutor) { return substitutor.substitute(functionDescriptor.getReturnType(), Variance.OUT_VARIANCE); }