Skip to content

Commit 2f133b3

Browse files
authored
Merge pull request #80843 from xedin/fix-printing-of-specifiers-and-attributes
[AST] ASTPrinter: Improvements to specifier and attribute printing
2 parents d0812a4 + 4fd4c00 commit 2f133b3

File tree

10 files changed

+95
-21
lines changed

10 files changed

+95
-21
lines changed

include/swift/AST/Decl.h

+15
Original file line numberDiff line numberDiff line change
@@ -6902,6 +6902,9 @@ class ParamDecl : public VarDecl {
69026902

69036903
/// Whether or not this parameter is 'sending'.
69046904
IsSending = 1 << 4,
6905+
6906+
/// Whether or not this parameter is isolated to a caller.
6907+
IsCallerIsolated = 1 << 5,
69056908
};
69066909

69076910
/// The type repr and 3 bits used for flags.
@@ -7190,6 +7193,18 @@ class ParamDecl : public VarDecl {
71907193
removeFlag(Flag::IsSending);
71917194
}
71927195

7196+
/// Whether or not this parameter is marked with 'nonisolated(nonsending)'.
7197+
bool isCallerIsolated() const {
7198+
return getOptions().contains(Flag::IsCallerIsolated);
7199+
}
7200+
7201+
void setCallerIsolated(bool value = true) {
7202+
if (value)
7203+
addFlag(Flag::IsCallerIsolated);
7204+
else
7205+
removeFlag(Flag::IsCallerIsolated);
7206+
}
7207+
71937208
/// Whether or not this parameter is marked with '@_addressable'.
71947209
bool isAddressable() const {
71957210
return getOptions().contains(Flag::IsAddressable);

lib/AST/ASTPrinter.cpp

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

38593859
switch (flags.getOwnershipSpecifier()) {
38603860
case ParamSpecifier::Default:
@@ -3883,7 +3883,7 @@ static void printParameterFlags(ASTPrinter &printer,
38833883

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

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

39143924
void PrintAST::visitVarDecl(VarDecl *decl) {
@@ -4024,11 +4034,24 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40244034

40254035
printArgName();
40264036

4037+
auto interfaceTy = param->getInterfaceType();
4038+
4039+
// If type of this parameter is isolated to a caller, let's
4040+
// strip the isolation from the type to avoid printing it as
4041+
// part of the function type because that would break ordering
4042+
// between specifiers and attributes.
4043+
if (param->isCallerIsolated()) {
4044+
if (auto *funcTy = dyn_cast<AnyFunctionType>(interfaceTy.getPointer())) {
4045+
interfaceTy =
4046+
funcTy->withIsolation(FunctionTypeIsolation::forNonIsolated());
4047+
}
4048+
}
4049+
40274050
TypeLoc TheTypeLoc;
40284051
if (auto *repr = param->getTypeRepr()) {
4029-
TheTypeLoc = TypeLoc(repr, param->getInterfaceType());
4052+
TheTypeLoc = TypeLoc(repr, interfaceTy);
40304053
} else {
4031-
TheTypeLoc = TypeLoc::withoutLoc(param->getInterfaceType());
4054+
TheTypeLoc = TypeLoc::withoutLoc(interfaceTy);
40324055
}
40334056

40344057
{
@@ -4040,7 +4063,8 @@ void PrintAST::printOneParameter(const ParamDecl *param,
40404063
!willUseTypeReprPrinting(TheTypeLoc, CurrentType, Options)) {
40414064
auto type = TheTypeLoc.getType();
40424065
printParameterFlags(Printer, Options, param, paramFlags,
4043-
isEscaping(type));
4066+
isEscaping(type),
4067+
param->isCallerIsolated());
40444068
}
40454069

40464070
printTypeLocForImplicitlyUnwrappedOptional(

lib/AST/Decl.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -8940,6 +8940,12 @@ void ParamDecl::setTypeRepr(TypeRepr *repr) {
89408940
continue;
89418941
}
89428942

8943+
if (auto *callerIsolated =
8944+
dyn_cast<CallerIsolatedTypeRepr>(unwrappedType)) {
8945+
setCallerIsolated(true);
8946+
unwrappedType = callerIsolated->getBase();
8947+
}
8948+
89438949
break;
89448950
}
89458951
}
@@ -11025,6 +11031,9 @@ AccessorDecl *AccessorDecl::createParsed(
1102511031
if (subscriptParam->isSending())
1102611032
param->setSending();
1102711033

11034+
if (subscriptParam->isCallerIsolated())
11035+
param->setCallerIsolated();
11036+
1102811037
newParams.push_back(param);
1102911038
}
1103011039

lib/Serialization/Deserialization.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -4110,6 +4110,7 @@ class DeclDeserializer {
41104110
bool isIsolated;
41114111
bool isCompileTimeLiteral, isConstValue;
41124112
bool isSending;
4113+
bool isCallerIsolated;
41134114
uint8_t rawDefaultArg;
41144115
TypeID defaultExprType;
41154116
uint8_t rawDefaultArgIsolation;
@@ -4122,6 +4123,7 @@ class DeclDeserializer {
41224123
isCompileTimeLiteral,
41234124
isConstValue,
41244125
isSending,
4126+
isCallerIsolated,
41254127
rawDefaultArg,
41264128
defaultExprType,
41274129
rawDefaultArgIsolation,
@@ -4167,6 +4169,7 @@ class DeclDeserializer {
41674169
param->setCompileTimeLiteral(isCompileTimeLiteral);
41684170
param->setConstValue(isConstValue);
41694171
param->setSending(isSending);
4172+
param->setCallerIsolated(isCallerIsolated);
41704173

41714174
// Decode the default argument kind.
41724175
// FIXME: Default argument expression, if available.

lib/Serialization/ModuleFormat.h

+2-1
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 = 941; // remove @execution attr
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 942; // `isCallerIsolated` parameter flag
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
@@ -1728,6 +1728,7 @@ namespace decls_block {
17281728
BCFixed<1>, // isCompileTimeLiteral?
17291729
BCFixed<1>, // isConst?
17301730
BCFixed<1>, // isSending?
1731+
BCFixed<1>, // isCallerIsolated?
17311732
DefaultArgumentField, // default argument kind
17321733
TypeIDField, // default argument type
17331734
ActorIsolationField, // default argument isolation

lib/Serialization/Serialization.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -4745,6 +4745,7 @@ class Serializer::DeclSerializer : public DeclVisitor<DeclSerializer> {
47454745
param->isCompileTimeLiteral(),
47464746
param->isConstVal(),
47474747
param->isSending(),
4748+
param->isCallerIsolated(),
47484749
getRawStableDefaultArgumentKind(argKind),
47494750
S.addTypeRef(defaultExprType),
47504751
getRawStableActorIsolationKind(isolation.getKind()),

test/Constraints/diagnostics.swift

+1-1
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

+9
Original file line numberDiff line numberDiff line change
@@ -100,3 +100,12 @@ public enum TestExtensible {
100100
case a
101101
case b
102102
}
103+
104+
public struct TestPlacementOfAttrsAndSpecifiers {
105+
// CHECK: public func test1<T>(_: sending @autoclosure () -> T)
106+
public func test1<T>(_: sending @autoclosure () -> T) {}
107+
// CHECK: public func test2<T>(_: borrowing @autoclosure () -> T)
108+
public func test2<T>(_: borrowing @autoclosure () -> T) {}
109+
// CHECK: public func test3<T>(_: inout () async -> T)
110+
public func test3<T>(_: inout () async -> T) {}
111+
}

test/ModuleInterface/execution_behavior_attrs.swift

+12
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

+3-3
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,12 @@ public func foo<S>(f: @escaping () -> (), ext int: Int = 2, s: S) where S: Seque
4141
// FOO-NEXT: "spelling": ": "
4242
// FOO-NEXT: },
4343
// FOO-NEXT: {
44-
// FOO-NEXT: "kind": "keyword",
45-
// FOO-NEXT: "spelling": "@escaping"
44+
// FOO-NEXT: "kind": "attribute",
45+
// FOO-NEXT: "spelling": "@escaping "
4646
// FOO-NEXT: },
4747
// FOO-NEXT: {
4848
// FOO-NEXT: "kind": "text",
49-
// FOO-NEXT: "spelling": " () -> (), "
49+
// FOO-NEXT: "spelling": "() -> (), "
5050
// FOO-NEXT: },
5151
// FOO-NEXT: {
5252
// FOO-NEXT: "kind": "externalParam",

0 commit comments

Comments
 (0)