Skip to content

Commit adee860

Browse files
authored
Merge pull request #4126 from slavapestov/sil-dynamic-self-round-tripping
SIL: Round-trip DynamicSelfType properly
2 parents ad445d0 + 173658a commit adee860

File tree

15 files changed

+110
-25
lines changed

15 files changed

+110
-25
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ TYPE_ATTR(escaping)
4040
// SIL-specific attributes
4141
TYPE_ATTR(block_storage)
4242
TYPE_ATTR(box)
43+
TYPE_ATTR(dynamic_self)
4344
TYPE_ATTR(sil_unowned)
4445
TYPE_ATTR(sil_unmanaged)
4546
TYPE_ATTR(sil_weak)

include/swift/Subsystems.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,19 @@ namespace swift {
192192
///
193193
/// \returns false on success, true on error.
194194
bool performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
195-
bool isSILType, DeclContext *DC,
195+
DeclContext *DC,
196+
bool ProduceDiagnostics = true);
197+
198+
/// \brief Recursively validate the specified type.
199+
///
200+
/// This is used when dealing with partial source files (e.g. SIL parsing,
201+
/// code completion).
202+
///
203+
/// \returns false on success, true on error.
204+
bool performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
205+
bool isSILMode,
206+
bool isSILType,
207+
DeclContext *DC,
196208
bool ProduceDiagnostics = true);
197209

198210
/// Expose TypeChecker's handling of GenericParamList to SIL parsing.

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3736,6 +3736,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
37363736
}
37373737

37383738
void visitDynamicSelfType(DynamicSelfType *T) {
3739+
if (Options.PrintInSILBody) {
3740+
Printer << "@dynamic_self ";
3741+
visit(T->getSelfType());
3742+
return;
3743+
}
3744+
37393745
Printer.printTypeRef(T, T->getASTContext().Id_Self);
37403746
}
37413747

