Skip to content

Commit 87cd363

Browse files
committed
---
yaml --- r: 326007 b: refs/heads/master-next c: 93b39c9 h: refs/heads/master i: 326005: b5ea6b1 326003: 4e41ece 325999: f70de4b
1 parent 1603fdc commit 87cd363

File tree

7 files changed

+113
-24
lines changed

7 files changed

+113
-24
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: e052da7d8886fa0439677852e8f7830b20c2e1da
3-
refs/heads/master-next: 1a57fc403a4ccdc194d2a0d501632422b9e2e70a
3+
refs/heads/master-next: 93b39c9c2324f853e4c8515d1f9ce9071bc0e625
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea
66
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-b: 66d897bfcf64a82cb9a87f5e663d889189d06d07

branches/master-next/lib/Sema/CSDiag.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4080,23 +4080,22 @@ bool FailureDiagnosis::visitApplyExpr(ApplyExpr *callExpr) {
40804080
callExpr->getLoc()))
40814081
return true;
40824082

4083+
// TODO(diagnostics): There are still cases not yet handled by new
4084+
// diagnostics framework e.g.
4085+
//
4086+
// var tuple = (1, 2, 3)
4087+
// switch tuple {
4088+
// case (let (_, _, _)) + 1: break
4089+
// }
40834090
if (callExpr->isImplicit() && overloadName == "~=") {
4084-
// This binop was synthesized when typechecking an expression pattern.
4085-
auto diag = lhsType->is<UnresolvedType>()
4086-
? diagnose(lhsExpr->getLoc(),
4087-
diag::cannot_match_unresolved_expr_pattern_with_value,
4088-
rhsType)
4089-
: diagnose(lhsExpr->getLoc(),
4090-
diag::cannot_match_expr_pattern_with_value,
4091-
lhsType, rhsType);
4092-
diag.highlight(lhsExpr->getSourceRange());
4093-
diag.highlight(rhsExpr->getSourceRange());
4094-
if (auto optUnwrappedType = rhsType->getOptionalObjectType()) {
4095-
if (lhsType->isEqual(optUnwrappedType)) {
4096-
diag.fixItInsertAfter(lhsExpr->getEndLoc(), "?");
4097-
}
4098-
}
4099-
return true;
4091+
auto *locator =
4092+
CS.getConstraintLocator(callExpr,
4093+
{ConstraintLocator::ApplyArgument,
4094+
LocatorPathElt::ApplyArgToParam(0, 0)},
4095+
/*summaryFlags=*/0);
4096+
4097+
ArgumentMismatchFailure failure(expr, CS, lhsType, rhsType, locator);
4098+
return failure.diagnosePatternMatchingMismatch();
41004099
}
41014100

41024101
// Diagnose attempts to compare reference equality of certain types.

branches/master-next/lib/Sema/CSDiagnostics.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4455,6 +4455,9 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
44554455
if (diagnoseArchetypeMismatch())
44564456
return true;
44574457

4458+
if (diagnosePatternMatchingMismatch())
4459+
return true;
4460+
44584461
auto argType = getFromType();
44594462
auto paramType = getToType();
44604463

