Skip to content

Commit 890e45d

Browse files
committed
[CSSimplify] Increase impact of treat r-value as l-value fix in certain situations
If location (member) isn't mutable in the current context or there are other problems at this location, increase impact of the fix since it compounds the problem.
1 parent 55b8d95 commit 890e45d

File tree

4 files changed

+37
-38
lines changed

4 files changed

+37
-38
lines changed

include/swift/Sema/CSFix.h

+4
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,10 @@ class TreatRValueAsLValue final : public ConstraintFix {
620620
return diagnose(*commonFixes.front().first);
621621
}
622622

623+
/// Assess the impact this fix is going to have at the given location.
624+
static unsigned assessImpact(ConstraintSystem &cs,
625+
ConstraintLocator *atLoc);
626+
623627
static TreatRValueAsLValue *create(ConstraintSystem &cs,
624628
ConstraintLocator *locator);
625629

lib/Sema/CSFix.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,29 @@ bool TreatRValueAsLValue::diagnose(const Solution &solution,
141141
return failure.diagnose(asNote);
142142
}
143143

144+
unsigned TreatRValueAsLValue::assessImpact(ConstraintSystem &cs,
145+
ConstraintLocator *atLoc) {
146+
// Results of calls can never be l-value.
147+
unsigned impact = isExpr<CallExpr>(atLoc->getAnchor()) ? 2 : 1;
148+
// An overload choice that isn't settable is least interesting for
149+
// diagnosis.
150+
auto *calleeLoc = cs.getCalleeLocator(atLoc, /*lookThroughApply=*/false);
151+
if (auto overload = cs.findSelectedOverloadFor(calleeLoc)) {
152+
if (auto *var = dyn_cast_or_null<AbstractStorageDecl>(
153+
overload->choice.getDeclOrNull())) {
154+
impact += !var->isSettableInSwift(cs.DC) ? 1 : 0;
155+
} else {
156+
impact += 1;
157+
}
158+
}
159+
160+
// This is extra impactful if location has other issues.
161+
if (cs.hasFixFor(atLoc) || cs.hasFixFor(calleeLoc))
162+
impact += 2;
163+
164+
return impact;
165+
}
166+
144167
TreatRValueAsLValue *TreatRValueAsLValue::create(ConstraintSystem &cs,
145168
ConstraintLocator *locator) {
146169
if (locator->isLastElement<LocatorPathElt::ApplyArgToParam>())

lib/Sema/CSSimplify.cpp

+5-35
Original file line numberDiff line numberDiff line change
@@ -14023,26 +14023,9 @@ ConstraintSystem::simplifyLValueObjectConstraint(
1402314023
if (!shouldAttemptFixes())
1402414024
return SolutionKind::Error;
1402514025

14026-
auto assessImpact = [&]() -> unsigned {
14027-
// If this is a projection of a member reference
14028-
// let's check whether the member is unconditionally
14029-
// settable, if so than it's a problem with its base.
14030-
if (locator.directlyAt<UnresolvedDotExpr>()) {
14031-
auto *memberLoc = getConstraintLocator(locator.getAnchor(),
14032-
ConstraintLocator::Member);
14033-
if (auto selected = findSelectedOverloadFor(memberLoc)) {
14034-
if (auto *storage = dyn_cast_or_null<AbstractStorageDecl>(
14035-
selected->choice.getDeclOrNull())) {
14036-
return storage->isSettable(nullptr) ? 1 : 2;
14037-
}
14038-
}
14039-
}
14040-
return 2;
14041-
};
14042-
14043-
if (recordFix(
14044-
TreatRValueAsLValue::create(*this, getConstraintLocator(locator)),
14045-
assessImpact()))
14026+
auto *fixLoc = getConstraintLocator(locator);
14027+
if (recordFix(TreatRValueAsLValue::create(*this, fixLoc),
14028+
TreatRValueAsLValue::assessImpact(*this, fixLoc)))
1404614029
return SolutionKind::Error;
1404714030

1404814031
lvalueTy = LValueType::get(lvalueTy);
@@ -15198,21 +15181,8 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
1519815181
}
1519915182

1520015183
case FixKind::TreatRValueAsLValue: {
15201-
unsigned impact = 1;
15202-
// If this is an attempt to use result of a function/subscript call as
15203-
// an l-value, it has to have an increased impact because it's either
15204-
// a function - which is completely incorrect, or it's a get-only
15205-
// subscript, which requires changes to declaration to become mutable.
15206-
impact += (locator.endsWith<LocatorPathElt::FunctionResult>() ||
15207-
locator.endsWith<LocatorPathElt::SubscriptMember>())
15208-
? 1
15209-
: 0;
15210-
// An overload choice that isn't settable is least interesting for diagnosis.
15211-
if (auto overload = findSelectedOverloadFor(getCalleeLocator(fix->getLocator()))) {
15212-
if (auto *var = dyn_cast_or_null<VarDecl>(overload->choice.getDeclOrNull())) {
15213-
impact += !var->isSettableInSwift(DC) ? 1 : 0;
15214-
}
15215-
}
15184+
unsigned impact =
15185+
TreatRValueAsLValue::assessImpact(*this, fix->getLocator());
1521615186
return recordFix(fix, impact) ? SolutionKind::Error : SolutionKind::Solved;
1521715187
}
1521815188

test/Generics/function_defs.swift

+5-3
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,15 @@ protocol Subscriptable {
123123
func getIndex() -> Index
124124
func getValue() -> Value
125125

126-
subscript (index : Index) -> Value { get set } // expected-note {{candidate expects value of type 'T.Index' for parameter #1 (got 'T.Value')}}
126+
subscript (index : Index) -> Value { get set }
127127
}
128128

129129
protocol IntSubscriptable {
130130
associatedtype ElementType
131131

132132
func getElement() -> ElementType
133133

134-
subscript (index : Int) -> ElementType { get } // expected-note {{candidate expects value of type 'Int' for parameter #1 (got 'T.Value')}}
134+
subscript (index : Int) -> ElementType { get }
135135
}
136136

137137
func subscripting<T : Subscriptable & IntSubscriptable>(_ t: T) {
@@ -144,7 +144,9 @@ func subscripting<T : Subscriptable & IntSubscriptable>(_ t: T) {
144144
element = t[17]
145145
t[42] = element // expected-error{{cannot assign through subscript: subscript is get-only}}
146146

147-
t[value] = 17 // expected-error{{no exact matches in call to subscript}}
147+
// Note that this is not an ambiguity because only one subscript is mutating
148+
t[value] = 17 // expected-error{{cannot convert value of type 'T.Value' to expected argument type 'T.Index'}}
149+
// expected-error@-1 {{cannot assign value of type 'Int' to subscript of type 'T.Value'}}
148150
}
149151

150152
//===----------------------------------------------------------------------===//

0 commit comments

Comments
 (0)