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
017 package org.jetbrains.jet.lang.types.expressions;
018
019 import com.google.common.collect.Lists;
020 import com.intellij.psi.PsiElement;
021 import com.intellij.util.Function;
022 import com.intellij.util.containers.ContainerUtil;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
027 import org.jetbrains.jet.lang.descriptors.impl.*;
028 import org.jetbrains.jet.lang.psi.*;
029 import org.jetbrains.jet.lang.resolve.*;
030 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
031 import org.jetbrains.jet.lang.resolve.name.LabelName;
032 import org.jetbrains.jet.lang.resolve.name.Name;
033 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
034 import org.jetbrains.jet.lang.types.*;
035 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
036 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
037 import org.jetbrains.jet.util.lazy.RecursionIntolerantLazyValueWithDefault;
038 import org.jetbrains.jet.util.slicedmap.WritableSlice;
039
040 import java.util.Collection;
041 import java.util.Collections;
042 import java.util.List;
043
044 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
045 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
046 import static org.jetbrains.jet.lang.resolve.calls.context.ContextDependency.*;
047 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
048 import static org.jetbrains.jet.lang.types.TypeUtils.noExpectedType;
049 import static org.jetbrains.jet.lang.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
050 import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.CANT_INFER_LAMBDA_PARAM_TYPE;
051
052 public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
053 protected ClosureExpressionsTypingVisitor(@NotNull ExpressionTypingInternals facade) {
054 super(facade);
055 }
056
057 @Override
058 public JetTypeInfo visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final ExpressionTypingContext context) {
059 DelegatingBindingTrace delegatingBindingTrace = context.trace.get(TRACE_DELTAS_CACHE, expression.getObjectDeclaration());
060 if (delegatingBindingTrace != null) {
061 delegatingBindingTrace.addAllMyDataTo(context.trace);
062 JetType type = context.trace.get(EXPRESSION_TYPE, expression);
063 return DataFlowUtils.checkType(type, expression, context, context.dataFlowInfo);
064 }
065 final JetType[] result = new JetType[1];
066 final TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve object literal expression", expression);
067 ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor> handler = new ObservableBindingTrace.RecordHandler<PsiElement, ClassDescriptor>() {
068
069 @Override
070 public void handleRecord(WritableSlice<PsiElement, ClassDescriptor> slice, PsiElement declaration, final ClassDescriptor descriptor) {
071 if (slice == CLASS && declaration == expression.getObjectDeclaration()) {
072 JetType defaultType = DeferredType.create(context.trace, new RecursionIntolerantLazyValueWithDefault<JetType>(ErrorUtils.createErrorType("Recursive dependency")) {
073 @Override
074 protected JetType compute() {
075 return descriptor.getDefaultType();
076 }
077 });
078 result[0] = defaultType;
079 if (!context.trace.get(PROCESSED, expression)) {
080 temporaryTrace.record(EXPRESSION_TYPE, expression, defaultType);
081 temporaryTrace.record(PROCESSED, expression);
082 }
083 }
084 }
085 };
086 ObservableBindingTrace traceAdapter = new ObservableBindingTrace(temporaryTrace);
087 traceAdapter.addHandler(CLASS, handler);
088 TopDownAnalyzer.processClassOrObject(context.replaceBindingTrace(traceAdapter).replaceContextDependency(INDEPENDENT),
089 context.scope.getContainingDeclaration(),
090 expression.getObjectDeclaration());
091
092 DelegatingBindingTrace cloneDelta = new DelegatingBindingTrace(
093 new BindingTraceContext().getBindingContext(), "cached delta trace for object literal expression resolve", expression);
094 temporaryTrace.addAllMyDataTo(cloneDelta);
095 context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta);
096 temporaryTrace.commit();
097 return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo);
098 }
099
100 @Override
101 public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
102 JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
103 if (bodyExpression == null) return null;
104
105 Name callerName = getCallerName(expression);
106 if (callerName != null) {
107 context.labelResolver.enterLabeledElement(new LabelName(callerName.asString()), expression);
108 }
109
110 JetType expectedType = context.expectedType;
111 boolean functionTypeExpected = !noExpectedType(expectedType) && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(
112 expectedType);
113
114 AnonymousFunctionDescriptor functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected);
115 JetType safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected);
116 functionDescriptor.setReturnType(safeReturnType);
117
118 JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter());
119 List<JetType> valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters());
120 JetType resultType = KotlinBuiltIns.getInstance().getFunctionType(
121 Collections.<AnnotationDescriptor>emptyList(), receiver, valueParametersTypes, safeReturnType);
122 if (!noExpectedType(expectedType) && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) {
123 // all checks were done before
124 return JetTypeInfo.create(resultType, context.dataFlowInfo);
125 }
126
127 if (callerName != null) {
128 context.labelResolver.exitLabeledElement(expression);
129 }
130
131 return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
132 }
133
134 @Nullable
135 private static Name getCallerName(@NotNull JetFunctionLiteralExpression expression) {
136 JetCallExpression callExpression = getContainingCallExpression(expression);
137 if (callExpression == null) return null;
138
139 JetExpression calleeExpression = callExpression.getCalleeExpression();
140 if (calleeExpression instanceof JetSimpleNameExpression) {
141 JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) calleeExpression;
142 return nameExpression.getReferencedNameAsName();
143 }
144
145 return null;
146 }
147
148 @Nullable
149 private static JetCallExpression getContainingCallExpression(JetFunctionLiteralExpression expression) {
150 PsiElement parent = expression.getParent();
151 if (parent instanceof JetCallExpression) {
152 // f {}
153 return (JetCallExpression) parent;
154 }
155
156 if (parent instanceof JetValueArgument) {
157 // f ({}) or f(p = {})
158 JetValueArgument argument = (JetValueArgument) parent;
159 PsiElement argList = argument.getParent();
160 if (argList == null) return null;
161 PsiElement call = argList.getParent();
162 if (call instanceof JetCallExpression) {
163 return (JetCallExpression) call;
164 }
165 }
166 return null;
167 }
168
169 @NotNull
170 private static AnonymousFunctionDescriptor createFunctionDescriptor(
171 @NotNull JetFunctionLiteralExpression expression,
172 @NotNull ExpressionTypingContext context,
173 boolean functionTypeExpected
174 ) {
175 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
176 JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef();
177 AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
178 context.scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), CallableMemberDescriptor.Kind.DECLARATION);
179
180 List<ValueParameterDescriptor> valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral,
181 functionDescriptor, functionTypeExpected);
182
183 JetType effectiveReceiverType;
184 if (receiverTypeRef == null) {
185 if (functionTypeExpected) {
186 effectiveReceiverType = KotlinBuiltIns.getInstance().getReceiverType(context.expectedType);
187 }
188 else {
189 effectiveReceiverType = null;
190 }
191 }
192 else {
193 effectiveReceiverType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef, context.trace, true);
194 }
195 functionDescriptor.initialize(effectiveReceiverType,
196 ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
197 Collections.<TypeParameterDescriptorImpl>emptyList(),
198 valueParameterDescriptors,
199 /*unsubstitutedReturnType = */ null,
200 Modality.FINAL,
201 Visibilities.LOCAL,
202 /*isInline = */ false
203 );
204 BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor);
205 return functionDescriptor;
206 }
207
208 @NotNull
209 private static List<ValueParameterDescriptor> createValueParameterDescriptors(
210 @NotNull ExpressionTypingContext context,
211 @NotNull JetFunctionLiteral functionLiteral,
212 @NotNull FunctionDescriptorImpl functionDescriptor,
213 boolean functionTypeExpected
214 ) {
215 List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
216 List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters();
217
218 List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected)
219 ? KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, context.expectedType)
220 : null;
221
222 JetParameterList valueParameterList = functionLiteral.getValueParameterList();
223 boolean hasDeclaredValueParameters = valueParameterList != null;
224 if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) {
225 ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
226 ValueParameterDescriptor it = new ValueParameterDescriptorImpl(
227 functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"),
228 valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()
229 );
230 valueParameterDescriptors.add(it);
231 context.trace.record(AUTO_CREATED_IT, it);
232 }
233 else {
234 if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
235 List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters);
236 context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes));
237 }
238 for (int i = 0; i < declaredValueParameters.size(); i++) {
239 ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor(
240 context, functionDescriptor, declaredValueParameters, expectedValueParameters, i);
241 valueParameterDescriptors.add(valueParameterDescriptor);
242 }
243 }
244 return valueParameterDescriptors;
245 }
246
247 @NotNull
248 private static ValueParameterDescriptor createValueParameterDescriptor(
249 @NotNull ExpressionTypingContext context,
250 @NotNull FunctionDescriptorImpl functionDescriptor,
251 @NotNull List<JetParameter> declaredValueParameters,
252 @Nullable List<ValueParameterDescriptor> expectedValueParameters,
253 int index
254 ) {
255 JetParameter declaredParameter = declaredValueParameters.get(index);
256 JetTypeReference typeReference = declaredParameter.getTypeReference();
257
258 JetType expectedType;
259 if (expectedValueParameters != null && index < expectedValueParameters.size()) {
260 expectedType = expectedValueParameters.get(index).getType();
261 }
262 else {
263 expectedType = null;
264 }
265 JetType type;
266 if (typeReference != null) {
267 type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true);
268 if (expectedType != null) {
269 if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) {
270 context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType));
271 }
272 }
273 }
274 else {
275 if (expectedType == null || expectedType == CallResolverUtil.DONT_CARE || expectedType == CallResolverUtil.CANT_INFER_TYPE_PARAMETER) {
276 context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter));
277 }
278 if (expectedType != null) {
279 type = expectedType;
280 }
281 else {
282 type = CANT_INFER_LAMBDA_PARAM_TYPE;
283 }
284 }
285 return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptorWithAnnotationArguments(
286 context.scope, functionDescriptor, declaredParameter, index, type, context.trace);
287 }
288
289 @NotNull
290 private static JetType computeReturnType(
291 @NotNull JetFunctionLiteralExpression expression,
292 @NotNull ExpressionTypingContext context,
293 @NotNull SimpleFunctionDescriptorImpl functionDescriptor,
294 boolean functionTypeExpected
295 ) {
296 JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(context.expectedType) : null;
297 JetType returnType = computeUnsafeReturnType(expression, context, functionDescriptor, expectedReturnType);
298
299 if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
300 if (KotlinBuiltIns.getInstance().isUnit(expectedReturnType)) {
301 return KotlinBuiltIns.getInstance().getUnitType();
302 }
303 }
304 return returnType == null ? CANT_INFER_LAMBDA_PARAM_TYPE : returnType;
305 }
306
307 @Nullable
308 private static JetType computeUnsafeReturnType(
309 @NotNull JetFunctionLiteralExpression expression,
310 @NotNull ExpressionTypingContext context,
311 @NotNull SimpleFunctionDescriptorImpl functionDescriptor,
312 @Nullable JetType expectedReturnType
313 ) {
314 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
315 JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
316 assert bodyExpression != null;
317
318 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
319 JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
320 JetType declaredReturnType = null;
321 if (returnTypeRef != null) {
322 declaredReturnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true);
323 // This is needed for ControlStructureTypingVisitor#visitReturnExpression() to properly type-check returned expressions
324 functionDescriptor.setReturnType(declaredReturnType);
325 if (expectedReturnType != null) {
326 if (!JetTypeChecker.INSTANCE.isSubtypeOf(declaredReturnType, expectedReturnType)) {
327 context.trace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType));
328 }
329 }
330 }
331
332 // Type-check the body
333 ExpressionTypingContext newContext = context.replaceScope(functionInnerScope)
334 .replaceExpectedType(declaredReturnType != null
335 ? declaredReturnType
336 : (expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE));
337
338 JetType typeOfBodyExpression = context.expressionTypingServices.getBlockReturnedType(bodyExpression, COERCION_TO_UNIT, newContext).getType();
339
340 List<JetType> returnedExpressionTypes = Lists.newArrayList(getTypesOfLocallyReturnedExpressions(
341 functionLiteral, context.trace, collectReturns(bodyExpression)));
342 ContainerUtil.addIfNotNull(returnedExpressionTypes, typeOfBodyExpression);
343
344 if (declaredReturnType != null) return declaredReturnType;
345 if (returnedExpressionTypes.isEmpty()) return null;
346 return CommonSupertypes.commonSupertype(returnedExpressionTypes);
347 }
348
349 private static List<JetType> getTypesOfLocallyReturnedExpressions(
350 final JetFunctionLiteral functionLiteral,
351 final BindingTrace trace,
352 Collection<JetReturnExpression> returnExpressions
353 ) {
354 return ContainerUtil.mapNotNull(returnExpressions, new Function<JetReturnExpression, JetType>() {
355 @Override
356 public JetType fun(JetReturnExpression returnExpression) {
357 JetSimpleNameExpression label = returnExpression.getTargetLabel();
358 if (label == null) {
359 // No label => non-local return
360 return null;
361 }
362
363 PsiElement labelTarget = trace.get(BindingContext.LABEL_TARGET, label);
364 if (labelTarget != functionLiteral) {
365 // Either a local return of inner lambda/function or a non-local return
366 return null;
367 }
368
369 JetExpression returnedExpression = returnExpression.getReturnedExpression();
370 if (returnedExpression == null) {
371 return KotlinBuiltIns.getInstance().getUnitType();
372 }
373 JetType returnedType = trace.get(EXPRESSION_TYPE, returnedExpression);
374 assert returnedType != null : "No type for returned expression: " + returnedExpression + ",\n" +
375 "the type should have been computed by getBlockReturnedType() above";
376 return returnedType;
377 }
378 });
379 }
380
381 public static Collection<JetReturnExpression> collectReturns(@NotNull JetExpression expression) {
382 Collection<JetReturnExpression> result = Lists.newArrayList();
383 expression.accept(
384 new JetTreeVisitor<Collection<JetReturnExpression>>() {
385 @Override
386 public Void visitReturnExpression(
387 JetReturnExpression expression, Collection<JetReturnExpression> data
388 ) {
389 data.add(expression);
390 return null;
391 }
392 },
393 result
394 );
395 return result;
396 }
397 }