Skip to content

Commit 29b9c5f

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 39723f4 + 0a15fb6 commit 29b9c5f

File tree

8 files changed

+37
-52
lines changed

8 files changed

+37
-52
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4420,12 +4420,6 @@ bool FailureDiagnosis::diagnoseSubscriptErrors(SubscriptExpr *SE,
44204420
if (calleeInfo.diagnoseSimpleErrors(SE))
44214421
return true;
44224422

4423-
// If we haven't found a diagnostic yet, and we are in an assignment's
4424-
// destination, continue with diagnosing the assignment rather than giving
4425-
// a last resort diagnostic here.
4426-
if (inAssignmentDestination)
4427-
return false;
4428-
44294423
diagnose(SE->getLoc(), diag::cannot_subscript_with_index, baseType,
44304424
indexType);
44314425

@@ -5826,10 +5820,16 @@ bool FailureDiagnosis::visitAssignExpr(AssignExpr *assignExpr) {
58265820
if (diagnoseSubscriptErrors(subscriptExpr, /* inAssignmentDestination = */ true))
58275821
return true;
58285822
}
5829-
5830-
AssignmentFailure failure(destExpr, CS, assignExpr->getLoc());
5831-
if (failure.diagnoseAsError())
5832-
return true;
5823+
// Member ref assignment errors detected elsewhere, so not an assignment issue if found here.
5824+
// The remaining exception involves mutable pointer conversions which aren't always caught elsewhere.
5825+
PointerTypeKind ptk;
5826+
if (!isa<MemberRefExpr>(destExpr) || CS.getType(destExpr)
5827+
->lookThroughAllOptionalTypes()
5828+
->getAnyPointerElementType(ptk)) {
5829+
AssignmentFailure failure(destExpr, CS, assignExpr->getLoc());
5830+
if (failure.diagnoseAsError())
5831+
return true;
5832+
}
58335833
}
58345834

58355835
auto *srcExpr = assignExpr->getSrc();

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -644,16 +644,12 @@ bool RValueTreatedAsLValueFailure::diagnoseAsError() {
644644
}
645645
}
646646
}
647-
} else if (auto sub = dyn_cast<SubscriptExpr>(diagExpr)) {
648-
subElementDiagID = diag::assignment_subscript_has_immutable_base;
649647

650-
// If the destination is a subscript with a 'dynamicLookup:' label and if
651-
// the tuple is implicit, then this was actually a @dynamicMemberLookup
652-
// access. Emit a more specific diagnostic.
653-
if (sub->getIndex()->isImplicit() &&
654-
sub->getArgumentLabels().size() == 1 &&
655-
sub->getArgumentLabels().front() == getTypeChecker().Context.Id_dynamicMember)
648+
if (auto resolvedOverload = getResolvedOverload(getLocator()))
649+
if (resolvedOverload->Choice.getKind() == OverloadChoiceKind::DynamicMemberLookup)
656650
subElementDiagID = diag::assignment_dynamic_property_has_immutable_base;
651+
} else if (auto sub = dyn_cast<SubscriptExpr>(diagExpr)) {
652+
subElementDiagID = diag::assignment_subscript_has_immutable_base;
657653
} else {
658654
subElementDiagID = diag::assignment_lhs_is_immutable_variable;
659655
}
@@ -728,23 +724,6 @@ bool AssignmentFailure::diagnoseAsError() {
728724
auto *DC = getDC();
729725
auto *destExpr = getParentExpr();
730726

731-
// Assignments to let-properties in delegating initializers will be caught
732-
// elsewhere now, so if we see them here, it isn't an assignment problem.
733-
if (auto *ctor = dyn_cast<ConstructorDecl>(DC)) {
734-
DeclRefExpr *baseRef = nullptr;
735-
if (auto *member = dyn_cast<UnresolvedDotExpr>(destExpr)) {
736-
baseRef = dyn_cast<DeclRefExpr>(member->getBase());
737-
} else if (auto *member = dyn_cast<MemberRefExpr>(destExpr)) {
738-
if (auto *load = dyn_cast<LoadExpr>(member->getBase()))
739-
baseRef = dyn_cast<DeclRefExpr>(load->getSubExpr());
740-
}
741-
if (baseRef && baseRef->getDecl() == ctor->getImplicitSelfDecl() &&
742-
ctor->getDelegatingOrChainedInitKind(nullptr) ==
743-
ConstructorDecl::BodyInitKind::Delegating) {
744-
return false;
745-
}
746-
}
747-
748727
// Walk through the destination expression, resolving what the problem is. If
749728
// we find a node in the lvalue path that is problematic, this returns it.
750729
auto immInfo = resolveImmutableBase(destExpr);

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2792,7 +2792,7 @@ namespace {
27922792
return TupleType::get(destTupleTypes, CS.getASTContext());
27932793
} else {
27942794
Type destTy = CS.createTypeVariable(CS.getConstraintLocator(expr));
2795-
CS.addConstraint(ConstraintKind::Bind, CS.getType(expr), LValueType::get(destTy),
2795+
CS.addConstraint(ConstraintKind::Bind, LValueType::get(destTy), CS.getType(expr),
27962796
CS.getConstraintLocator(expr));
27972797
return destTy;
27982798
}

lib/Sema/CSSimplify.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,16 +2369,19 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
23692369
// If we're converting an lvalue to an inout type, add the missing '&'.
23702370
conversionsOrFixes.push_back(
23712371
AddAddressOf::create(*this, getConstraintLocator(locator)));
2372-
} else if (!isTypeVarOrMember1) {
2372+
} else {
23732373
// If we have a concrete type that's an rvalue, "fix" it.
23742374
conversionsOrFixes.push_back(
23752375
TreatRValueAsLValue::create(*this, getConstraintLocator(locator)));
23762376
}
23772377
}
23782378
}
23792379

