Skip to content

Commit 9044aa0

Browse files
committed
[AST] ParamDecl::isNonEphemeral() not to evaluate InterfaceTypeRequest
'-dump-parse' for the following code used to hit an assertion failure: struct MyStruct {} _ = { (val: MyStruct) in } Because 'isNonEphemeral()' on 'val' parameter unintentionally causes 'InterfaceTypeRequest::evaluate()'. Since 'isNonEphemeral()' inference based on the interface type is not possible after type checking, return 'false' unless 'hasInterfaceType()' Also: * Dump parameter list on 'EnumElementDecl' as well * Adjust the position of 'range=...' in parameter list dumping
1 parent 9855496 commit 9044aa0

File tree

4 files changed

+77
-34
lines changed

4 files changed

+77
-34
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5502,35 +5502,10 @@ class ParamDecl : public VarDecl {
55025502
}
55035503

55045504
/// Does this parameter reject temporary pointer conversions?
5505-
bool isNonEphemeral() const {
5506-
if (getAttrs().hasAttribute<NonEphemeralAttr>())
5507-
return true;
5508-
5509-
// Only pointer parameters can be non-ephemeral.
5510-
auto ty = getInterfaceType();
5511-
if (!ty->lookThroughSingleOptionalType()->getAnyPointerElementType())
5512-
return false;
5513-
5514-
// Enum element pointer parameters are always non-ephemeral.
5515-
auto *parentDecl = getDeclContext()->getAsDecl();
5516-
if (parentDecl && isa<EnumElementDecl>(parentDecl))
5517-
return true;
5518-
5519-
return false;
5520-
}
5505+
bool isNonEphemeral() const;
55215506

55225507
/// Attempt to apply an implicit `@_nonEphemeral` attribute to this parameter.
5523-
void setNonEphemeralIfPossible() {
5524-
// Don't apply the attribute if this isn't a pointer param.
5525-
auto type = getInterfaceType();
5526-
if (!type->lookThroughSingleOptionalType()->getAnyPointerElementType())
5527-
return;
5528-
5529-
if (!getAttrs().hasAttribute<NonEphemeralAttr>()) {
5530-
auto &ctx = getASTContext();
5531-
getAttrs().add(new (ctx) NonEphemeralAttr(/*IsImplicit*/ true));
5532-
}
5533-
}
5508+
void setNonEphemeralIfPossible();
55345509

55355510
/// Remove the type of this varargs element designator, without the array
55365511
/// type wrapping it. A parameter like "Int..." will have formal parameter

