Skip to content

Commit 8feaee5

Browse files
committed
Sema: Subscript called with opened existential cannot produce lvalue if result is type-erased
1 parent 26e888e commit 8feaee5

File tree

4 files changed

+38
-18
lines changed

4 files changed

+38
-18
lines changed

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,8 +1002,14 @@ namespace {
10021002
auto *env = record.Archetype->getGenericEnvironment();
10031003

10041004
if (resultTy->hasLocalArchetypeFromEnvironment(env)) {
1005-
Type erasedTy = typeEraseOpenedArchetypesFromEnvironment(
1006-
resultTy, env);
1005+
Type erasedTy = typeEraseOpenedArchetypesFromEnvironment(resultTy, env);
1006+
ASSERT(erasedTy.getPointer() != resultTy.getPointer());
1007+
1008+
// We currently cannot keep lvalueness if the object type changed.
1009+
if (auto *lvalueTy = dyn_cast<LValueType>(erasedTy.getPointer())) {
1010+
erasedTy = lvalueTy->getObjectType();
1011+
}
1012+
10071013
auto range = result->getSourceRange();
10081014
result = coerceToType(result, erasedTy, locator);
10091015
// FIXME: Implement missing tuple-to-tuple conversion

lib/Sema/CSSimplify.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13220,9 +13220,19 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyApplicableFnConstraint(
1322013220
Type result2 = func2->getResult();
1322113221
if (result2->hasTypeVariable() && !openedExistentials.empty()) {
1322213222
for (const auto &opened : openedExistentials) {
13223-
result2 = typeEraseOpenedExistentialReference(
13224-
result2, opened.second->getExistentialType(), opened.first,
13223+
auto originalTy = result2;
13224+
if (auto *lvalueTy = dyn_cast<LValueType>(originalTy.getPointer())) {
13225+
originalTy = lvalueTy->getObjectType();
13226+
}
13227+
13228+
const auto erasedTy = typeEraseOpenedExistentialReference(
13229+
originalTy, opened.second->getExistentialType(), opened.first,
1322513230
TypePosition::Covariant);
13231+
13232+
if (originalTy.getPointer() != erasedTy.getPointer()) {
13233+
// We currently cannot keep lvalueness if the object type changed.
13234+
result2 = erasedTy;
13235+
}
1322613236
}
1322713237
}
1322813238

lib/Sema/OpenedExistentials.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -762,20 +762,6 @@ static Type typeEraseExistentialSelfReferences(
762762
return parameterized->getBaseType();
763763
}
764764
}
765-
/*
766-
if (auto lvalue = dyn_cast<LValueType>(t)) {
767-
auto objTy = lvalue->getObjectType();
768-
auto erasedTy =
769-
typeEraseExistentialSelfReferences(
770-
objTy, currPos,
771-
containsFn, predicateFn, eraseFn);
772-
773-
if (erasedTy.getPointer() == objTy.getPointer())
774-
return Type(lvalue);
775-
776-
return erasedTy;
777-
}
778-
*/
779765

780766
if (!predicateFn(t)) {
781767
// Recurse.

test/Sema/open_existential_lvalue.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,21 @@ do {
6666
}
6767
}
6868
}
69+
70+
// https://github.com/swiftlang/swift/issues/60619
71+
do {
72+
protocol P {
73+
associatedtype A
74+
}
75+
struct S {
76+
subscript<T: P>(_: T) -> T {
77+
get {} set {}
78+
}
79+
}
80+
81+
var s: S
82+
let p: any P
83+
84+
let _ = s[p]
85+
s[p] = p // expected-error {{cannot assign through subscript: 's' is immutable}}
86+
}

0 commit comments

Comments
 (0)