lib/IDE/CodeCompletion.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1387,7 +1387,7 @@ class CodeCompletionCallbacksImpl : public CodeCompletionCallbacks {
13871387
/// \returns true on success, false on failure.
13881388
bool typecheckParsedType() {
13891389
assert(ParsedTypeLoc.getTypeRepr() && "should have a TypeRepr");
1390-
return !performTypeLocChecking(P.Context, ParsedTypeLoc, /*SIL*/ false,
1390+
return !performTypeLocChecking(P.Context, ParsedTypeLoc,
13911391
CurDeclContext, false);
13921392
}
13931393

lib/Parse/ParseSIL.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ namespace {
118118
llvm::function_ref<void(Type)> ParsedTypeCallback;
119119

120120

121-
bool performTypeLocChecking(TypeLoc &T, bool IsSIL = true);
121+
bool performTypeLocChecking(TypeLoc &T, bool IsSILType = true);
122122
bool parseSpecConformanceSubstitutions(
123123
SmallVectorImpl<ParsedSubstitution> &parsed);
124124
ProtocolConformance *parseProtocolConformanceHelper(ProtocolDecl *&proto,
@@ -770,11 +770,13 @@ static bool parseDeclSILOptional(bool *isTransparent, bool *isFragile,
770770
return false;
771771
}
772772

773-
bool SILParser::performTypeLocChecking(TypeLoc &T, bool IsSIL) {
773+
bool SILParser::performTypeLocChecking(TypeLoc &T, bool IsSILType) {
774774
// Do some type checking / name binding for the parsed type.
775775
assert(P.SF.ASTStage == SourceFile::Parsing &&
776776
"Unexpected stage during parsing!");
777-
return swift::performTypeLocChecking(P.Context, T, /*SIL*/ IsSIL, &P.SF);
777+
return swift::performTypeLocChecking(P.Context, T,
778+
/*isSILMode=*/true,
779+
IsSILType, &P.SF);
778780
}
779781

780782
/// Find the top-level ValueDecl or Module given a name.
@@ -814,7 +816,7 @@ bool SILParser::parseASTType(CanType &result) {
814816
ParserResult<TypeRepr> parsedType = P.parseType();
815817
if (parsedType.isNull()) return true;
816818
TypeLoc loc = parsedType.get();
817-
if (performTypeLocChecking(loc, false))
819+
if (performTypeLocChecking(loc, /*isSILType=*/ false))
818820
return true;
819821
result = loc.getType()->getCanonicalType();
820822
// Invoke the callback on the parsed type.
@@ -1371,7 +1373,7 @@ bool SILParser::parseApplySubstitutions(
13711373
if (TyR.isNull())
13721374
return true;
13731375
TypeLoc Ty = TyR.get();
1374-
if (performTypeLocChecking(Ty, false))
1376+
if (performTypeLocChecking(Ty, /*isSILType=*/ false))
13751377
return true;
13761378
parsed.push_back({Loc, Ty.getType()});
13771379
} while (P.consumeIf(tok::comma));
@@ -2875,7 +2877,7 @@ bool SILParser::parseSILInstruction(SILBasicBlock *BB, SILBuilder &B) {
28752877
}
28762878
}
28772879

2878-
if (performTypeLocChecking(Ty, false))
2880+
if (performTypeLocChecking(Ty, /*isSILType=*/ false))
28792881
return true;
28802882

28812883
if (P.parseToken(tok::comma, diag::expected_tok_in_sil_instr, ",") ||
@@ -4272,7 +4274,7 @@ bool SILParser::parseSpecConformanceSubstitutions(
42724274
if (TyR.isNull())
42734275
return true;
42744276
TypeLoc Ty = TyR.get();
4275-
if (performTypeLocChecking(Ty, false))
4277+
if (performTypeLocChecking(Ty, /*isSILType=*/ false))
42764278
return true;
42774279
parsed.push_back({Loc, Ty.getType()});
42784280
} while (P.consumeIf(tok::comma));
@@ -4326,7 +4328,7 @@ ProtocolConformance *SILParser::parseProtocolConformanceHelper(
43264328
if (TyR.isNull())
43274329
return nullptr;
43284330
TypeLoc Ty = TyR.get();
4329-
if (performTypeLocChecking(Ty, false))
4331+
if (performTypeLocChecking(Ty, /*isSILType=*/ false))
43304332
return nullptr;
43314333
auto ConformingTy = Ty.getType();
43324334

@@ -4520,7 +4522,9 @@ bool Parser::parseSILWitnessTable() {
45204522
if (TyR.isNull())
45214523
return true;
45224524
TypeLoc Ty = TyR.get();
4523-
if (swift::performTypeLocChecking(Context, Ty, false, &SF))
4525+
if (swift::performTypeLocChecking(Context, Ty,
4526+
/*isSILMode=*/ false,
4527+
/*isSILType=*/ false, &SF))
45244528
return true;
45254529

45264530
witnessEntries.push_back(SILWitnessTable::AssociatedTypeWitness{

lib/RemoteAST/RemoteAST.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,8 +426,7 @@ class RemoteASTTypeBuilder {
426426
DeclContext *dc = getNotionalDC();
427427

428428
TypeLoc loc(repr);
429-
if (performTypeLocChecking(Ctx, loc, /*SILType*/ false, dc,
430-
/*diagnose*/ false))
429+
if (performTypeLocChecking(Ctx, loc, dc, /*diagnose*/ false))
431430
return Type();
432431

433432
return loc.getType();

lib/SIL/SILPrinter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ class SILPrinter : public SILVisitor<SILPrinter> {
436436
PrintState{{PrintCtx.OS()}, PrintOptions::printSIL()},
437437
LastBufferID(0) {
438438
PrintState.ASTOptions.AlternativeTypeNames = AlternativeTypeNames;
439+
PrintState.ASTOptions.PrintForSIL = true;
439440
}
440441

441442
ID getID(const SILBasicBlock *B);

lib/Sema/TypeCheckType.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,20 @@ Type TypeResolver::resolveType(TypeRepr *repr, TypeResolutionOptions options) {
17241724
llvm_unreachable("all cases should be handled");
17251725
}
17261726

1727+
static Type rebuildWithDynamicSelf(ASTContext &Context, Type ty) {
1728+
OptionalTypeKind OTK;
1729+
if (auto metatypeTy = ty->getAs<MetatypeType>()) {
1730+
return MetatypeType::get(
1731+
rebuildWithDynamicSelf(Context, metatypeTy->getInstanceType()),
1732+
metatypeTy->getRepresentation());
1733+
} else if (auto optionalTy = ty->getAnyOptionalObjectType(OTK)) {
1734+
return OptionalType::get(
1735+
OTK, rebuildWithDynamicSelf(Context, optionalTy));
1736+
} else {
1737+
return DynamicSelfType::get(ty, Context);
1738+
}
1739+
}
1740+
17271741
Type TypeResolver::resolveAttributedType(AttributedTypeRepr *repr,
17281742
TypeResolutionOptions options) {
17291743
// Copy the attributes, since we're about to start hacking on them.
@@ -2018,7 +2032,13 @@ Type TypeResolver::resolveAttributedType(TypeAttributes &attrs,
20182032
ty = SILBoxType::get(ty->getCanonicalType());
20192033
attrs.clearAttribute(TAK_box);
20202034
}
2021-
2035+
2036+
// In SIL *only*, allow @dynamic_self to specify a dynamic Self type.
2037+
if ((options & TR_SILMode) && attrs.has(TAK_dynamic_self)) {
2038+
ty = rebuildWithDynamicSelf(TC.Context, ty);
2039+
attrs.clearAttribute(TAK_dynamic_self);
2040+
}
2041+
20222042
for (unsigned i = 0; i != TypeAttrKind::TAK_Count; ++i)
20232043
if (attrs.has((TypeAttrKind)i))
20242044
TC.diagnose(attrs.getLoc((TypeAttrKind)i),

lib/Sema/TypeChecker.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,12 +674,25 @@ void swift::performWholeModuleTypeChecking(SourceFile &SF) {
674674
}
675675

676676
bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
677-
bool isSILType, DeclContext *DC,
677+
DeclContext *DC,
678+
bool ProduceDiagnostics) {
679+
return performTypeLocChecking(Ctx, T,
680+
/*isSILMode=*/false,
681+
/*isSILType=*/false,
682+
DC, ProduceDiagnostics);
683+
}
684+
685+
bool swift::performTypeLocChecking(ASTContext &Ctx, TypeLoc &T,
686+
bool isSILMode,
687+
bool isSILType,
688+
DeclContext *DC,
678689
bool ProduceDiagnostics) {
679690
TypeResolutionOptions options;
680691

681692
// Fine to have unbound generic types.
682693
options |= TR_AllowUnboundGenerics;
694+
if (isSILMode)
695+
options |= TR_SILMode;
683696
if (isSILType)
684697
options |= TR_SILType;
685698

lib/Sema/TypeChecker.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,16 @@ enum TypeResolutionFlags : unsigned {
332332
/// Whether we are validating the type for SIL.
333333
TR_SILType = 0x10,
334334

335+
/// Whether we are parsing a SIL file. Not the same as TR_SILType,
336+
/// because the latter is not set if we're parsing an AST type.
337+
TR_SILMode = 0x20,
338+
335339
/// Whether we are in the input type of a function, or under one level of
336340
/// tuple type. This is not set for multi-level tuple arguments.
337-
TR_FunctionInput = 0x20,
341+
TR_FunctionInput = 0x40,
338342

339343
/// Whether this is the immediate input type to a function type,
340-
TR_ImmediateFunctionInput = 0x40,
344+
TR_ImmediateFunctionInput = 0x80,
341345

342346
/// Whether we are in the result type of a function body that is
343347
/// known to produce dynamic Self.

test/SIL/Parser/self.sil

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-frontend %s -parse-stdlib -module-name Swift -emit-silgen | FileCheck %s
2+
3+
enum Optional<T> {
4+
case none
5+
case some(T)
6+
}
7+
8+
enum ImplicitlyUnwrappedOptional<T> {
9+
case none
10+
case some(T)
11+
}
12+
13+
class SelfTest {}
14+
15+
sil_vtable SelfTest {}
16+
17+
sil @test_stuff : $@convention(thin) (@owned SelfTest) -> () {
18+
bb0(%0 : $SelfTest):
19+
// CHECK: metatype $@thick @dynamic_self SelfTest
20+
%2 = metatype $@thick @dynamic_self SelfTest.Type
21+
// CHECK: metatype $@thick Optional<@dynamic_self SelfTest>.Type
22+
%5 = metatype $@thick @dynamic_self SelfTest?.Type
23+
%7 = tuple ()
24+
return %7 : $()
25+
}

test/SILGen/dynamic_self.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func testDynamicSelfDispatch(y: Y) {
3636
// CHECK: bb0([[Y:%[0-9]+]] : $Y):
3737
// CHECK: strong_retain [[Y]]
3838
// CHECK: [[Y_AS_X:%[0-9]+]] = upcast [[Y]] : $Y to $X
39-
// CHECK: [[X_F:%[0-9]+]] = class_method [[Y_AS_X]] : $X, #X.f!1 : (X) -> () -> Self , $@convention(method) (@guaranteed X) -> @owned X
39+
// CHECK: [[X_F:%[0-9]+]] = class_method [[Y_AS_X]] : $X, #X.f!1 : (X) -> () -> @dynamic_self X , $@convention(method) (@guaranteed X) -> @owned X
4040
// CHECK: [[X_RESULT:%[0-9]+]] = apply [[X_F]]([[Y_AS_X]]) : $@convention(method) (@guaranteed X) -> @owned X
4141
// CHECK: strong_release [[Y_AS_X]]
4242
// CHECK: [[Y_RESULT:%[0-9]+]] = unchecked_ref_cast [[X_RESULT]] : $X to $Y
@@ -50,7 +50,7 @@ func testDynamicSelfDispatchGeneric(gy: GY<Int>) {
5050
// CHECK: bb0([[GY:%[0-9]+]] : $GY<Int>):
5151
// CHECK: strong_retain [[GY]]
5252
// CHECK: [[GY_AS_GX:%[0-9]+]] = upcast [[GY]] : $GY<Int> to $GX<Array<Int>>
53-
// CHECK: [[GX_F:%[0-9]+]] = class_method [[GY_AS_GX]] : $GX<Array<Int>>, #GX.f!1 : <T> (GX<T>) -> () -> Self , $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
53+
// CHECK: [[GX_F:%[0-9]+]] = class_method [[GY_AS_GX]] : $GX<Array<Int>>, #GX.f!1 : <T> (GX<T>) -> () -> @dynamic_self GX<T> , $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
5454
// CHECK: [[GX_RESULT:%[0-9]+]] = apply [[GX_F]]<[Int]>([[GY_AS_GX]]) : $@convention(method) <τ_0_0> (@guaranteed GX<τ_0_0>) -> @owned GX<τ_0_0>
5555
// CHECK: strong_release [[GY_AS_GX]]
5656
// CHECK: [[GY_RESULT:%[0-9]+]] = unchecked_ref_cast [[GX_RESULT]] : $GX<Array<Int>> to $GY<Int>
@@ -145,7 +145,7 @@ func testOptionalResult(v : OptionalResultInheritor) {
145145
v.foo()?.bar()
146146
}
147147
// CHECK-LABEL: sil hidden @_TF12dynamic_self18testOptionalResult{{.*}} : $@convention(thin) (@owned OptionalResultInheritor) -> ()
148-
// CHECK: [[T0:%.*]] = class_method [[V:%.*]] : $OptionalResult, #OptionalResult.foo!1 : (OptionalResult) -> () -> Self? , $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult>
148+
// CHECK: [[T0:%.*]] = class_method [[V:%.*]] : $OptionalResult, #OptionalResult.foo!1 : (OptionalResult) -> () -> @dynamic_self OptionalResult? , $@convention(method) (@guaranteed OptionalResult) -> @owned Optional<OptionalResult>
149149
// CHECK-NEXT: [[RES:%.*]] = apply [[T0]]([[V]])
150150
// CHECK: select_enum [[RES]]
151151
// CHECK: [[T1:%.*]] = unchecked_enum_data [[RES]]
@@ -183,8 +183,8 @@ class Z {
183183
// CHECK: [[WEAK_SELF:%.*]] = alloc_box $@sil_weak Optional<Z>
184184
// CHECK: [[FN:%.*]] = function_ref @_TFFC12dynamic_self1Z23testDynamicSelfCapturesFT1xSi_DS0_U1_FT_T_ : $@convention(thin) (@owned @box @sil_weak Optional<Z>, @thick Z.Type) -> ()
185185
// CHECK: strong_retain [[WEAK_SELF]] : $@box @sil_weak Optional<Z>
186-
// CHECK-NEXT: [[DYNAMIC_SELF:%.*]] = metatype $@thick Self.Type
187-
// CHECK-NEXT: [[STATIC_SELF:%.*]] = upcast [[DYNAMIC_SELF]] : $@thick Self.Type to $@thick Z.Type
186+
// CHECK-NEXT: [[DYNAMIC_SELF:%.*]] = metatype $@thick @dynamic_self Z.Type
187+
// CHECK-NEXT: [[STATIC_SELF:%.*]] = upcast [[DYNAMIC_SELF]] : $@thick @dynamic_self Z.Type to $@thick Z.Type
188188
// CHECK: partial_apply [[FN]]([[WEAK_SELF]], [[STATIC_SELF]]) : $@convention(thin) (@owned @box @sil_weak Optional<Z>, @thick Z.Type) -> ()
189189
let fn3 = {
190190
[weak self] in

test/SILGen/existential_erasure.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class EraseDynamicSelf {
124124

125125
// CHECK-LABEL: sil hidden @_TZFC19existential_erasure16EraseDynamicSelf7factoryfT_DS0_ : $@convention(method) (@thick EraseDynamicSelf.Type) -> @owned EraseDynamicSelf
126126
// CHECK: [[ANY:%.*]] = alloc_stack $Any
127-
// CHECK: init_existential_addr [[ANY]] : $*Any, $Self
127+
// CHECK: init_existential_addr [[ANY]] : $*Any, $@dynamic_self EraseDynamicSelf
128128
//
129129
class func factory() -> Self {
130130
let instance = self.init()

test/SILOptimizer/functionsigopts_self.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ extension C {
2424
// CHECK-LABEL: sil hidden @_TTSf4d_n___TZFC20functionsigopts_self1C7factory{{.*}} : $@convention(method) (@thick C.Type) -> @owned C
2525
// CHECK: bb0(%0 : $@thick C.Type):
2626
// CHECK: function_ref functionsigopts_self.gen <A> () -> A
27-
// CHECK: apply %{{[0-9]+}}<Self>
27+
// CHECK: apply %{{[0-9]+}}<@dynamic_self C>
2828

2929
// Call the function so the specialization is not dead.
3030
var x = C()

test/SILOptimizer/specialize_self.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func cast<T,R>(_ x: T) -> R? {
1111
// CHECK-LABEL: static specialize_self.Base.returnIfSelf (Swift.AnyObject) -> Swift.Optional<Self>
1212
// CHECK-NEXT: sil hidden @_TZFC15specialize_self4Base12returnIfSelf{{.*}} : $@convention(method) (@owned AnyObject, @thick Base.Type) -> @owned Optional<Base>
1313
// CHECK: [[CAST:%[0-9]+]] = function_ref @_TF15specialize_self4cast
14-
// CHECK: apply [[CAST]]<AnyObject, Self>
14+
// CHECK: apply [[CAST]]<AnyObject, @dynamic_self Base>
1515
class Base {
1616
class func returnIfSelf(_ x: AnyObject) -> Self? {
1717
return cast(x)

0 commit comments

Comments
 (0)