lib/AST/ASTDumper.cpp

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,12 @@ namespace {
900900

901901
void visitEnumElementDecl(EnumElementDecl *EED) {
902902
printCommon(EED, "enum_element_decl");
903+
if (auto *paramList = EED->getParameterList()) {
904+
Indent += 2;
905+
OS << "\n";
906+
printParameterList(paramList);
907+
Indent -= 2;
908+
}
903909
PrintWithColorRAII(OS, ParenthesisColor) << ')';
904910
}
905911

@@ -1011,7 +1017,7 @@ namespace {
10111017
if (P->isAutoClosure())
10121018
OS << " autoclosure";
10131019

1014-
if (P->isNonEphemeral())
1020+
if (P->getAttrs().hasAttribute<NonEphemeralAttr>())
10151021
OS << " nonEphemeral";
10161022

10171023
if (P->getDefaultArgumentKind() != DefaultArgumentKind::None) {
@@ -1038,11 +1044,6 @@ namespace {
10381044
OS.indent(Indent);
10391045
PrintWithColorRAII(OS, ParenthesisColor) << '(';
10401046
PrintWithColorRAII(OS, ParameterColor) << "parameter_list";
1041-
Indent += 2;
1042-
for (auto P : *params) {
1043-
OS << '\n';
1044-
printParameter(P);
1045-
}
10461047

10471048
if (!ctx && params->size() != 0 && params->get(0))
10481049
ctx = &params->get(0)->getASTContext();
@@ -1056,8 +1057,14 @@ namespace {
10561057
}
10571058
}
10581059

1059-
PrintWithColorRAII(OS, ParenthesisColor) << ')';
1060+
Indent += 2;
1061+
for (auto P : *params) {
1062+
OS << '\n';
1063+
printParameter(P);
1064+
}
10601065
Indent -= 2;
1066+
1067+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
10611068
}
10621069

10631070
void printAbstractFunctionDecl(AbstractFunctionDecl *D) {

lib/AST/Decl.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6266,6 +6266,36 @@ SourceRange ParamDecl::getSourceRange() const {
62666266
return startLoc;
62676267
}
62686268

6269+
bool ParamDecl::isNonEphemeral() const {
6270+
if (getAttrs().hasAttribute<NonEphemeralAttr>())
6271+
return true;
6272+
6273+
// Only enum element parameters are non-ephemeral without '@_nonEphemeral'.
6274+
auto *parentDecl = getDeclContext()->getAsDecl();
6275+
if (!parentDecl || !isa<EnumElementDecl>(parentDecl))
6276+
return false;
6277+
6278+
// Only pointer parameters can be non-ephemeral.
6279+
auto ty = getInterfaceType();
6280+
if (!ty->lookThroughSingleOptionalType()->getAnyPointerElementType())
6281+
return false;
6282+
6283+
return true;
6284+
}
6285+
6286+
void ParamDecl::setNonEphemeralIfPossible() {
6287+
assert(hasInterfaceType() && "Must be pre-typechecked.");
6288+
// Don't apply the attribute if this isn't a pointer param.
6289+
auto type = getInterfaceType();
6290+
if (!type->lookThroughSingleOptionalType()->getAnyPointerElementType())
6291+
return;
6292+
6293+
if (!getAttrs().hasAttribute<NonEphemeralAttr>()) {
6294+
auto &ctx = getASTContext();
6295+
getAttrs().add(new (ctx) NonEphemeralAttr(/*IsImplicit*/ true));
6296+
}
6297+
}
6298+
62696299
Type ParamDecl::getVarargBaseTy(Type VarArgT) {
62706300
TypeBase *T = VarArgT.getPointer();
62716301
if (auto *AT = dyn_cast<ArraySliceType>(T))

test/Frontend/dump-parse.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,34 @@ nonescaping({ $0 })
7373
// CHECK-AST: (declref_expr type='((Int) -> Int) -> ()'
7474
// CHECK-AST-NEXT: (paren_expr
7575
// CHECK-AST-NEXT: (closure_expr type='(Int) -> Int' {{.*}} discriminator=1 single-expression
76+
77+
// CHECK-LABEL: (struct_decl range=[{{.+}}] "MyStruct")
78+
struct MyStruct {}
79+
80+
// CHECK-LABEL: (enum_decl range=[{{.+}}] "MyEnum"
81+
enum MyEnum {
82+
83+
// CHECK-LABEL: (enum_case_decl range=[{{.+}}]
84+
// CHECK-NEXT: (enum_element_decl range=[{{.+}}] "foo(x:)"
85+
// CHECK-NEXT: (parameter_list range=[{{.+}}]
86+
// CHECK-NEXT: (parameter "x" apiName=x)))
87+
// CHECK-NEXT: (enum_element_decl range=[{{.+}}] "bar"))
88+
// CHECK-NEXT: (enum_element_decl range=[{{.+}}] "foo(x:)"
89+
// CHECK-NEXT: (parameter_list range=[{{.+}}]
90+
// CHECK-NEXT: (parameter "x" apiName=x)))
91+
// CHECK-NEXT: (enum_element_decl range=[{{.+}}] "bar"))
92+
case foo(x: MyStruct), bar
93+
}
94+
95+
// CHECK-LABEL: (top_level_code_decl range=[{{.+}}]
96+
// CHECK-NEXT: (brace_stmt implicit range=[{{.+}}]
97+
// CHECK-NEXT: (sequence_expr type='<null>'
98+
// CHECK-NEXT: (discard_assignment_expr type='<null>')
99+
// CHECK-NEXT: (assign_expr type='<null>'
100+
// CHECK-NEXT: (**NULL EXPRESSION**)
101+
// CHECK-NEXT: (**NULL EXPRESSION**))
102+
// CHECK-NEXT: (closure_expr type='<null>' discriminator={{[0-9]+}}
103+
// CHECK-NEXT: (parameter_list range=[{{.+}}]
104+
// CHECK-NEXT: (parameter "v"))
105+
// CHECK-NEXT: (brace_stmt range=[{{.+}}])))))
106+
_ = { (v: MyEnum) in }

0 commit comments

Comments
 (0)