2380-
if (attemptFixes && type2->is<LValueType>() && !isTypeVarOrMember1) {
2381-
conversionsOrFixes.push_back(
2380+
if (attemptFixes && type2->is<LValueType>()) {
2381+
conversionsOrFixes.push_back(
2382+
TreatRValueAsLValue::create(*this, getConstraintLocator(locator)));
2383+
} else if (attemptFixes && kind == ConstraintKind::Bind && type1->is<LValueType>()) {
2384+
conversionsOrFixes.push_back(
23822385
TreatRValueAsLValue::create(*this, getConstraintLocator(locator)));
23832386
}
23842387

@@ -5008,7 +5011,11 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
50085011
}
50095012

50105013
case FixKind::TreatRValueAsLValue: {
5011-
auto result = matchTypes(LValueType::get(type1), type2,
5014+
if (type2->is<LValueType>() || type2->is<InOutType>())
5015+
type1 = LValueType::get(type1);
5016+
else
5017+
type2 = LValueType::get(type2);
5018+
auto result = matchTypes(type1, type2,
50125019
matchKind, subflags, locator);
50135020
if (result == SolutionKind::Solved)
50145021
if (recordFix(fix))

test/Constraints/assignment.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ value(_) // expected-error{{'_' can only appear in a pattern or on the left side
5353
// <rdar://problem/23798944> = vs. == in Swift if string character count statement causes segmentation fault
5454
func f23798944() {
5555
let s = ""
56-
// FIXME: better would be: use of '=' in a boolean context, did you mean '=='?
57-
if s.count = 0 { // expected-error {{cannot assign to property: 'count' is a get-only property}}
56+
if s.count = 0 { // expected-error {{use of '=' in a boolean context, did you mean '=='?}}
5857
}
5958
}
6059

test/Constraints/dynamic_lookup.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ obj.generic4!(5) // expected-error{{value of type 'Id' (aka 'AnyObject') has no
180180
// Find properties via dynamic lookup.
181181
var prop1Result : Int = obj.prop1!
182182
var prop2Result : String = obj.prop2!
183-
obj.prop2 = "hello" // expected-error{{cannot assign to immutable expression of type 'String?'}}
183+
obj.prop2 = "hello" // expected-error{{cannot assign to property: 'obj' is immutable}}
184184
var protoPropResult : Int = obj.protoProp!
185185

186186
// Find subscripts via dynamic lookup
@@ -290,9 +290,9 @@ let _: String = o[s]
290290
let _: String = o[s]!
291291
let _: String? = o[s]
292292
// FIXME: These should all produce lvalues that we can write through
293-
o.s = s // expected-error {{cannot assign to immutable expression of type 'String?'}}
293+
o.s = s // expected-error {{cannot assign to property: 'o' is immutable}}
294294
o.s! = s // expected-error {{cannot assign through '!': 'o' is immutable}}
295-
o[s] = s // expected-error {{cannot assign to immutable expression of type 'String?'}}
295+
o[s] = s // expected-error {{cannot assign through subscript: 'o' is immutable}}
296296
o[s]! = s // expected-error {{cannot assign through '!': 'o' is immutable}}
297297

298298
let _: String = o.t
@@ -309,7 +309,7 @@ let _: DynamicIUO = o[dyn_iuo]!
309309
let _: DynamicIUO = o[dyn_iuo]!!
310310
let _: DynamicIUO? = o[dyn_iuo]
311311
// FIXME: These should all produce lvalues that we can write through
312-
o[dyn_iuo] = dyn_iuo // expected-error {{cannot assign to immutable expression of type 'DynamicIUO??'}}
312+
o[dyn_iuo] = dyn_iuo // expected-error {{cannot assign through subscript: 'o' is immutable}}
313313
o[dyn_iuo]! = dyn_iuo // expected-error {{cannot assign through '!': 'o' is immutable}}
314314
o[dyn_iuo]!! = dyn_iuo // expected-error {{cannot assign through '!': 'o' is immutable}}
315315

test/NameBinding/dynamic-member-lookup.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func test(a: Gettable, b: Settable, c: MutGettable, d: NonMutSettable) {
6767

6868
func test_iuo(a : Gettable!, b : Settable!) {
6969
global = a.wyverns
70-
a.flavor = global // expected-error {{cannot assign through dynamic lookup property: subscript is get-only}}
70+
a.flavor = global // expected-error {{cannot assign through dynamic lookup property: 'a' is a 'let' constant}}
7171

7272
global = b.flavor
7373
b.universal = global // expected-error {{cannot assign through dynamic lookup property: 'b' is a 'let' constant}}

test/expr/unary/keypath/keypath.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -314,9 +314,9 @@ func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscri
314314
sink = writable[keyPath: wkp]
315315
sink = readonly[keyPath: rkp]
316316
sink = writable[keyPath: rkp]
317-
readonly[keyPath: kp] = sink // expected-error{{cannot assign through subscript: 'kp' is a read-only key path}}
318-
writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: 'kp' is a read-only key path}}
319-
readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
317+
readonly[keyPath: kp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}}
318+
writable[keyPath: kp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}}
319+
readonly[keyPath: wkp] = sink // expected-error{{cannot assign through subscript: subscript is get-only}}
320320
// FIXME: silently falls back to keypath application, which seems inconsistent
321321
writable[keyPath: wkp] = sink
322322
// FIXME: silently falls back to keypath application, which seems inconsistent
@@ -331,8 +331,8 @@ func testKeyPathSubscript(readonly: ZwithSubscript, writable: inout ZwithSubscri
331331
var anySink2 = writable[keyPath: pkp]
332332
expect(&anySink2, toHaveType: Exactly<Any>.self)
333333

334-
readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: 'readonly' is a 'let' constant}}
335-
writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: 'writable' is immutable}}
334+
readonly[keyPath: pkp] = anySink1 // expected-error{{cannot assign through subscript: subscript is get-only}}
335+
writable[keyPath: pkp] = anySink2 // expected-error{{cannot assign through subscript: subscript is get-only}}
336336

337337
let akp: AnyKeyPath = pkp
338338

0 commit comments

Comments
 (0)