Skip to content

Commit c18e231

Browse files
authored
Merge pull request #80892 from xedin/fix-printing-of-specifiers-and-attributes-6.2
[6.2][AST] ASTPrinter: Improvements to specifier and attribute printing
2 parents 393c24d + fbadca2 commit c18e231

File tree

10 files changed

+95
-21
lines changed

10 files changed

+95
-21
lines changed

include/swift/AST/Decl.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6911,6 +6911,9 @@ class ParamDecl : public VarDecl {
69116911

69126912
/// Whether or not this parameter is 'sending'.
69136913
IsSending = 1 << 4,
6914+
6915+
/// Whether or not this parameter is isolated to a caller.
6916+
IsCallerIsolated = 1 << 5,
69146917
};
69156918

69166919
/// The type repr and 3 bits used for flags.
@@ -7199,6 +7202,18 @@ class ParamDecl : public VarDecl {
71997202
removeFlag(Flag::IsSending);
72007203
}
72017204

7205+
/// Whether or not this parameter is marked with 'nonisolated(nonsending)'.
7206+
bool isCallerIsolated() const {
7207+
return getOptions().contains(Flag::IsCallerIsolated);
7208+
}
7209+
7210+
void setCallerIsolated(bool value = true) {
7211+
if (value)
7212+
addFlag(Flag::IsCallerIsolated);
7213+
else
7214+
removeFlag(Flag::IsCallerIsolated);
7215+
}
7216+
72027217
/// Whether or not this parameter is marked with '@_addressable'.
72037218
bool isAddressable() const {
72047219
return getOptions().contains(Flag::IsAddressable);

lib/AST/ASTPrinter.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3847,13 +3847,13 @@ static void printParameterFlags(ASTPrinter &printer,
38473847
const PrintOptions &options,
38483848
const ParamDecl *param,
38493849
ParameterTypeFlags flags,
3850-
bool escaping) {
3851-
if (!options.excludeAttrKind(TypeAttrKind::Autoclosure) &&
3852-
flags.isAutoClosure())
3853-
printer.printAttrName("@autoclosure ");
3854-
if (!options.excludeAttrKind(TypeAttrKind::NoDerivative) &&
3855-
flags.isNoDerivative())
3856-
printer.printAttrName("@noDerivative ");
3850+
bool escaping,
3851+
bool isIsolatedToCaller = false) {
3852+
// Always print `nonisolated(nonsending)` specifier on a parameter
3853+
// first, to avoid any issues with ordering.
3854+
if (isIsolatedToCaller) {
3855+
printer.printKeyword("nonisolated(nonsending)", options, " ");
3856+
}
38573857

38583858
switch (flags.getOwnershipSpecifier()) {
38593859
case ParamSpecifier::Default:
@@ -3882,7 +3882,7 @@ static void printParameterFlags(ASTPrinter &printer,
38823882

38833883
if (flags.isSending()) {
38843884
if (!options.SuppressSendingArgsAndResults) {
3885-
printer.printAttrName("sending ");
3885+
printer.printKeyword("sending", options, " ");
38863886
} else if (flags.getOwnershipSpecifier() ==
38873887
ParamSpecifier::ImplicitlyCopyableConsuming) {
38883888
// Ok. We are suppressing sending. If our ownership specifier was
@@ -3900,14 +3900,24 @@ static void printParameterFlags(ASTPrinter &printer,
39003900
printer.printKeyword("isolated", options, " ");
39013901
}
39023902

3903-
if (!options.excludeAttrKind(TypeAttrKind::Escaping) && escaping)
3904-
printer.printKeyword("@escaping", options, " ");
3905-
39063903
if (flags.isCompileTimeLiteral())
39073904
printer.printKeyword("_const", options, " ");
3908-
3905+
3906+
if (!options.excludeAttrKind(TypeAttrKind::Autoclosure) &&
3907+
flags.isAutoClosure())
3908+
printer.printAttrName("@autoclosure ");
3909+
if (!options.excludeAttrKind(TypeAttrKind::NoDerivative) &&
3910+
flags.isNoDerivative())
3911+
printer.printAttrName("@noDerivative ");
3912+
3913+
// `inout` implies `@escaping`
3914+
if (flags.getOwnershipSpecifier() != ParamSpecifier::InOut) {
3915+
if (!options.excludeAttrKind(TypeAttrKind::Escaping) && escaping)
3916+
printer.printAttrName("@escaping ");
3917+
}
3918+
39093919
if (flags.isConstValue())
3910-
printer.printKeyword("@const", options, " ");
3920+
printer.printAttrName("@const ");
39113921
}
39123922

39133923
void PrintAST::visitVarDecl(VarDecl *decl) {
@@ -4016,11 +4026,24 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40164026

40174027
printArgName();
40184028

4029+
auto interfaceTy = param->getInterfaceType();
4030+
4031+
// If type of this parameter is isolated to a caller, let's
4032+
// strip the isolation from the type to avoid printing it as
4033+
// part of the function type because that would break ordering
4034+
// between specifiers and attributes.
4035+
if (param->isCallerIsolated()) {
4036+
if (auto *funcTy = dyn_cast<AnyFunctionType>(interfaceTy.getPointer())) {
4037+
interfaceTy =
4038+
funcTy->withIsolation(FunctionTypeIsolation::forNonIsolated());
4039+
}
4040+
}
4041+
40194042
TypeLoc TheTypeLoc;
40204043
if (auto *repr = param->getTypeRepr()) {
4021-
TheTypeLoc = TypeLoc(repr, param->getInterfaceType());
4044+
TheTypeLoc = TypeLoc(repr, interfaceTy);
40224045
} else {
4023-
TheTypeLoc = TypeLoc::withoutLoc(param->getInterfaceType());
4046+
TheTypeLoc = TypeLoc::withoutLoc(interfaceTy);
40244047
}
40254048

40264049
{
@@ -4032,7 +4055,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40324055
!willUseTypeReprPrinting(TheTypeLoc, CurrentType, Options)) {
40334056
auto type = TheTypeLoc.getType();
40344057
printParameterFlags(Printer, Options, param, paramFlags,
4035-
isEscaping(type));
4058+
isEscaping(type),
4059+
param->isCallerIsolated());
40364060
}
40374061

40384062
printTypeLocForImplicitlyUnwrappedOptional(

lib/AST/Decl.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9010,6 +9010,12 @@ void ParamDecl::setTypeRepr(TypeRepr *repr) {
90109010
continue;
90119011
}
90129012

9013+
if (auto *callerIsolated =
9014+
dyn_cast<CallerIsolatedTypeRepr>(unwrappedType)) {
9015+
setCallerIsolated(true);
9016+
unwrappedType = callerIsolated->getBase();
9017+
}
9018+
90139019
break;
90149020
}
90159021
}
@@ -11095,6 +11101,9 @@ AccessorDecl *AccessorDecl::createParsed(
1109511101
if (subscriptParam->isSending())
1109611102
param->setSending();
1109711103

11104+
if (subscriptParam->isCallerIsolated())
11105+
param->setCallerIsolated();
11106+
1109811107
newParams.push_back(param);
1109911108
}
1110011109

lib/Serialization/Deserialization.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4117,6 +4117,7 @@ class DeclDeserializer {
41174117
bool isIsolated;
41184118
bool isCompileTimeLiteral, isConstValue;
41194119
bool isSending;
4120+
bool isCallerIsolated;
41204121
uint8_t rawDefaultArg;
41214122
TypeID defaultExprType;
41224123
uint8_t rawDefaultArgIsolation;
@@ -4129,6 +4130,7 @@ class DeclDeserializer {
41294130
isCompileTimeLiteral,
41304131
isConstValue,
41314132
isSending,
4133+
isCallerIsolated,
41324134
rawDefaultArg,
41334135
defaultExprType,
41344136
rawDefaultArgIsolation,
@@ -4174,6 +4176,7 @@ class DeclDeserializer {
41744176
param->setCompileTimeLiteral(isCompileTimeLiteral);
41754177
param->setConstValue(isConstValue);
41764178
param->setSending(isSending);
4179+
param->setCallerIsolated(isCallerIsolated);
41774180

41784181
// Decode the default argument kind.
41794182
// FIXME: Default argument expression, if available.

lib/Serialization/ModuleFormat.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 937; // remove @execution attr
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 938; // `isCallerIsolated` parameter flag
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1733,6 +1733,7 @@ namespace decls_block {
17331733
BCFixed<1>, // isCompileTimeLiteral?
17341734
BCFixed<1>, // isConst?
17351735
BCFixed<1>, // isSending?
1736+
BCFixed<1>, // isCallerIsolated?
17361737
DefaultArgumentField, // default argument kind
17371738
TypeIDField, // default argument type
17381739
ActorIsolationField, // default argument isolation

lib/Serialization/Serialization.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4750,6 +4750,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
47504750
param->isCompileTimeLiteral(),
47514751
param->isConstVal(),
47524752
param->isSending(),
4753+
param->isCallerIsolated(),
47534754
getRawStableDefaultArgumentKind(argKind),
47544755
S.addTypeRef(defaultExprType),
47554756
getRawStableActorIsolationKind(isolation.getKind()),

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ func rdar17170728() {
11271127
}
11281128

11291129
let _ = [i, j, k].reduce(0 as Int?) { // expected-error {{missing argument label 'into:' in call}}
1130-
// expected-error@-1 {{cannot convert value of type 'Int?' to expected argument type '(inout @escaping (Bool, Bool) -> Bool?, Int?) throws -> ()'}}
1130+
// expected-error@-1 {{cannot convert value of type 'Int?' to expected argument type '(inout (Bool, Bool) -> Bool?, Int?) throws -> ()'}}
11311131
$0 && $1 ? $0 + $1 : ($0 ? $0 : ($1 ? $1 : nil))
11321132
// expected-error@-1 {{binary operator '+' cannot be applied to two 'Bool' operands}}
11331133
}

test/ModuleInterface/attrs.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,12 @@ public func testExecutionConcurrent() async {}
9292
nonisolated(nonsending)
9393
public func testExecutionCaller() async {}
9494
// CHECK: nonisolated(nonsending) public func testExecutionCaller() async
95+
96+
public struct TestPlacementOfAttrsAndSpecifiers {
97+
// CHECK: public func test1<T>(_: sending @autoclosure () -> T)
98+
public func test1<T>(_: sending @autoclosure () -> T) {}
99+
// CHECK: public func test2<T>(_: borrowing @autoclosure () -> T)
100+
public func test2<T>(_: borrowing @autoclosure () -> T) {}
101+
// CHECK: public func test3<T>(_: inout () async -> T)
102+
public func test3<T>(_: inout () async -> T) {}
103+
}

test/ModuleInterface/execution_behavior_attrs.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@
55

66
// REQUIRES: concurrency
77

8+
public struct TestWithAttrs {
9+
// CHECK: #if compiler(>=5.3) && $AsyncExecutionBehaviorAttributes
10+
// CHECK-NEXT: public func test(_: nonisolated(nonsending) @escaping () async -> Swift.Void)
11+
// CHECK-NEXT: #endif
12+
public func test(_: nonisolated(nonsending) @escaping () async -> Void) {}
13+
14+
// CHECK: #if compiler(>=5.3) && $AsyncExecutionBehaviorAttributes
15+
// CHECK-NEXT: public func withInOut(fn: nonisolated(nonsending) inout () async -> Swift.Void)
16+
// CHECK-NEXT: #endif
17+
public func withInOut(fn: nonisolated(nonsending) inout () async -> Void) {}
18+
}
19+
820
public struct Test {
921
// CHECK: #if compiler(>=5.3) && $AsyncExecutionBehaviorAttributes
1022
// CHECK-NEXT: nonisolated(nonsending) public init() async

test/SymbolGraph/Symbols/Mixins/DeclarationFragments/Full/Function.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ public func foo<S>(f: @escaping () -> (), ext int: Int = 2, s: S) where S: Seque
3939
// CHECK-NEXT: "spelling": ": "
4040
// CHECK-NEXT: },
4141
// CHECK-NEXT: {
42-
// CHECK-NEXT: "kind": "keyword",
43-
// CHECK-NEXT: "spelling": "@escaping"
42+
// CHECK-NEXT: "kind": "attribute",
43+
// CHECK-NEXT: "spelling": "@escaping "
4444
// CHECK-NEXT: },
4545
// CHECK-NEXT: {
4646
// CHECK-NEXT: "kind": "text",
47-
// CHECK-NEXT: "spelling": " () -> (), "
47+
// CHECK-NEXT: "spelling": "() -> (), "
4848
// CHECK-NEXT: },
4949
// CHECK-NEXT: {
5050
// CHECK-NEXT: "kind": "externalParam",

0 commit comments

Comments
 (0)