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