Skip to content

Commit de32e4d

Browse files
authored
Merge pull request swiftlang#69951 from slavapestov/fix-lvalue-open-existential-5.10
Sema: Strip off LValueType from opened existential accesses with an erased result type [5.10]
2 parents 72576b7 + c1e97b6 commit de32e4d

File tree

3 files changed

+83
-0
lines changed

3 files changed

+83
-0
lines changed

lib/AST/Type.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,15 @@ Type TypeBase::typeEraseOpenedArchetypesWithRoot(
569569
}
570570
}
571571

572+
if (auto lvalue = dyn_cast<LValueType>(type)) {
573+
auto objTy = lvalue->getObjectType();
574+
auto erased = transformFn(objTy);
575+
if (erased.getPointer() == objTy.getPointer())
576+
return Type(lvalue);
577+
578+
return erased;
579+
}
580+
572581
auto *const archetype = dyn_cast<OpenedArchetypeType>(ty);
573582
if (!archetype) {
574583
// Recurse.

lib/Sema/ConstraintSystem.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,15 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
21672167
}
21682168
}
21692169

2170+
if (auto lvalue = dyn_cast<LValueType>(t)) {
2171+
auto objTy = lvalue->getObjectType();
2172+
auto erased = transformFn(objTy, currPos);
2173+
if (erased.getPointer() == objTy.getPointer())
2174+
return Type(lvalue);
2175+
2176+
return erased;
2177+
}
2178+
21702179
if (!t->isTypeParameter()) {
21712180
// Recurse.
21722181
return llvm::None;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
protocol Q {}
4+
5+
protocol P {
6+
associatedtype T: Q
7+
var member: T { get set }
8+
var otherMember: any Q { get set }
9+
subscript(_: Int) -> T { get set }
10+
}
11+
12+
func takesAny(x: any Q) {}
13+
func takesRValue(x: any Q) {}
14+
func takesInOut(x: inout any Q) {}
15+
16+
func f(data: inout any P) {
17+
takesAny(x: data.member)
18+
takesAny(x: data[0])
19+
20+
takesRValue(x: data.member)
21+
takesRValue(x: data[0])
22+
23+
takesInOut(x: &data.member) // expected-error {{cannot pass immutable value as inout argument: 'data' is immutable}}
24+
takesInOut(x: &data[0]) // expected-error {{cannot pass immutable value as inout argument: 'data' is immutable}}
25+
26+
takesInOut(x: &data.otherMember) // okay
27+
}
28+
29+
struct S {
30+
subscript<T: Q>(_ ct: T.Type) -> T {
31+
get { fatalError() }
32+
set { fatalError() }
33+
}
34+
}
35+
36+
func f(s: inout S, t: any Q.Type) -> (any Q) {
37+
takesAny(x: s[t])
38+
takesRValue(x: s[t])
39+
takesInOut(x: &s[t]) // expected-error {{cannot pass immutable value as inout argument: 's' is immutable}}
40+
}
41+
42+
// https://github.com/apple/swift/issues/62219
43+
do {
44+
struct Action {
45+
var intVar: Int
46+
var strVar: String
47+
}
48+
49+
protocol TestDelegate: AnyObject {
50+
associatedtype ActionType
51+
var actions: [ActionType] { get set }
52+
}
53+
54+
class TestDelegateImpl: TestDelegate {
55+
typealias ActionType = Action
56+
var actions: [Action] = []
57+
}
58+
59+
class TestViewController {
60+
var testDelegate: (any TestDelegate)?
61+
func testFunc() {
62+
testDelegate?.actions.removeAll() // expected-error {{cannot use mutating member on immutable value: 'self' is immutable}}
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)