@@ -4488,17 +4491,46 @@ bool ArgumentMismatchFailure::diagnoseAsNote() {
44884491
auto argToParam = locator->findFirst<LocatorPathElt::ApplyArgToParam>();
44894492
assert(argToParam);
44904493

4491-
if (auto overload = getChoiceFor(getRawAnchor())) {
4492-
if (auto *decl = overload->choice.getDeclOrNull()) {
4493-
emitDiagnostic(decl, diag::candidate_has_invalid_argument_at_position,
4494-
getToType(), argToParam->getParamIdx());
4495-
return true;
4496-
}
4494+
if (auto *decl = getDecl()) {
4495+
emitDiagnostic(decl, diag::candidate_has_invalid_argument_at_position,
4496+
getToType(), argToParam->getParamIdx());
4497+
return true;
44974498
}
44984499

44994500
return false;
45004501
}
45014502

4503+
bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const {
4504+
if (!isArgumentOfPatternMatchingOperator(getLocator()))
4505+
return false;
4506+
4507+
auto *op = cast<BinaryExpr>(getRawAnchor());
4508+
auto *lhsExpr = op->getArg()->getElement(0);
4509+
auto *rhsExpr = op->getArg()->getElement(1);
4510+
4511+
auto lhsType = getType(lhsExpr)->getRValueType();
4512+
auto rhsType = getType(rhsExpr)->getRValueType();
4513+
4514+
auto diagnostic =
4515+
lhsType->is<UnresolvedType>()
4516+
? emitDiagnostic(
4517+
getLoc(), diag::cannot_match_unresolved_expr_pattern_with_value,
4518+
rhsType)
4519+
: emitDiagnostic(getLoc(), diag::cannot_match_expr_pattern_with_value,
4520+
lhsType, rhsType);
4521+
4522+
diagnostic.highlight(lhsExpr->getSourceRange());
4523+
diagnostic.highlight(rhsExpr->getSourceRange());
4524+
4525+
if (auto optUnwrappedType = rhsType->getOptionalObjectType()) {
4526+
if (lhsType->isEqual(optUnwrappedType)) {
4527+
diagnostic.fixItInsertAfter(lhsExpr->getEndLoc(), "?");
4528+
}
4529+
}
4530+
4531+
return true;
4532+
}
4533+
45024534
bool ArgumentMismatchFailure::diagnoseArchetypeMismatch() const {
45034535
auto *argTy = getFromType()->getAs<ArchetypeType>();
45044536
auto *paramTy = getToType()->getAs<ArchetypeType>();

branches/master-next/lib/Sema/CSDiagnostics.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,8 +1619,20 @@ class ArgumentMismatchFailure : public ContextualFailure {
16191619
/// produce a special diagnostic in case their names match.
16201620
bool diagnoseArchetypeMismatch() const;
16211621

1622+
/// Tailored diagnostic for pattern matching with `~=` operator.
1623+
bool diagnosePatternMatchingMismatch() const;
1624+
16221625
protected:
16231626
SourceLoc getLoc() const { return getAnchor()->getLoc(); }
1627+
1628+
ValueDecl *getDecl() const {
1629+
auto selectedOverload = getChoiceFor(getRawAnchor());
1630+
if (!selectedOverload)
1631+
return nullptr;
1632+
1633+
auto choice = selectedOverload->choice;
1634+
return choice.getDeclOrNull();
1635+
}
16241636
};
16251637

16261638
/// Provides information about the application of a function argument to a

branches/master-next/lib/Sema/CSSimplify.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2400,7 +2400,10 @@ bool ConstraintSystem::repairFailures(
24002400
if (repairByInsertingExplicitCall(lhs, rhs))
24012401
break;
24022402

2403-
if (repairViaBridgingCast(*this, lhs, rhs, conversionsOrFixes, locator))
2403+
bool isPatternMatching = isArgumentOfPatternMatchingOperator(loc);
2404+
// Let's not suggest force downcasts in pattern-matching context.
2405+
if (!isPatternMatching &&
2406+
repairViaBridgingCast(*this, lhs, rhs, conversionsOrFixes, locator))
24042407
break;
24052408

24062409
// Argument is a r-value but parameter expects an l-value e.g.
@@ -2580,6 +2583,13 @@ bool ConstraintSystem::repairFailures(
25802583
if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality))
25812584
break;
25822585

2586+
// If this is a ~= operator implicitly generated by pattern matching
2587+
// let's not try to fix right-hand side of the operator because it's
2588+
// a correct contextual type.
2589+
if (isPatternMatching &&
2590+
elt.castTo<LocatorPathElt::ApplyArgToParam>().getParamIdx() == 1)
2591+
break;
2592+
25832593
conversionsOrFixes.push_back(AllowArgumentMismatch::create(
25842594
*this, lhs, rhs, getConstraintLocator(locator)));
25852595
break;

branches/master-next/lib/Sema/ConstraintSystem.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2898,3 +2898,35 @@ bool constraints::isKnownKeyPathDecl(ASTContext &ctx, ValueDecl *decl) {
28982898
decl == ctx.getReferenceWritableKeyPathDecl() ||
28992899
decl == ctx.getPartialKeyPathDecl() || decl == ctx.getAnyKeyPathDecl();
29002900
}
2901+
2902+
bool constraints::isArgumentOfPatternMatchingOperator(
2903+
ConstraintLocator *locator) {
2904+
Expr *anchor = nullptr;
2905+
if (locator->findLast<LocatorPathElt::ApplyArgToParam>()) {
2906+
anchor = locator->getAnchor();
2907+
} else {
2908+
return false;
2909+
}
2910+
2911+
auto *binaryOp = dyn_cast_or_null<BinaryExpr>(anchor);
2912+
if (!(binaryOp && binaryOp->isImplicit()))
2913+
return false;
2914+
2915+
auto *fnExpr = binaryOp->getFn()->getSemanticsProvidingExpr();
2916+
2917+
ValueDecl *choice = nullptr;
2918+
if (auto *ODRE = dyn_cast<OverloadedDeclRefExpr>(fnExpr)) {
2919+
choice = ODRE->getDecls().front();
2920+
} else if (auto *DRE = dyn_cast<DeclRefExpr>(fnExpr)) {
2921+
choice = DRE->getDecl();
2922+
} else {
2923+
return false;
2924+
}
2925+
2926+
if (auto *FD = dyn_cast_or_null<AbstractFunctionDecl>(choice)) {
2927+
auto name = FD->getBaseName().userFacingName();
2928+
return name == "~=";
2929+
}
2930+
2931+
return false;
2932+
}

branches/master-next/lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,6 +3987,10 @@ Expr *simplifyLocatorToAnchor(ConstraintLocator *locator);
39873987
/// wasn't of one of the kinds listed above.
39883988
Expr *getArgumentExpr(Expr *expr, unsigned index);
39893989

3990+
/// Determine whether given locator points to one of the arguments
3991+
/// associated with implicit `~=` (pattern-matching) operator
3992+
bool isArgumentOfPatternMatchingOperator(ConstraintLocator *locator);
3993+
39903994
// Check whether argument of the call at given position refers to
39913995
// parameter marked as `@autoclosure`. This function is used to
39923996
// maintain source compatibility with Swift versions < 5,

0 commit comments

Comments
 (0)