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.replaceBindingTrace(traceAdapter),
085 context.scope.getContainingDeclaration(),
086 expression.getObjectDeclaration());
087
088 DelegatingBindingTrace cloneDelta = new DelegatingBindingTrace(
089 new BindingTraceContext().getBindingContext(), "cached delta trace for object literal expression resolve", expression);
090 temporaryTrace.addAllMyDataTo(cloneDelta);
091 context.trace.record(TRACE_DELTAS_CACHE, expression.getObjectDeclaration(), cloneDelta);
092 temporaryTrace.commit();
093 return DataFlowUtils.checkType(result[0], expression, context, context.dataFlowInfo);
094 }
095
096 @Override
097 public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext context) {
098 JetBlockExpression bodyExpression = expression.getFunctionLiteral().getBodyExpression();
099 if (bodyExpression == null) return null;
100
101 JetType expectedType = context.expectedType;
102 boolean functionTypeExpected = expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(
103 expectedType);
104
105 AnonymousFunctionDescriptor functionDescriptor = createFunctionDescriptor(expression, context, functionTypeExpected);
106 JetType safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected);
107 functionDescriptor.setReturnType(safeReturnType);
108
109 JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter());
110 List<JetType> valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters());
111 JetType resultType = KotlinBuiltIns.getInstance().getFunctionType(
112 Collections.<AnnotationDescriptor>emptyList(), receiver, valueParametersTypes, safeReturnType);
113 if (expectedType != NO_EXPECTED_TYPE && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) {
114 // all checks were done before
115 return JetTypeInfo.create(resultType, context.dataFlowInfo);
116 }
117 return DataFlowUtils.checkType(resultType, expression, context, context.dataFlowInfo);
118 }
119
120 @NotNull
121 private static AnonymousFunctionDescriptor createFunctionDescriptor(
122 @NotNull JetFunctionLiteralExpression expression,
123 @NotNull ExpressionTypingContext context,
124 boolean functionTypeExpected
125 ) {
126 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
127 JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef();
128 AnonymousFunctionDescriptor functionDescriptor = new AnonymousFunctionDescriptor(
129 context.scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), CallableMemberDescriptor.Kind.DECLARATION);
130
131 List<ValueParameterDescriptor> valueParameterDescriptors = createValueParameterDescriptors(context, functionLiteral, functionDescriptor, functionTypeExpected);
132
133 JetType effectiveReceiverType;
134 if (receiverTypeRef == null) {
135 if (functionTypeExpected) {
136 effectiveReceiverType = KotlinBuiltIns.getInstance().getReceiverType(context.expectedType);
137 }
138 else {
139 effectiveReceiverType = null;
140 }
141 }
142 else {
143 effectiveReceiverType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, receiverTypeRef, context.trace, true);
144 }
145 functionDescriptor.initialize(effectiveReceiverType,
146 ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER,
147 Collections.<TypeParameterDescriptorImpl>emptyList(),
148 valueParameterDescriptors,
149 /*unsubstitutedReturnType = */ null,
150 Modality.FINAL,
151 Visibilities.LOCAL,
152 /*isInline = */ false
153 );
154 BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor);
155 return functionDescriptor;
156 }
157
158 @NotNull
159 private static List<ValueParameterDescriptor> createValueParameterDescriptors(
160 @NotNull ExpressionTypingContext context,
161 @NotNull JetFunctionLiteral functionLiteral,
162 @NotNull FunctionDescriptorImpl functionDescriptor,
163 boolean functionTypeExpected
164 ) {
165 List<ValueParameterDescriptor> valueParameterDescriptors = Lists.newArrayList();
166 List<JetParameter> declaredValueParameters = functionLiteral.getValueParameters();
167
168 List<ValueParameterDescriptor> expectedValueParameters = (functionTypeExpected)
169 ? KotlinBuiltIns.getInstance().getValueParameters(functionDescriptor, context.expectedType)
170 : null;
171
172 JetParameterList valueParameterList = functionLiteral.getValueParameterList();
173 boolean hasDeclaredValueParameters = valueParameterList != null;
174 if (functionTypeExpected && !hasDeclaredValueParameters && expectedValueParameters.size() == 1) {
175 ValueParameterDescriptor valueParameterDescriptor = expectedValueParameters.get(0);
176 ValueParameterDescriptor it = new ValueParameterDescriptorImpl(
177 functionDescriptor, 0, Collections.<AnnotationDescriptor>emptyList(), Name.identifier("it"),
178 valueParameterDescriptor.getType(), valueParameterDescriptor.hasDefaultValue(), valueParameterDescriptor.getVarargElementType()
179 );
180 valueParameterDescriptors.add(it);
181 context.trace.record(AUTO_CREATED_IT, it);
182 }
183 else {
184 if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
185 List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters);
186 context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes));
187 }
188 for (int i = 0; i < declaredValueParameters.size(); i++) {
189 ValueParameterDescriptor valueParameterDescriptor = createValueParameterDescriptor(
190 context, functionDescriptor, declaredValueParameters, expectedValueParameters, i);
191 valueParameterDescriptors.add(valueParameterDescriptor);
192 }
193 }
194 return valueParameterDescriptors;
195 }
196
197 @NotNull
198 private static ValueParameterDescriptor createValueParameterDescriptor(
199 @NotNull ExpressionTypingContext context,
200 @NotNull FunctionDescriptorImpl functionDescriptor,
201 @NotNull List<JetParameter> declaredValueParameters,
202 @Nullable List<ValueParameterDescriptor> expectedValueParameters,
203 int index
204 ) {
205 JetParameter declaredParameter = declaredValueParameters.get(index);
206 JetTypeReference typeReference = declaredParameter.getTypeReference();
207
208 JetType expectedType;
209 if (expectedValueParameters != null && index < expectedValueParameters.size()) {
210 expectedType = expectedValueParameters.get(index).getType();
211 }
212 else {
213 expectedType = null;
214 }
215 JetType type;
216 if (typeReference != null) {
217 type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true);
218 if (expectedType != null) {
219 if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) {
220 context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType));
221 }
222 }
223 }
224 else {
225 if (expectedType == null || expectedType == CallResolverUtil.DONT_CARE || expectedType == CallResolverUtil.CANT_INFER_TYPE_PARAMETER) {
226 context.trace.report(CANNOT_INFER_PARAMETER_TYPE.on(declaredParameter));
227 }
228 if (expectedType != null) {
229 type = expectedType;
230 }
231 else {
232 type = CANT_INFER_LAMBDA_PARAM_TYPE;
233 }
234 }
235 return context.expressionTypingServices.getDescriptorResolver().resolveValueParameterDescriptorWithAnnotationArguments(
236 context.scope, functionDescriptor, declaredParameter, index, type, context.trace);
237 }
238
239 @NotNull
240 private static JetType computeReturnType(
241 @NotNull JetFunctionLiteralExpression expression,
242 @NotNull ExpressionTypingContext context,
243 @NotNull SimpleFunctionDescriptorImpl functionDescriptor,
244 boolean functionTypeExpected
245 ) {
246 TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve function literal expression", expression);
247 JetType expectedReturnType = functionTypeExpected ? KotlinBuiltIns.getInstance().getReturnTypeFromFunctionType(context.expectedType) : null;
248 JetType returnType = computeUnsafeReturnType(expression, context, functionDescriptor, temporaryTrace, expectedReturnType);
249
250 temporaryTrace.commit(new TraceEntryFilter() {
251 @Override
252 public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) {
253 return (slice != BindingContext.TRACE_DELTAS_CACHE);
254 }
255 }, true);
256
257 if (!expression.getFunctionLiteral().hasDeclaredReturnType() && functionTypeExpected) {
258 if (KotlinBuiltIns.getInstance().isUnit(expectedReturnType)) {
259 return KotlinBuiltIns.getInstance().getUnitType();
260 }
261 }
262 return returnType == null ? CANT_INFER_LAMBDA_PARAM_TYPE : returnType;
263 }
264
265 @Nullable
266 private static JetType computeUnsafeReturnType(
267 @NotNull JetFunctionLiteralExpression expression,
268 @NotNull ExpressionTypingContext context,
269 @NotNull SimpleFunctionDescriptorImpl functionDescriptor,
270 @NotNull TemporaryBindingTrace temporaryTrace,
271 @Nullable JetType expectedReturnType
272 ) {
273 JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
274 JetBlockExpression bodyExpression = functionLiteral.getBodyExpression();
275 assert bodyExpression != null;
276
277 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace);
278 JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef();
279 if (returnTypeRef != null) {
280 JetType returnType = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, returnTypeRef, context.trace, true);
281 context.expressionTypingServices.checkFunctionReturnType(expression.getFunctionLiteral(), context.replaceScope(functionInnerScope).
282 replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace);
283 if (expectedReturnType != null) {
284 if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, expectedReturnType)) {
285 temporaryTrace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType));
286 }
287 }
288 return returnType;
289 }
290 ExpressionTypingContext newContext = context.replaceExpectedType(expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE)
291 .replaceBindingTrace(temporaryTrace);
292 return context.expressionTypingServices.getBlockReturnedType(functionInnerScope, bodyExpression, CoercionStrategy.COERCION_TO_UNIT,
293 newContext, temporaryTrace).getType();
294 }
295 }