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 org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025 import org.jetbrains.jet.lang.descriptors.impl.*;
026 import org.jetbrains.jet.lang.psi.*;
027 import org.jetbrains.jet.lang.resolve.*;
028 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
029 import org.jetbrains.jet.lang.resolve.name.Name;
030 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
031 import org.jetbrains.jet.lang.types.DeferredType;
032 import org.jetbrains.jet.lang.types.ErrorUtils;
033 import org.jetbrains.jet.lang.types.JetType;
034 import org.jetbrains.jet.lang.types.JetTypeInfo;
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.Collections;
041 import java.util.List;
042
043 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
044 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
045 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
046 import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.CANT_INFER_LAMBDA_PARAM_TYPE;
047
048 public 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 }