Skip to content

Commit 8c329fe

Browse files
authored
Merge pull request #27558 from AnthonyLatsis/lvalue-type-fixit
[NFC] Fix occasional @lvalue exposures
2 parents a9b5fe3 + d64d45d commit 8c329fe

File tree

5 files changed

+33
-24
lines changed

5 files changed

+33
-24
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4569,7 +4569,7 @@ diagnoseAmbiguousMultiStatementClosure(ClosureExpr *closure) {
45694569
auto type = getTypeOfExpressionWithoutApplying(
45704570
resultExpr, CS.DC, decl, FreeTypeVariableBinding::UnresolvedType);
45714571
if (type)
4572-
resultType = type;
4572+
resultType = type->getRValueType();
45734573
}
45744574

45754575
// If we found a type, presuppose it was the intended result and insert a

lib/Sema/CSDiagnostics.cpp

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,14 @@ std::pair<Expr *, bool> FailureDiagnostic::computeAnchor() const {
7575
return {anchor, !resolved->getPath().empty()};
7676
}
7777

78-
Type FailureDiagnostic::getType(Expr *expr) const {
79-
return resolveType(CS.getType(expr));
78+
Type FailureDiagnostic::getType(Expr *expr, bool wantRValue) const {
79+
return resolveType(CS.getType(expr), /*reconstituteSugar=*/false,
80+
wantRValue);
8081
}
8182

82-
Type FailureDiagnostic::getType(const TypeLoc &loc) const {
83-
return resolveType(CS.getType(loc));
83+
Type FailureDiagnostic::getType(const TypeLoc &loc, bool wantRValue) const {
84+
return resolveType(CS.getType(loc), /*reconstituteSugar=*/false,
85+
wantRValue);
8486
}
8587

8688
template <typename... ArgTypes>
@@ -248,7 +250,6 @@ FailureDiagnostic::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
248250
// Try to resolve the function type by loading lvalues and looking through
249251
// optional types, which can occur for expressions like `fn?(5)`.
250252
auto *fnType = resolveType(rawFnType)
251-
->getRValueType()
252253
->lookThroughAllOptionalTypes()
253254
->getAs<FunctionType>();
254255
if (!fnType)
@@ -1077,7 +1078,7 @@ bool MemberAccessOnOptionalBaseFailure::diagnoseAsError() {
10771078
return false;
10781079

10791080
auto *anchor = getAnchor();
1080-
auto baseType = getType(anchor)->getRValueType();
1081+
auto baseType = getType(anchor);
10811082
bool resultIsOptional = ResultTypeIsOptional;
10821083

10831084
// If we've resolved the member overload to one that returns an optional
@@ -1229,7 +1230,7 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() {
12291230
}
12301231

12311232
emitDiagnostic(tryExpr->getTryLoc(), diag::missing_unwrap_optional_try,
1232-
getType(anchor)->getRValueType())
1233+
getType(anchor))
12331234
.fixItReplace({tryExpr->getTryLoc(), tryExpr->getQuestionLoc()},
12341235
"try!");
12351236
return true;
@@ -1399,7 +1400,7 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
13991400

14001401
if (resolvedOverload->Choice.getKind() ==
14011402
OverloadChoiceKind::KeyPathDynamicMemberLookup) {
1402-
if (!getType(member->getBase())->hasLValueType())
1403+
if (!getType(member->getBase(), /*wantRValue=*/false)->hasLValueType())
14031404
subElementDiagID =
14041405
diag::assignment_dynamic_property_has_immutable_base;
14051406
}
@@ -2299,7 +2300,7 @@ bool ContextualFailure::diagnoseYieldByReferenceMismatch() const {
22992300
return false;
23002301

23012302
auto *anchor = getAnchor();
2302-
auto exprType = getType(anchor);
2303+
auto exprType = getType(anchor, /*wantRValue=*/false);
23032304
auto contextualType = getToType();
23042305

23052306
if (auto exprLV = exprType->getAs<LValueType>()) {
@@ -5163,7 +5164,7 @@ bool ArgumentMismatchFailure::diagnoseAsError() {
51635164
// let's match up its element type to the argument to see whether
51645165
// it would be appropriate to suggest adding `&`.
51655166
auto *argExpr = getAnchor();
5166-
if (getType(argExpr)->is<LValueType>()) {
5167+
if (getType(argExpr, /*wantRValue=*/false)->is<LValueType>()) {
51675168
auto elementTy = paramType->getAnyPointerElementType();
51685169
if (elementTy && argType->isEqual(elementTy)) {
51695170
diag.fixItInsert(argExpr->getStartLoc(), "&");
@@ -5199,8 +5200,8 @@ bool ArgumentMismatchFailure::diagnoseUseOfReferenceEqualityOperator() const {
51995200

52005201
auto name = *getOperatorName(binaryOp->getFn());
52015202

5202-
auto lhsType = getType(lhs)->getRValueType();
5203-
auto rhsType = getType(rhs)->getRValueType();
5203+
auto lhsType = getType(lhs);
5204+
auto rhsType = getType(rhs);
52045205

52055206
// If both arguments where incorrect e.g. both are function types,
52065207
// let's avoid producing a diagnostic second time, because first
@@ -5261,8 +5262,8 @@ bool ArgumentMismatchFailure::diagnosePatternMatchingMismatch() const {
52615262
auto *lhsExpr = op->getArg()->getElement(0);
52625263
auto *rhsExpr = op->getArg()->getElement(1);
52635264

5264-
auto lhsType = getType(lhsExpr)->getRValueType();
5265-
auto rhsType = getType(rhsExpr)->getRValueType();
5265+
auto lhsType = getType(lhsExpr);
5266+
auto rhsType = getType(rhsExpr);
52665267

52675268
auto diagnostic =
52685269
lhsType->is<UnresolvedType>()

lib/Sema/CSDiagnostics.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,18 @@ class FailureDiagnostic {
9292

9393
ConstraintLocator *getLocator() const { return Locator; }
9494

95-
Type getType(Expr *expr) const;
96-
Type getType(const TypeLoc &loc) const;
95+
Type getType(Expr *expr, bool wantRValue = true) const;
96+
Type getType(const TypeLoc &loc, bool wantRValue = true) const;
9797

9898
/// Resolve type variables present in the raw type, if any.
99-
Type resolveType(Type rawType, bool reconstituteSugar = false) const {
99+
Type resolveType(Type rawType, bool reconstituteSugar = false,
100+
bool wantRValue = true) const {
100101
auto resolvedType = CS.simplifyType(rawType);
101-
return reconstituteSugar
102-
? resolvedType->reconstituteSugar(/*recursive*/ true)
103-
: resolvedType;
102+
103+
if (reconstituteSugar)
104+
resolvedType = resolvedType->reconstituteSugar(/*recursive*/ true);
105+
106+
return wantRValue ? resolvedType->getRValueType() : resolvedType;
104107
}
105108

106109
/// Resolve type variables present in the raw type, using generic parameter
@@ -695,8 +698,7 @@ class ContextualFailure : public FailureDiagnostic {
695698
ContextualTypePurpose purpose, Type lhs, Type rhs,
696699
ConstraintLocator *locator)
697700
: FailureDiagnostic(root, cs, locator), CTP(purpose),
698-
FromType(resolve(lhs)->getRValueType()),
699-
ToType(resolve(rhs)->getRValueType()) {}
701+
FromType(resolve(lhs)), ToType(resolve(rhs)) {}
700702

701703
Type getFromType() const { return FromType; }
702704

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1274,7 +1274,7 @@ func rdar17170728() {
12741274
// expected-error@-1 {{missing argument label 'into:' in call}}
12751275
// expected-error@-2 {{optional type 'Int?' cannot be used as a boolean; test for '!= nil' instead}}
12761276
$0 && $1 ? $0 + $1 : ($0 ? $0 : ($1 ? $1 : nil))
1277-
// expected-error@-1 {{binary operator '+' cannot be applied to operands of type '@lvalue Bool' and 'Bool'}}
1277+
// expected-error@-1 {{binary operator '+' cannot be applied to two 'Bool' operands}}
12781278
// expected-error@-2 {{'nil' cannot be used in context expecting type 'Bool'}}
12791279
}
12801280
}

test/expr/closure/closures.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,9 @@ func lvalueCapture<T>(c: GenericClass<T>) {
355355
cc = wc!
356356
}
357357
}
358+
359+
// Don't expose @lvalue-ness in diagnostics.
360+
let closure = { // expected-error {{unable to infer complex closure return type; add explicit type to disambiguate}} {{16-16= () -> Bool in }}
361+
var helper = true
362+
return helper
363+
}

0 commit comments

Comments
 (0)