Skip to content

Commit 40c2678

Browse files
committed
Sema: Fix existential opening for arguments to self.init/super.init delegation
Fixes rdar://problem/98404682.
1 parent 67b23d7 commit 40c2678

File tree

3 files changed

+47
-9
lines changed

3 files changed

+47
-9
lines changed

lib/Sema/CSApply.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,8 @@ namespace {
726726
return inout->getSubExpr();
727727
} else if (auto force = dyn_cast<ForceValueExpr>(expr)) {
728728
return force->getSubExpr();
729+
} else if (auto rebind = dyn_cast<RebindSelfInConstructorExpr>(expr)) {
730+
return rebind->getSubExpr();
729731
} else {
730732
return nullptr;
731733
}
@@ -817,11 +819,6 @@ namespace {
817819
unsigned maxArgCount = member->getNumCurryLevels();
818820
unsigned depth = ExprStack.size() - getArgCount(maxArgCount);
819821

820-
// Invalid case -- direct call of a metatype. Has one less argument
821-
// application because there's no ".init".
822-
if (isa<ApplyExpr>(ExprStack.back()))
823-
depth++;
824-
825822
// Create the opaque opened value. If we started with a
826823
// metatype, it's a metatype.
827824
Type opaqueType = archetype;
@@ -3757,7 +3754,12 @@ namespace {
37573754
expr->setSubExpr(newSubExpr);
37583755
}
37593756

3760-
return expr;
3757+
// We might have opened existentials in the argument list of the
3758+
// constructor call.
3759+
Expr *result = expr;
3760+
closeExistentials(result, cs.getConstraintLocator(expr));
3761+
3762+
return result;
37613763
}
37623764

37633765
Expr *visitIfExpr(IfExpr *expr) {

lib/Sema/MiscDiagnostics.cpp

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,14 +109,16 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
109109
SmallPtrSet<DeclRefExpr*, 4> AlreadyDiagnosedBitCasts;
110110

111111
bool IsExprStmt;
112+
unsigned ExprNestingDepth;
112113
bool HasReachedSemanticsProvidingExpr;
113114

114115
ASTContext &Ctx;
115116
const DeclContext *DC;
116117

117118
public:
118119
DiagnoseWalker(const DeclContext *DC, bool isExprStmt)
119-
: IsExprStmt(isExprStmt), HasReachedSemanticsProvidingExpr(false),
120+
: IsExprStmt(isExprStmt), ExprNestingDepth(0),
121+
HasReachedSemanticsProvidingExpr(false),
120122
Ctx(DC->getASTContext()), DC(DC) {}
121123

122124
std::pair<bool, Pattern*> walkToPatternPre(Pattern *P) override {
@@ -130,6 +132,10 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
130132
bool shouldWalkIntoTapExpression() override { return false; }
131133

132134
std::pair<bool, Expr *> walkToExprPre(Expr *E) override {
135+
if (isa<OpenExistentialExpr>(E)) {
136+
// Don't increase ExprNestingDepth.
137+
return { true, E };
138+
}
133139

134140
if (auto collection = dyn_cast<CollectionExpr>(E)) {
135141
if (collection->isTypeDefaulted()) {
@@ -275,9 +281,11 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
275281
}
276282

277283
// Diagnose 'self.init' or 'super.init' nested in another expression
278-
// or closure.
284+
// or closure. The ExprNestingDepth thing is to allow this to be nested
285+
// inside of an OpenExistentialExpr that is at the top level.
279286
if (auto *rebindSelfExpr = dyn_cast<RebindSelfInConstructorExpr>(E)) {
280-
if (!Parent.isNull() || !IsExprStmt || DC->getParent()->isLocalContext()) {
287+
if (ExprNestingDepth > 0 || !IsExprStmt ||
288+
DC->getParent()->isLocalContext()) {
281289
bool isChainToSuper;
282290
(void)rebindSelfExpr->getCalledConstructor(isChainToSuper);
283291
Ctx.Diags.diagnose(E->getLoc(), diag::init_delegation_nested,
@@ -346,9 +354,20 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
346354
HasReachedSemanticsProvidingExpr = true;
347355
}
348356

357+
++ExprNestingDepth;
358+
349359
return { true, E };
350360
}
351361

362+
Expr *walkToExprPost(Expr *E) override {
363+
if (isa<OpenExistentialExpr>(E))
364+
return E;
365+
366+
assert(ExprNestingDepth != 0);
367+
--ExprNestingDepth;
368+
return E;
369+
}
370+
352371
/// Visit each component of the keypath and emit a diagnostic if they
353372
/// refer to a member that has effects.
354373
void checkForEffectfulKeyPath(KeyPathExpr *keyPath) {
@@ -1500,6 +1519,7 @@ static void diagRecursivePropertyAccess(const Expr *E, const DeclContext *DC) {
15001519
};
15011520

15021521
DiagnoseWalker walker(var, fn);
1522+
15031523
const_cast<Expr *>(E)->walk(walker);
15041524
}
15051525

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
protocol P {}
4+
class C {
5+
init(x: some P) {}
6+
7+
convenience init(y: any P) { self.init(x: y) }
8+
}
9+
10+
// CHECK-LABEL: sil hidden [ossa] @$s37opened_existential_in_init_delegation1CC1yAcA1P_p_tcfC : $@convention(method) (@in any P, @thick C.Type) -> @owned C {
11+
// CHECK: [[OPENED:%.*]] = open_existential_addr immutable_access %0 : $*any P to $*@opened("{{.*}}", any P) Self
12+
// CHECK: [[COPIED:%.*]] = alloc_stack $@opened("{{.*}}", any P) Self
13+
// CHECK: copy_addr [[OPENED]] to [initialization] [[COPIED]] : $*@opened("{{.*}}", any P) Self
14+
// CHECK: [[FN:%.*]] = class_method %1 : $@thick C.Type, #C.init!allocator : (C.Type) -> (some P) -> C, $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @thick C.Type) -> @owned C
15+
// CHECK: apply [[FN]]<@opened("{{.*}}", any P) Self>([[COPIED]], %1) : $@convention(method) <τ_0_0 where τ_0_0 : P> (@in τ_0_0, @thick C.Type) -> @owned C
16+
// CHECK: dealloc_stack [[COPIED]] : $*@opened("{{.*}}", any P) Self

0 commit comments

Comments
 (0)