001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.lang.types.expressions; 018 019import com.google.common.collect.Lists; 020import com.intellij.psi.PsiElement; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.jet.lang.descriptors.*; 024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 025import org.jetbrains.jet.lang.descriptors.impl.*; 026import org.jetbrains.jet.lang.psi.*; 027import org.jetbrains.jet.lang.resolve.*; 028import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; 029import org.jetbrains.jet.lang.resolve.name.Name; 030import org.jetbrains.jet.lang.resolve.scopes.JetScope; 031import org.jetbrains.jet.lang.types.DeferredType; 032import org.jetbrains.jet.lang.types.ErrorUtils; 033import org.jetbrains.jet.lang.types.JetType; 034import org.jetbrains.jet.lang.types.JetTypeInfo; 035import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 036import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 037import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValueWithDefault; 038import org.jetbrains.jet.util.slicedmap.WritableSlice; 039 040import java.util.Collections; 041import java.util.List; 042 043import static org.jetbrains.jet.lang.diagnostics.Errors.*; 044import static org.jetbrains.jet.lang.resolve.BindingContext.*; 045import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; 046import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.CANT_INFER_LAMBDA_PARAM_TYPE; 047 048public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { 049 protected ClosureExpressionsTypingVisitor(@NotNull ExpressionTypingInternals facade) { 050 super(facade); 051 } 052 053 @Override 054 public JetTypeInfo visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) { 055 DelegatingBindingTrace delegatingBindingTrace = context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration()); 056 if (delegatingBindingTrace != null) { 057 delegatingBindingTrace.addAllMyDataTo(context.trace); 058 JetType type = context.trace.get(EXPRESSION_TYPE, expression); 059 return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo); 060 } 061 final JetType[] result = new JetType[1]; 062 final TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve object literal expression", expression); 063 ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() { 064 065 @Override 066 public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) { 067 if (slice == CLASS && declaration == expression.getObjectDeclaration()) { 068 JetType defaultType = DeferredType.create(context.trace, new RecursionIntolerantLazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) { 069 @Override 070 protected JetType compute() { 071 return descriptor.getDefaultType(); 072 } 073 }); 074 result[0] = defaultType; 075 if (!context.trace.get(PROCESSED, expression)) { 076 temporaryTrace.record(EXPRESSION_TYPE, expression, defaultType); 077 temporaryTrace.record(PROCESSED, expression); 078 } 079 } 080 } 081 }; 082 ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace); 083 traceAdapter.addHandler(CLASS, handler); 084 TopDownAnalyzer.processClassOrObject(context.expressionTypingServices.getProject(), traceAdapter, context.scope, 085 context.scope.getContainingDeclaration(), expression.getObjectDeclaration()); 086 087 DelegatingBindingTrace cloneDelta = new DelegatingBindingTrace( 088 new BindingTraceContext().getBindingContext(), "cached delta trace for object literal expression resolve", expression); 089 temporaryTrace.addAllMyDataTo(cloneDelta); 090 context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta); 091 temporaryTrace.commit(); 092 return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo); 093 } 094 095 @Override 096 public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) { 097 JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression(); 098 if (bodyExpression == null) return null; 099 100 JetType expectedType = context.expectedType; 101 boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType( 102 expectedType); 103 104 AnonymousFunctionDescriptor functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected); 105 JetType safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected); 106 functionDescriptor.setReturnType(safeReturnType); 107 108 JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter()); 109 List<JetType> valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters()); 110 JetType resultType = KotlinBuiltIns.getInstance().getFunctionType( 111 Collections.<AnnotationDescriptor>emptyList(), receiver, valueParametersTypes, safeReturnType); 112 if (expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) { 113 // all checks were done before 114 return JetTypeInfo.create(resultType, context.dataFlowInfo); 115 } 116 return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo); 117 } 118 119 @NotNull 120 private static AnonymousFunctionDescriptor createFunctionDescriptor( 121 @NotNull JetFunctionLiteralExpression expression, 122 @NotNull ExpressionTypingContext context, 123 boolean functionTypeExpected 124 ) { 125 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); 126 JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef(); 127 AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor( 128 context.scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), CallableMemberDescriptor.Kind.DECLARATION); 129 130 List<ValueParameterDescriptor> valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral, functionDescriptor, functionTypeExpected); 131 132 JetType effectiveReceiverType; 133 if (receiverTypeRef == null) { 134 if (functionTypeExpected) { 135 effectiveReceiverType = KotlinBuiltIns.getInstance().getReceiverType(context.expectedType); 136 } 137 else { 138 effectiveReceiverType = null; 139 } 140 } 141 else { 142 effectiveReceiverType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef, context.trace, true); 143 } 144 functionDescriptor.initialize(effectiveReceiverType, 145 ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER, 146 Collections.<TypeParameterDescriptorImpl>emptyList(), 147 valueParameterDescriptors, 148 /*unsubstitutedReturnType = */ null, 149 Modality.FINAL, 150 Visibilities.LOCAL, 151 /*isInline = */ false 152 ); 153 BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor); 154 return functionDescriptor; 155 } 156 157 @NotNull 158 private static List<ValueParameterDescriptor> createValueParameterDescriptors( 159 @NotNull ExpressionTypingContext context, 160 @NotNull JetFunctionLiteral functionLiteral, 161 @NotNull FunctionDescriptorImpl functionDescriptor, 162 boolean functionTypeExpected 163 ) { 164 List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList(); 165 List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters(); 166 167 List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected) 168 ? KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, context.expectedType) 169 : null; 170 171 JetParameterList valueParameterList = functionLiteral.getValueParameterList(); 172 boolean hasDeclaredValueParameters = valueParameterList != null; 173 if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) { 174 ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0); 175 ValueParameterDescriptor it = new ValueParameterDescriptorImpl( 176 functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"), 177 valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType() 178 ); 179 valueParameterDescriptors.add(it); 180 context.trace.record(AUTO_CREATED_IT, it); 181 } 182 else { 183 if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { 184 List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); 185 context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); 186 } 187 for (int i = 0; i < declaredValueParameters.size(); i++) { 188 ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor( 189 context, functionDescriptor, declaredValueParameters, expectedValueParameters, i); 190 valueParameterDescriptors.add(valueParameterDescriptor); 191 } 192 } 193 return valueParameterDescriptors; 194 } 195 196 @NotNull 197 private static ValueParameterDescriptor createValueParameterDescriptor( 198 @NotNull ExpressionTypingContext context, 199 @NotNull FunctionDescriptorImpl functionDescriptor, 200 @NotNull List<JetParameter> declaredValueParameters, 201 @Nullable List<ValueParameterDescriptor> expectedValueParameters, 202 int index 203 ) { 204 JetParameter declaredParameter = declaredValueParameters.get(index); 205 JetTypeReference typeReference = declaredParameter.getTypeReference(); 206 207 JetType expectedType; 208 if (expectedValueParameters != null && index < expectedValueParameters.size()) { 209 expectedType = expectedValueParameters.get(index).getType(); 210 } 211 else { 212 expectedType = null; 213 } 214 JetType type; 215 if (typeReference != null) { 216 type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true); 217 if (expectedType != null) { 218 if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) { 219 context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType)); 220 } 221 } 222 } 223 else { 224 if (expectedType == null || expectedType == CallResolverUtil.DONT_CARE || expectedType == CallResolverUtil.CANT_INFER_TYPE_PARAMETER) { 225 context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter)); 226 } 227 if (expectedType != null) { 228 type = expectedType; 229 } 230 else { 231 type = CANT_INFER_LAMBDA_PARAM_TYPE; 232 } 233 } 234 return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptorWithAnnotationArguments( 235 context.scope, functionDescriptor, declaredParameter, index, type, context.trace); 236 } 237 238 @NotNull 239 private static JetType computeReturnType( 240 @NotNull JetFunctionLiteralExpression expression, 241 @NotNull ExpressionTypingContext context, 242 @NotNull SimpleFunctionDescriptorImpl functionDescriptor, 243 boolean functionTypeExpected 244 ) { 245 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve function literal expression", expression); 246 JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(context.expectedType) : null; 247 JetType returnType = computeUnsafeReturnType(expression, context, functionDescriptor, temporaryTrace, expectedReturnType); 248 249 temporaryTrace.commit(new TraceEntryFilter() { 250 @Override 251 public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) { 252 return (slice != BindingContext.TRACE_DELTAS_CACHE); 253 } 254 }, true); 255 256 if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) { 257 if (KotlinBuiltIns.getInstance().isUnit(expectedReturnType)) { 258 return KotlinBuiltIns.getInstance().getUnitType(); 259 } 260 } 261 return returnType == null ? CANT_INFER_LAMBDA_PARAM_TYPE : returnType; 262 } 263 264 @Nullable 265 private static JetType computeUnsafeReturnType( 266 @NotNull JetFunctionLiteralExpression expression, 267 @NotNull ExpressionTypingContext context, 268 @NotNull SimpleFunctionDescriptorImpl functionDescriptor, 269 @NotNull TemporaryBindingTrace temporaryTrace, 270 @Nullable JetType expectedReturnType 271 ) { 272 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); 273 JetBlockExpression bodyExpression = functionLiteral.getBodyExpression(); 274 assert bodyExpression != null; 275 276 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); 277 JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); 278 if (returnTypeRef != null) { 279 JetType returnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true); 280 context.expressionTypingServices.checkFunctionReturnType(expression.getFunctionLiteral(), context.replaceScope(functionInnerScope). 281 replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace); 282 if (expectedReturnType != null) { 283 if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, expectedReturnType)) { 284 temporaryTrace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); 285 } 286 } 287 return returnType; 288 } 289 ExpressionTypingContext newContext = context.replaceExpectedType(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE) 290 .replaceBindingTrace(temporaryTrace); 291 return context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT, 292 newContext, temporaryTrace).getType(); 293 } 294}