diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index b85e37691bb76..c0ff3daf3f172 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -560,6 +560,7 @@ Optional> GenericArgumentsMismatchFailure::getDiagnosticFor( case CTP_ReturnSingleExpr: return diag::cannot_convert_to_return_type; case CTP_DefaultParameter: + case CTP_AutoclosureDefaultParameter: return diag::cannot_convert_default_arg_value; case CTP_YieldByValue: return diag::cannot_convert_yield_value; @@ -2085,6 +2086,7 @@ getContextualNilDiagnostic(ContextualTypePurpose CTP) { case CTP_EnumCaseRawValue: return diag::cannot_convert_raw_initializer_value_nil; case CTP_DefaultParameter: + case CTP_AutoclosureDefaultParameter: return diag::cannot_convert_default_arg_value_nil; case CTP_YieldByValue: return diag::cannot_convert_yield_value_nil; @@ -2863,6 +2865,7 @@ ContextualFailure::getDiagnosticFor(ContextualTypePurpose context, case CTP_EnumCaseRawValue: return diag::cannot_convert_raw_initializer_value; case CTP_DefaultParameter: + case CTP_AutoclosureDefaultParameter: return forProtocol ? diag::cannot_convert_default_arg_value_protocol : diag::cannot_convert_default_arg_value; case CTP_YieldByValue: diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 09a1c7eda4973..e017aeb2cee63 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9130,6 +9130,7 @@ void ConstraintSystem::addContextualConversionConstraint( case CTP_ThrowStmt: case CTP_EnumCaseRawValue: case CTP_DefaultParameter: + case CTP_AutoclosureDefaultParameter: case CTP_ClosureResult: case CTP_DictionaryKey: case CTP_DictionaryValue: diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 0a9f90509187a..d1ca555020aea 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2107,6 +2107,14 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc, } } + // For an @autoclosure default parameter, we want to convert to the result + // type. Stash the autoclosure default parameter type. + FunctionType *autoclosureDefaultParamType = nullptr; + if (convertTypePurpose == CTP_AutoclosureDefaultParameter) { + autoclosureDefaultParamType = convertType.getType()->castTo(); + convertType.setType(autoclosureDefaultParamType->getResult()); + } + // Tell the constraint system what the contextual type is. This informs // diagnostics and is a hint for various performance optimizations. // FIXME: Look through LoadExpr. This is an egregious hack due to the @@ -2130,6 +2138,7 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc, allowFreeTypeVariables = FreeTypeVariableBinding::UnresolvedType; Type convertTo = convertType.getType(); + if (options.contains(TypeCheckExprFlags::ExpressionTypeMustBeOptional)) { assert(!convertTo && "convertType and type check options conflict"); auto *convertTypeLocator = @@ -2175,6 +2184,12 @@ Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc, } result = resultTarget->getAsExpr(); + // For an @autoclosure default parameter type, add the autoclosure + // conversion. + if (convertTypePurpose == CTP_AutoclosureDefaultParameter) { + result = cs.buildAutoClosureExpr(result, autoclosureDefaultParamType); + } + // Notify listener that we've applied the solution. if (listener) result = listener->appliedSolution(solution, result); @@ -2204,32 +2219,9 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue, DeclContext *DC, Type paramType, bool isAutoClosure) { assert(paramType && !paramType->hasError()); - - if (isAutoClosure) { - class AutoClosureListener : public ExprTypeCheckListener { - FunctionType *ParamType; - - public: - AutoClosureListener(FunctionType *paramType) - : ParamType(paramType) {} - - Expr *appliedSolution(constraints::Solution &solution, - Expr *expr) override { - auto &cs = solution.getConstraintSystem(); - return cs.buildAutoClosureExpr(expr, ParamType); - } - }; - - auto *fnType = paramType->castTo(); - AutoClosureListener listener(fnType); - return typeCheckExpression(defaultValue, DC, - TypeLoc::withoutLoc(fnType->getResult()), - CTP_DefaultParameter, TypeCheckExprOptions(), - &listener); - } - - return typeCheckExpression(defaultValue, DC, TypeLoc::withoutLoc(paramType), - CTP_DefaultParameter); + return typeCheckExpression( + defaultValue, DC, TypeLoc::withoutLoc(paramType), + isAutoClosure ? CTP_AutoclosureDefaultParameter : CTP_DefaultParameter); } Type TypeChecker:: @@ -3209,30 +3201,7 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, /*Implicit=*/true); // Check the expression as a condition. - // - // TODO: Type-check of `~=` operator can't (yet) use `typeCheckCondition` - // because that utilizes contextual type which interferes with diagnostics. - // We don't yet have a full access to pattern-matching context in - // constraint system, which is required to enable these situations - // to be properly diagnosed. - struct ConditionListener : public ExprTypeCheckListener { - // Add the appropriate Boolean constraint. - bool builtConstraints(ConstraintSystem &cs, Expr *expr) override { - // Otherwise, the result must be convertible to Bool. - auto boolDecl = cs.getASTContext().getBoolDecl(); - if (!boolDecl) - return true; - - // Condition must convert to Bool. - cs.addConstraint(ConstraintKind::Conversion, cs.getType(expr), - boolDecl->getDeclaredType(), - cs.getConstraintLocator(expr)); - return false; - } - }; - - ConditionListener listener; - bool hadError = !typeCheckExpression(matchCall, DC, &listener); + bool hadError = typeCheckCondition(matchCall, DC); // Save the type-checked expression in the pattern. EP->setMatchExpr(matchCall); // Set the type on the pattern. diff --git a/lib/Sema/TypeChecker.h b/lib/Sema/TypeChecker.h index 3c643d706e25e..341f00a9b0e63 100644 --- a/lib/Sema/TypeChecker.h +++ b/lib/Sema/TypeChecker.h @@ -133,6 +133,10 @@ enum ContextualTypePurpose { CTP_EnumCaseRawValue, ///< Raw value specified for "case X = 42" in enum. CTP_DefaultParameter, ///< Default value in parameter 'foo(a : Int = 42)'. + /// Default value in @autoclosure parameter + /// 'foo(a : @autoclosure () -> Int = 42)'. + CTP_AutoclosureDefaultParameter, + CTP_CalleeResult, ///< Constraint is placed on the result of a callee. CTP_CallArgument, ///< Call to function or operator requires type. CTP_ClosureResult, ///< Closure result expects a specific type.