diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index 44df643b150..1ead3251e54 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -574,7 +574,11 @@ public class JetControlFlowProcessor { @Override public void visitParameter(JetParameter parameter) { + JetExpression defaultValue = parameter.getDefaultValue(); builder.declare(parameter); + if (defaultValue != null) { + builder.read(defaultValue); + } builder.write(parameter, parameter); } @@ -838,6 +842,10 @@ public class JetControlFlowProcessor { @Override public void visitClass(JetClass klass) { + List parameters = klass.getPrimaryConstructorParameters(); + for (JetParameter parameter : parameters) { + value(parameter, inCondition); + } visitClassOrObject(klass); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 0fc0e09e4b7..ac9e50bd495 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -262,7 +262,12 @@ public class JetFlowInformationProvider { } if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) { varWithUninitializedErrorGenerated.add(variableDescriptor); - trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor)); + if (variableDescriptor instanceof ValueParameterDescriptor) { + trace.report(Errors.UNINITIALIZED_PARAMETER.on((JetSimpleNameExpression) element, (ValueParameterDescriptor) variableDescriptor)); + } + else { + trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor)); + } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java index 11cf22db63f..198cebc590b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertyDescriptor.java @@ -261,6 +261,9 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab propertyDescriptor, Lists.newArrayList(setter.getAnnotations()), setter.hasBody(), setter.isDefault()); + if (newSetter != null) { + newSetter.initialize(setter.getValueParameters().get(0).copy(newSetter)); + } propertyDescriptor.initialize(newGetter, newSetter); return propertyDescriptor; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java index f0590c49604..d2f34c8b70c 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/descriptors/PropertySetterDescriptor.java @@ -1,6 +1,5 @@ package org.jetbrains.jet.lang.descriptors; -import com.google.common.collect.Sets; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.types.JetStandardClasses; @@ -15,22 +14,28 @@ import java.util.Set; */ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { - private MutableValueParameterDescriptor parameter; + private ValueParameterDescriptor parameter; - public PropertySetterDescriptor(@NotNull Modality modality, @NotNull Visibility visibility, - @NotNull PropertyDescriptor correspondingProperty, @NotNull List annotations, - boolean hasBody, boolean isDefault) - { + public PropertySetterDescriptor(@NotNull Modality modality, + @NotNull Visibility visibility, + @NotNull PropertyDescriptor correspondingProperty, + @NotNull List annotations, + boolean hasBody, + boolean isDefault) { super(modality, visibility, correspondingProperty, annotations, "set-" + correspondingProperty.getName(), hasBody, isDefault); + if (isDefault) { + initializeDefault(); + } } - public void initialize(@NotNull MutableValueParameterDescriptor parameter) { + public void initialize(@NotNull ValueParameterDescriptor parameter) { assert this.parameter == null; this.parameter = parameter; } - public void setParameterType(@NotNull JetType type) { - parameter.setType(type); + public void initializeDefault() { + assert parameter == null; + parameter = new ValueParameterDescriptorImpl(this, 0, Collections.emptyList(), "<>", null, getCorrespondingProperty().getReturnType(), false, null); } @NotNull @@ -42,7 +47,7 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor { @NotNull @Override public List getValueParameters() { - return Collections.singletonList(parameter); + return Collections.singletonList(parameter); } @NotNull diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 72f82897c6b..1485bb0056b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -150,7 +150,8 @@ public interface Errors { }; PsiElementOnlyDiagnosticFactory3 VIRTUAL_MEMBER_HIDDEN = PsiElementOnlyDiagnosticFactory3.create(ERROR, "''{0}'' hides ''{1}'' in class {2} and needs 'override' modifier", DescriptorRenderer.TEXT); - PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); + PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); + PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_PARAMETER = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Parameter ''{0}'' is uninitialized here", NAME); UnusedElementDiagnosticFactory UNUSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is never used", NAME); UnusedElementDiagnosticFactory UNUSED_PARAMETER = UnusedElementDiagnosticFactory.create(WARNING, "Parameter ''{0}'' is never used", NAME); UnusedElementDiagnosticFactory ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = UnusedElementDiagnosticFactory.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java index 81e0f647999..02c127040b6 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BodyResolver.java @@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.Pair; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.containers.Queue; import org.jetbrains.annotations.NotNull; @@ -48,6 +49,7 @@ public class BodyResolver { resolvePropertyDeclarationBodies(); resolveAnonymousInitializers(); + resolvePrimaryConstructorParameters(); resolveSecondaryConstructorBodies(); resolveFunctionBodies(); @@ -250,6 +252,17 @@ public class BodyResolver { } } + private void resolvePrimaryConstructorParameters() { + for (Map.Entry entry : context.getClasses().entrySet()) { + JetClass klass = entry.getKey(); + MutableClassDescriptor classDescriptor = entry.getValue(); + ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); + if (unsubstitutedPrimaryConstructor != null) { + checkDefaultParameterValues(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(), classDescriptor.getScopeForInitializers()); + } + } + } + private void resolveSecondaryConstructorBodies() { for (Map.Entry entry : this.context.getConstructors().entrySet()) { JetSecondaryConstructor constructor = entry.getKey(); @@ -332,8 +345,10 @@ public class BodyResolver { if (bodyExpression != null) { ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace); - typeInferrer.checkFunctionReturnType(scopeForConstructorBody, declaration, JetStandardClasses.getUnitType()); + typeInferrer.checkFunctionReturnType(scopeForConstructorBody, declaration, descriptor, JetStandardClasses.getUnitType()); } + + checkDefaultParameterValues(declaration.getValueParameters(), descriptor.getValueParameters(), scopeForConstructorBody); } private void resolvePropertyDeclarationBodies() { @@ -477,17 +492,25 @@ public class BodyResolver { if (!context.completeAnalysisNeeded(function)) return; JetExpression bodyExpression = function.getBodyExpression(); + JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace); if (bodyExpression != null) { - //JetFlowInformationProvider flowInformationProvider = context.getDescriptorResolver().computeFlowData(function.asElement(), bodyExpression); ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace); - typeInferrer.checkFunctionReturnType(declaringScope, function, functionDescriptor); + typeInferrer.checkFunctionReturnType(functionInnerScope, function, functionDescriptor); } - ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace); List valueParameters = function.getValueParameters(); + List valueParameterDescriptors = functionDescriptor.getValueParameters(); + + checkDefaultParameterValues(valueParameters, valueParameterDescriptors, functionInnerScope); + + assert functionDescriptor.getReturnType() != null; + } + + private void checkDefaultParameterValues(List valueParameters, List valueParameterDescriptors, JetScope declaringScope) { + ExpressionTypingServices typeInferrer = context.getSemanticServices().getTypeInferrerServices(trace); for (int i = 0; i < valueParameters.size(); i++) { - ValueParameterDescriptor valueParameterDescriptor = functionDescriptor.getValueParameters().get(i); + ValueParameterDescriptor valueParameterDescriptor = valueParameterDescriptors.get(i); if (valueParameterDescriptor.hasDefaultValue()) { JetParameter jetParameter = valueParameters.get(i); JetExpression defaultValue = jetParameter.getDefaultValue(); @@ -496,8 +519,6 @@ public class BodyResolver { } } } - - assert functionDescriptor.getReturnType() != null; } private void computeDeferredTypes() { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 87b1f0a72b2..193c860e02b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -707,6 +707,10 @@ public class DescriptorResolver { MutableValueParameterDescriptor valueParameterDescriptor = resolveValueParameterDescriptor(setterDescriptor, parameter, 0, type); setterDescriptor.initialize(valueParameterDescriptor); } + else { + setterDescriptor.initializeDefault(); + } + trace.record(BindingContext.PROPERTY_ACCESSOR, setter, setterDescriptor); } else if (property.isVar()) { @@ -841,11 +845,12 @@ public class DescriptorResolver { DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), name == null ? "" : name ); + JetType inType = isMutable ? type : null; + propertyDescriptor.setType(inType, type, Collections.emptyList(), ReceiverDescriptor.NO_RECEIVER); + PropertyGetterDescriptor getter = createDefaultGetter(propertyDescriptor); PropertySetterDescriptor setter = createDefaultSetter(propertyDescriptor); - JetType inType = isMutable ? type : null; - propertyDescriptor.setType(inType, type, Collections.emptyList(), ReceiverDescriptor.NO_RECEIVER); propertyDescriptor.initialize(getter, setter); getter.initialize(propertyDescriptor.getOutType()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index a6be38a744c..66769cd0f6e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -18,13 +18,17 @@ import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.CommonSupertypes; +import org.jetbrains.jet.lang.types.ErrorUtils; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lexer.JetTokens; import java.util.*; import static org.jetbrains.jet.lang.diagnostics.Errors.TYPE_MISMATCH; -import static org.jetbrains.jet.lang.resolve.BindingContext.*; +import static org.jetbrains.jet.lang.resolve.BindingContext.LABEL_TARGET; +import static org.jetbrains.jet.lang.resolve.BindingContext.STATEMENT; import static org.jetbrains.jet.lang.types.TypeUtils.FORBIDDEN; import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE; @@ -76,10 +80,6 @@ public class ExpressionTypingServices { // return ((ExpressionTypingContext) ExpressionTyperVisitorWithNamespaces).INSTANCE.getType(expression, ExpressionTypingContext.newRootContext(semanticServices, trace, scope, DataFlowInfo.getEmpty(), TypeUtils.NO_EXPECTED_TYPE, TypeUtils.NO_EXPECTED_TYPE)); } - public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { - checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.EMPTY); - } - @NotNull public JetType inferFunctionReturnType(@NotNull JetScope outerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor) { Map typeMap = collectReturnedExpressionsWithTypes(trace, outerScope, function, functionDescriptor); @@ -89,24 +89,30 @@ public class ExpressionTypingServices { : CommonSupertypes.commonSupertype(types); } - public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType) { - checkFunctionReturnType(function, ExpressionTypingContext.newContext( - semanticServices, new HashMap(), new HashMap>(), new LabelResolver(), - trace, functionInnerScope, DataFlowInfo.EMPTY, NO_EXPECTED_TYPE, expectedReturnType, false - )); + + public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { + checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, null); } + public void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @Nullable JetType expectedReturnType) { + checkFunctionReturnType(functionInnerScope, function, functionDescriptor, DataFlowInfo.EMPTY, expectedReturnType); + } ///////////////////////////////////////////////////////// - /*package*/ void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, DataFlowInfo dataFlowInfo) { - JetType expectedReturnType = functionDescriptor.getReturnType(); - if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) { - expectedReturnType = NO_EXPECTED_TYPE; + /*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo) { + checkFunctionReturnType(functionInnerScope, function, functionDescriptor, dataFlowInfo, null); + } + + /*package*/ void checkFunctionReturnType(@NotNull JetScope functionInnerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, @NotNull DataFlowInfo dataFlowInfo, @Nullable JetType expectedReturnType) { + if (expectedReturnType == null) { + expectedReturnType = functionDescriptor.getReturnType(); + if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) { + expectedReturnType = NO_EXPECTED_TYPE; + } } - JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace); checkFunctionReturnType(function, ExpressionTypingContext.newContext( - semanticServices, new HashMap(), new HashMap>(), new LabelResolver(), - trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType, false + semanticServices, new HashMap(), new HashMap>(), new LabelResolver(), + trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType, false )); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index c483bfff97c..dcf5dbb77a8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.types.expressions; +import com.intellij.openapi.util.Pair; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,6 +13,7 @@ import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace; import org.jetbrains.jet.lang.resolve.TopDownAnalyzer; import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.ResolvedCall; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.types.JetStandardClasses; @@ -108,7 +110,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito public JetType visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) { FunctionDescriptorImpl functionDescriptor = context.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function); scope.addFunctionDescriptor(functionDescriptor); - context.getServices().checkFunctionReturnType(context.scope, function, functionDescriptor, context.dataFlowInfo); + JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); + context.getServices().checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.dataFlowInfo); return checkExpectedType(function, context); } diff --git a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.jet b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.jet index 67d360888da..5e178a2ac17 100644 --- a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.jet +++ b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.jet @@ -1,5 +1,15 @@ val x = "" -fun bar(x : Int = "", y : Int = x, z : String = y) { +fun bar(x : Int = "", y : Int = x, z : String = y) { -} \ No newline at end of file +} + +// KT-371 Resolve default parameters for constructors + +class A(x : Int = y, y : Int = x) { // None of the references is resolved, no types checked + this(bool: Boolean, a: Int = b, b: String = a) : this(1) {} +} + +val z = 3 + +fun foo(x: Int = y, y: Int = x, i : Int = z): Int = x + y \ No newline at end of file