-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[Sema] Implement type erasure for dynamic replacement. #30101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
96d7434
3032dbd
3a361c7
3cdc30f
5ce5096
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -985,6 +985,20 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options, | |
break; | ||
} | ||
|
||
case DAK_TypeEraser: { | ||
Printer.printAttrName("@_typeEraser"); | ||
Printer << "("; | ||
Printer.callPrintNamePre(PrintNameContext::Attribute); | ||
auto typeLoc = cast<TypeEraserAttr>(this)->getTypeEraserLoc(); | ||
if (auto type = typeLoc.getType()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's an option to prefer the |
||
type->print(Printer, Options); | ||
else | ||
typeLoc.getTypeRepr()->print(Printer, Options); | ||
Printer.printNamePost(PrintNameContext::Attribute); | ||
Printer << ")"; | ||
break; | ||
} | ||
|
||
case DAK_Custom: { | ||
Printer.callPrintNamePre(PrintNameContext::Attribute); | ||
Printer << "@"; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7417,6 +7417,7 @@ ExprWalker::rewriteTarget(SolutionApplicationTarget target) { | |
return None; | ||
|
||
result.setFunctionBody(newBody); | ||
fn.getAbstractFunctionDecl()->setHasSingleExpressionBody(false); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anything that calls |
||
} | ||
|
||
// Follow-up tasks. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// RUN: %target-swift-frontend -typecheck -disable-availability-checking -dump-ast %s | %FileCheck %s | ||
|
||
class AnyP: P { | ||
init<T: P>(erasing: T) {} | ||
} | ||
|
||
@_typeEraser(AnyP) | ||
protocol P {} | ||
|
||
struct ConcreteP: P, Hashable {} | ||
|
||
// CHECK-LABEL: testBasic | ||
dynamic func testBasic() -> some P { | ||
// CHECK: underlying_to_opaque_expr{{.*}}'some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: testTypeAlias | ||
typealias AliasForP = P | ||
dynamic func testTypeAlias() -> some AliasForP { | ||
// CHECK: underlying_to_opaque_expr{{.*}}'some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: testNoDynamic | ||
func testNoDynamic() -> some P { | ||
// CHECK: underlying_to_opaque_expr{{.*}}'some P' | ||
// CHECK-NEXT: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: testNoOpaque | ||
dynamic func testNoOpaque() -> P { | ||
// CHECK: erasure_expr implicit type='P' | ||
// CHECK-NEXT: normal_conformance type=ConcreteP protocol=P | ||
// CHECK-NEXT: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: testComposition | ||
typealias Composition = P & Hashable | ||
dynamic func testComposition() -> some Composition { | ||
// CHECK: underlying_to_opaque_expr{{.*}}'some Hashable & P' | ||
// CHECK-NEXT: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: struct_decl{{.*}}Builder | ||
@_functionBuilder | ||
struct Builder { | ||
static func buildBlock(_ params: P...) -> ConcreteP { | ||
return ConcreteP() | ||
} | ||
} | ||
|
||
// CHECK-LABEL: TestFunctionBuilder | ||
class TestFunctionBuilder { | ||
// CHECK-LABEL: testTransformFnBody | ||
@Builder dynamic var testTransformFnBody: some P { | ||
// CHECK: return_stmt | ||
// CHECK-NEXT: underlying_to_opaque_expr implicit type='some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: declref_expr implicit type='@lvalue ConcreteP' | ||
ConcreteP() | ||
} | ||
|
||
// CHECK-LABEL: func_decl{{.*}}takesBuilder | ||
func takesBuilder(@Builder closure: () -> ConcreteP) -> ConcreteP { closure() } | ||
|
||
// CHECK-LABEL: testClosureBuilder | ||
dynamic var testClosureBuilder: some P { | ||
// CHECK: underlying_to_opaque_expr implicit type='some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: closure_expr type='() -> ConcreteP' | ||
takesBuilder { | ||
// CHECK: return_stmt | ||
// CHECK-NEXT: load_expr implicit type='ConcreteP' | ||
ConcreteP() | ||
} | ||
} | ||
} | ||
|
||
// CHECK-LABEL: class_decl{{.*}}DynamicReplacement | ||
class DynamicReplacement { | ||
dynamic func testDynamicReplaceable() -> some P { | ||
// CHECK: underlying_to_opaque_expr implicit type='some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: call_expr type='ConcreteP' | ||
ConcreteP() | ||
} | ||
} | ||
|
||
// CHECK-LABEL: extension_decl{{.*}}DynamicReplacement | ||
extension DynamicReplacement { | ||
// CHECK-LABEL: testDynamicReplacement | ||
@_dynamicReplacement(for: testDynamicReplaceable) | ||
func testDynamicReplacement() -> some P { | ||
print("not single expr return") | ||
// CHECK: return_stmt | ||
// CHECK-NEXT: underlying_to_opaque_expr implicit type='some P' | ||
// CHECK-NEXT: call_expr implicit type='AnyP'{{.*}}arg_labels=erasing: | ||
// CHECK: call_expr type='ConcreteP' | ||
return ConcreteP() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm. Please bump the version number in
ModuleFormat.h
to account for this.