From 74f65ba2cece76746a066f56ad9730f35fe435f4 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 23 Jan 2020 10:48:55 -0800 Subject: [PATCH 1/2] [ConstraintSystem] Find solutions for code with invalid '_' using holes. --- lib/Sema/CSDiag.cpp | 48 ------------------------------ lib/Sema/CSGen.cpp | 3 +- test/Constraints/diagnostics.swift | 2 +- test/Parse/matching_patterns.swift | 3 +- test/expr/expressions.swift | 2 +- 5 files changed, 5 insertions(+), 53 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index f6cbbee7a7b49..f3df3dcd02752 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1447,29 +1447,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { auto lhsType = CS.getType(lhsExpr)->getRValueType(); auto rhsType = CS.getType(rhsExpr)->getRValueType(); - // TODO(diagnostics): There are still cases not yet handled by new - // diagnostics framework e.g. - // - // var tuple = (1, 2, 3) - // switch tuple { - // case (let (_, _, _)) + 1: break - // } - if (callExpr->isImplicit() && overloadName == "~=") { - auto flags = ParameterTypeFlags(); - if (calleeInfo.candidates.size() == 1) - if (auto fnType = calleeInfo.candidates[0].getFunctionType()) - flags = fnType->getParams()[0].getParameterFlags(); - - auto *locator = CS.getConstraintLocator( - callExpr, - {ConstraintLocator::ApplyArgument, - LocatorPathElt::ApplyArgToParam(0, 0, flags)}, - /*summaryFlags=*/0); - - ArgumentMismatchFailure failure(CS, lhsType, rhsType, locator); - return failure.diagnosePatternMatchingMismatch(); - } - if (isContextualConversionFailure(argTuple)) return false; @@ -1754,22 +1731,6 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) { if (auto *assignment = dyn_cast(E)) { if (isa(assignment->getDest())) { auto *srcExpr = assignment->getSrc(); - - bool diagnosedInvalidUseOfDiscardExpr = false; - srcExpr->forEachChildExpr([&](Expr *expr) -> Expr * { - if (auto *DAE = dyn_cast(expr)) { - diagnose(DAE->getLoc(), diag::discard_expr_outside_of_assignment) - .highlight(srcExpr->getSourceRange()); - diagnosedInvalidUseOfDiscardExpr = true; - return nullptr; - } - - return expr; - }); - - if (diagnosedInvalidUseOfDiscardExpr) - return; - diagnoseAmbiguity(srcExpr); return; } @@ -1783,15 +1744,6 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) { return; } - // A DiscardAssignmentExpr (spelled "_") needs contextual type information to - // infer its type. If we see one at top level, diagnose that it must be part - // of an assignment so we don't get a generic "expression is ambiguous" error. - if (isa(E)) { - diagnose(E->getLoc(), diag::discard_expr_outside_of_assignment) - .highlight(E->getSourceRange()); - return; - } - // Diagnose ".foo" expressions that lack context specifically. if (auto UME = dyn_cast(E->getSemanticsProvidingExpr())) { diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 78402bbf3e69d..d25f93e0a0403 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2827,7 +2827,8 @@ namespace { Type visitDiscardAssignmentExpr(DiscardAssignmentExpr *expr) { auto locator = CS.getConstraintLocator(expr); - auto typeVar = CS.createTypeVariable(locator, TVO_CanBindToNoEscape); + auto typeVar = CS.createTypeVariable(locator, TVO_CanBindToNoEscape | + TVO_CanBindToHole); return LValueType::get(typeVar); } diff --git a/test/Constraints/diagnostics.swift b/test/Constraints/diagnostics.swift index f441234e43f92..c603df2c04b76 100644 --- a/test/Constraints/diagnostics.swift +++ b/test/Constraints/diagnostics.swift @@ -1271,7 +1271,7 @@ func badTypes() { // rdar://34357545 func unresolvedTypeExistential() -> Bool { return (Int.self==_{}) - // expected-error@-1 {{expression type 'Bool' is ambiguous without more context}} + // expected-error@-1 {{'_' can only appear in a pattern or on the left side of an assignment}} } func rdar43525641(_ a: Int, _ b: Int = 0, c: Int = 0, _ d: Int) {} diff --git a/test/Parse/matching_patterns.swift b/test/Parse/matching_patterns.swift index 39cadef2359ec..0448390a53a97 100644 --- a/test/Parse/matching_patterns.swift +++ b/test/Parse/matching_patterns.swift @@ -288,8 +288,7 @@ case (_, var e, 3) +++ (1, 2, 3): // expected-error@-2{{'var' binding pattern cannot appear in an expression}} () case (let (_, _, _)) + 1: -// expected-error@-1 2 {{'var' binding pattern cannot appear in an expression}} -// expected-error@-2 {{expression pattern of type 'Int' cannot match values of type '(Int, Int, Int)'}} +// expected-error@-1 {{expression pattern of type 'Int' cannot match values of type '(Int, Int, Int)'}} () } diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index d14e2671e841b..43af91bfcfebb 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -708,7 +708,7 @@ func test() { func unusedExpressionResults() { // Unused l-value _ // expected-error{{'_' can only appear in a pattern or on the left side of an assignment}} - + // expected-error@-1 {{expression resolves to an unused variable}} // Conditional Optional binding hides compiler error let optionalc:C? = nil From 689a57b8a084bf6642059b7323fef6bf595a3b21 Mon Sep 17 00:00:00 2001 From: Holly Borla Date: Thu, 23 Jan 2020 16:22:15 -0800 Subject: [PATCH 2/2] [CSDiag] Remove some dead code for diagnosing ambiguity from CSDiag. --- lib/Sema/CSDiag.cpp | 51 --------------------------------------------- 1 file changed, 51 deletions(-) diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index f3df3dcd02752..560d42041cb5a 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1494,41 +1494,6 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) { AnyFunctionType::decomposeInput(CS.getType(argExpr), params); auto argString = AnyFunctionType::getParamListAsString(params); - // If we couldn't get the name of the callee, then it must be something of a - // more complex "value of function type". - if (overloadName.empty()) { - // If we couldn't infer the result type of the closure expr, then we have - // some sort of ambiguity, let the ambiguity diagnostic stuff handle this. - if (auto ffty = fnType->getAs()) - if (ffty->getResult()->hasTypeVariable()) { - diagnoseAmbiguity(fnExpr); - return true; - } - - // The most common unnamed value of closure type is a ClosureExpr, so - // special case it. - if (isa(fnExpr->getValueProvidingExpr())) { - if (fnType->hasTypeVariable()) - diagnose(argExpr->getStartLoc(), diag::cannot_invoke_closure, argString) - .highlight(fnExpr->getSourceRange()); - else - diagnose(argExpr->getStartLoc(), diag::cannot_invoke_closure_type, - fnType, argString) - .highlight(fnExpr->getSourceRange()); - - } else if (fnType->hasTypeVariable()) { - diagnose(argExpr->getStartLoc(), diag::cannot_call_function_value, - argString) - .highlight(fnExpr->getSourceRange()); - } else { - diagnose(argExpr->getStartLoc(), diag::cannot_call_value_of_function_type, - fnType, argString) - .highlight(fnExpr->getSourceRange()); - } - - return true; - } - if (auto MTT = fnType->getAs()) { if (MTT->getInstanceType()->isExistentialType()) { diagnose(fnExpr->getLoc(), diag::construct_protocol_value, fnType); @@ -1755,22 +1720,6 @@ void FailureDiagnosis::diagnoseAmbiguity(Expr *E) { } } - // Diagnose empty collection literals that lack context specifically. - if (auto CE = dyn_cast(E->getSemanticsProvidingExpr())) { - if (CE->getNumElements() == 0) { - diagnose(E->getLoc(), diag::unresolved_collection_literal) - .highlight(E->getSourceRange()); - return; - } - } - - // Diagnose 'nil' without a contextual type. - if (isa(E->getSemanticsProvidingExpr())) { - diagnose(E->getLoc(), diag::unresolved_nil_literal) - .highlight(E->getSourceRange()); - return; - } - // Attempt to re-type-check the entire expression, allowing ambiguity, but // ignoring a contextual type. if (expr == E) {