Skip to content

Commit ef6630f

Browse files
committed
Sema: Strip off LValueType from opened existential accesses with an erased result type
- Fixes swiftlang#62219 - Fixes swiftlang#60619, - Fixes rdar://104230391 - Fixes rdar://118247162.
1 parent 897fae2 commit ef6630f

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
@@ -653,6 +653,15 @@ Type TypeBase::typeEraseOpenedArchetypesWithRoot(
653653
}
654654
}
655655

656+
if (auto lvalue = dyn_cast<LValueType>(type)) {
657+
auto objTy = lvalue->getObjectType();
658+
auto erased = transformFn(objTy);
659+
if (erased.getPointer() == objTy.getPointer())
660+
return Type(lvalue);
661+
662+
return erased;
663+
}
664+
656665
auto *const archetype = dyn_cast<OpenedArchetypeType>(ty);
657666
if (!archetype) {
658667
// Recurse.

lib/Sema/ConstraintSystem.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2182,6 +2182,15 @@ static Type typeEraseExistentialSelfReferences(Type refTy, Type baseTy,
21822182
}
21832183
}
21842184

2185+
if (auto lvalue = dyn_cast<LValueType>(t)) {
2186+
auto objTy = lvalue->getObjectType();
2187+
auto erased = transformFn(objTy, currPos);
2188+
if (erased.getPointer() == objTy.getPointer())
2189+
return Type(lvalue);
2190+
2191+
return erased;
2192+
}
2193+
21852194
if (!t->isTypeParameter()) {
21862195
// Recurse.
21872196
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)