Skip to content

Commit

Permalink
[sending] Begin parsing 'sending' while still accepting 'transferring'.
Browse files Browse the repository at this point in the history
A few things:

1. Internally except for in the parser and the clang importer, we only represent
'sending'. This means that it will be easy to remove 'transferring' once enough
time has passed.

2. I included a warning that suggested to the user to change 'transferring' ->
'sending'.

3. I duplicated the parsing diagnostics for 'sending' so both will still get
different sets of diagnostics for parsing issues... but anywhere below parsing,
I have just changed 'transferring' to 'sending' since transferring isn't
represented at those lower levels.

4. Since SendingArgsAndResults is always enabled when TransferringArgsAndResults
is enabled (NOTE not vis-a-versa), we know that we can always parse sending. So
we import "transferring" as "sending". This means that even if one marks a
function with "transferring", the compiler will guard it behind a
SendingArgsAndResults -D flag and in the imported header print out sending.

rdar://128216574
  • Loading branch information
gottesmm committed May 17, 2024
1 parent 71e95b9 commit b780ff6
Show file tree
Hide file tree
Showing 58 changed files with 947 additions and 237 deletions.
1 change: 1 addition & 0 deletions include/swift/AST/ASTBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,7 @@ enum ENUM_EXTENSIBILITY_ATTR(open) BridgedAttributedTypeSpecifier : size_t {
BridgedAttributedTypeSpecifierIsolated,
BridgedAttributedTypeSpecifierResultDependsOn,
BridgedAttributedTypeSpecifierTransferring,
BridgedAttributedTypeSpecifierSending,
};

SWIFT_NAME("BridgedUnqualifiedIdentTypeRepr.createParsed(_:loc:name:)")
Expand Down
4 changes: 2 additions & 2 deletions include/swift/AST/Builtins.def
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(GetCurrentAsyncTask, "getCurrentAsyncTask", "
BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Special)

/// startAsyncLet()<T>: (
/// __owned @escaping () async throws -> transferring T
/// __owned @escaping () async throws -> sending T
/// ) -> Builtin.RawPointer
///
/// DEPRECATED. startAsyncLetWithLocalBuffer is used instead.
Expand All @@ -878,7 +878,7 @@ BUILTIN_MISC_OPERATION_WITH_SILGEN(CancelAsyncTask, "cancelAsyncTask", "", Speci
BUILTIN_MISC_OPERATION(StartAsyncLet, "startAsyncLet", "", Special)

/// startAsyncLetWithLocalBuffer()<T>: (
/// __owned @escaping () async throws -> transferring T,
/// __owned @escaping () async throws -> sending T,
/// _ resultBuf: Builtin.RawPointer
/// ) -> Builtin.RawPointer
///
Expand Down
10 changes: 10 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -2200,6 +2200,16 @@ ERROR(transferring_after_parameter_specifier,none,
"'transferring' must be placed before specifier '%0'", (StringRef))
ERROR(transferring_repeated,none,
"parameter may have at most one 'transferring' specifier", ())
ERROR(sending_before_parameter_specifier,none,
"'sending' must be placed after specifier '%0'", (StringRef))
ERROR(sending_repeated,none,
"parameter may have at most one 'sending' specifier", ())
ERROR(sending_and_transferring_used_together,none,
"'transferring' and 'sending' may not be used together", ())
WARNING(transferring_is_now_sendable,none,
"'transferring' has been renamed to 'sending' and the 'transferring' spelling will be removed shortly",
())


#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
26 changes: 16 additions & 10 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -7972,17 +7972,23 @@ ERROR(lifetime_dependence_cannot_infer_ambiguous_candidate, none,
"Escapable",
())

//===----------------------------------------------------------------------===//
// MARK: Transferring
//===----------------------------------------------------------------------===//

ERROR(transferring_unsupported_param_specifier, none,
"'%0' cannot be applied to a 'transferring' parameter", (StringRef))
//===----------------------------------------------------------------------===//
// MARK: Transferring
//===----------------------------------------------------------------------===//

ERROR(transferring_only_on_parameters_and_results, none,
"'transferring' may only be used on parameters and results", ())
ERROR(transferring_cannot_be_applied_to_tuple_elt, none,
"'transferring' cannot be applied to tuple elements", ())
ERROR(transferring_unsupported_param_specifier, none,
"'%0' cannot be applied to a 'transferring' parameter", (StringRef))

ERROR(transferring_only_on_parameters_and_results, none,
"'transferring' may only be used on parameters and results", ())
ERROR(transferring_cannot_be_applied_to_tuple_elt, none,
"'transferring' cannot be applied to tuple elements", ())
ERROR(sending_unsupported_param_specifier, none,
"'%0' cannot be applied to a 'sending' parameter", (StringRef))
ERROR(sending_only_on_parameters_and_results, none,
"'sending' may only be used on parameters and results", ())
ERROR(sending_cannot_be_applied_to_tuple_elt, none,
"'sending' cannot be applied to tuple elements", ())

#define UNDEFINE_DIAGNOSTIC_MACROS
#include "DefineDiagnosticMacros.h"
4 changes: 2 additions & 2 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,8 @@ struct PrintOptions {
/// Suppress 'isolated' and '#isolation' on isolated parameters with optional type.
bool SuppressOptionalIsolatedParams = false;

/// Suppress 'transferring' on arguments and results.
bool SuppressTransferringArgsAndResults = false;
/// Suppress 'sending' on arguments and results.
bool SuppressSendingArgsAndResults = false;

/// Suppress Noncopyable generics.
bool SuppressNoncopyableGenerics = false;
Expand Down
19 changes: 18 additions & 1 deletion include/swift/AST/TypeRepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,8 @@ class SpecifierTypeRepr : public TypeRepr {
T->getKind() == TypeReprKind::CompileTimeConst ||
T->getKind() == TypeReprKind::ResultDependsOn ||
T->getKind() == TypeReprKind::LifetimeDependentReturn ||
T->getKind() == TypeReprKind::Transferring;
T->getKind() == TypeReprKind::Transferring ||
T->getKind() == TypeReprKind::Sending;
}
static bool classof(const SpecifierTypeRepr *T) { return true; }

Expand Down Expand Up @@ -1217,6 +1218,21 @@ class TransferringTypeRepr : public SpecifierTypeRepr {
static bool classof(const TransferringTypeRepr *T) { return true; }
};

/// A sending type.
/// \code
/// x : sending Int
/// \endcode
class SendingTypeRepr : public SpecifierTypeRepr {
public:
SendingTypeRepr(TypeRepr *Base, SourceLoc Loc)
: SpecifierTypeRepr(TypeReprKind::Sending, Base, Loc) {}

static bool classof(const TypeRepr *T) {
return T->getKind() == TypeReprKind::Sending;
}
static bool classof(const SendingTypeRepr *T) { return true; }
};

/// A TypeRepr for a known, fixed type.
///
/// Fixed type representations should be used sparingly, in places
Expand Down Expand Up @@ -1618,6 +1634,7 @@ inline bool TypeRepr::isSimple() const {
case TypeReprKind::SILBox:
case TypeReprKind::Isolated:
case TypeReprKind::Transferring:
case TypeReprKind::Sending:
case TypeReprKind::Placeholder:
case TypeReprKind::CompileTimeConst:
case TypeReprKind::ResultDependsOn:
Expand Down
1 change: 1 addition & 0 deletions include/swift/AST/TypeReprNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ ABSTRACT_TYPEREPR(Specifier, TypeRepr)
SPECIFIER_TYPEREPR(CompileTimeConst, SpecifierTypeRepr)
SPECIFIER_TYPEREPR(ResultDependsOn, SpecifierTypeRepr)
SPECIFIER_TYPEREPR(Transferring, SpecifierTypeRepr)
SPECIFIER_TYPEREPR(Sending, SpecifierTypeRepr)
TYPEREPR(Fixed, TypeRepr)
TYPEREPR(SILBox, TypeRepr)
TYPEREPR(Self, TypeRepr)
Expand Down
9 changes: 8 additions & 1 deletion include/swift/Basic/Features.def
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,14 @@ EXPERIMENTAL_FEATURE(FixedArrays, true)
EXPERIMENTAL_FEATURE(GroupActorErrors, true)

// Allow for the 'transferring' keyword to be applied to arguments and results.
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(TransferringArgsAndResults, true)
//
// Enables SendingArgsAndResults as well. After parsing, we just represent this
// as 'sendable' implying that since both are always enabled together, this
// doesn't need to be suppressed.
EXPERIMENTAL_FEATURE(TransferringArgsAndResults, true)

// Allow for the 'sending' keyword to be applied to arguments and results.
SUPPRESSIBLE_EXPERIMENTAL_FEATURE(SendingArgsAndResults, true)

// Enable explicit isolation of closures.
EXPERIMENTAL_FEATURE(ClosureIsolation, true)
Expand Down
7 changes: 7 additions & 0 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,9 @@ class Parser {
if (Context.LangOpts.hasFeature(Feature::TransferringArgsAndResults) &&
Tok.isContextualKeyword("transferring"))
return true;
if (Context.LangOpts.hasFeature(Feature::SendingArgsAndResults) &&
Tok.isContextualKeyword("sending"))
return true;
if (Context.LangOpts.hasFeature(Feature::NonescapableTypes) &&
(Tok.isContextualKeyword("_resultDependsOn") ||
isLifetimeDependenceToken()))
Expand Down Expand Up @@ -1256,6 +1259,7 @@ class Parser {
SourceLoc ConstLoc;
SourceLoc ResultDependsOnLoc;
SourceLoc TransferringLoc;
SourceLoc SendingLoc;
SmallVector<TypeOrCustomAttr> Attributes;
SmallVector<LifetimeDependenceSpecifier> lifetimeDependenceSpecifiers;

Expand Down Expand Up @@ -1573,6 +1577,9 @@ class Parser {
/// The location of the 'transferring' keyword if present.
SourceLoc TransferringLoc;

/// The location of the 'sending' keyword if present.
SourceLoc SendingLoc;

/// The type following the ':'.
TypeRepr *Type = nullptr;

Expand Down
5 changes: 5 additions & 0 deletions lib/AST/ASTBridging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,8 @@ BridgedParamDecl BridgedParamDecl_createParsed(
paramDecl->setCompileTimeConst(true);
else if (isa<TransferringTypeRepr>(STR))
paramDecl->setSending(true);
else if (isa<SendingTypeRepr>(STR))
paramDecl->setSending(true);

unwrappedType = STR->getBase();
continue;
Expand Down Expand Up @@ -2225,6 +2227,9 @@ BridgedSpecifierTypeRepr BridgedSpecifierTypeRepr_createParsed(
case BridgedAttributedTypeSpecifierTransferring: {
return new (context) TransferringTypeRepr(baseType, loc);
}
case BridgedAttributedTypeSpecifierSending: {
return new (context) SendingTypeRepr(baseType, loc);
}
case BridgedAttributedTypeSpecifierConst: {
return new (context) CompileTimeConstTypeRepr(baseType, loc);
}
Expand Down
6 changes: 6 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3450,6 +3450,12 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr, void, StringRef>,
printFoot();
}

void visitSendingTypeRepr(SendingTypeRepr *T, StringRef label) {
printCommon("sending", label);
printRec(T->getBase());
printFoot();
}

void visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T, StringRef label) {
printCommon("_const", label);
printRec(T->getBase());
Expand Down
29 changes: 15 additions & 14 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3117,10 +3117,10 @@ static void suppressingFeatureOptionalIsolatedParameters(
action();
}

static void suppressingFeatureTransferringArgsAndResults(
PrintOptions &options, llvm::function_ref<void()> action) {
llvm::SaveAndRestore<bool> scope(options.SuppressTransferringArgsAndResults,
true);
static void
suppressingFeatureSendingArgsAndResults(PrintOptions &options,
llvm::function_ref<void()> action) {
llvm::SaveAndRestore<bool> scope(options.SuppressSendingArgsAndResults, true);
action();
}

Expand Down Expand Up @@ -3722,8 +3722,6 @@ static void printParameterFlags(ASTPrinter &printer,
if (!options.excludeAttrKind(TypeAttrKind::NoDerivative) &&
flags.isNoDerivative())
printer.printAttrName("@noDerivative ");
if (!options.SuppressTransferringArgsAndResults && flags.isSending())
printer.printAttrName("transferring ");

switch (flags.getOwnershipSpecifier()) {
case ParamSpecifier::Default:
Expand All @@ -3749,11 +3747,14 @@ static void printParameterFlags(ASTPrinter &printer,
printer.printKeyword("__owned", options, " ");
break;
case ParamSpecifier::ImplicitlyCopyableConsuming:
// Nothing... we infer from transferring.
assert(flags.isSending() && "Only valid when transferring is enabled");
// Nothing... we infer from sending.
assert(flags.isSending() && "Only valid when sending is enabled");
break;
}


if (!options.SuppressSendingArgsAndResults && flags.isSending())
printer.printAttrName("sending ");

if (flags.isIsolated()) {
if (!(param && param->getInterfaceType()->isOptional() &&
options.SuppressOptionalIsolatedParams))
Expand Down Expand Up @@ -4183,13 +4184,13 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
}
}

if (!Options.SuppressTransferringArgsAndResults) {
if (!Options.SuppressSendingArgsAndResults) {
if (decl->hasSendingResult()) {
Printer << "transferring ";
Printer << "sending ";
} else if (auto *ft = llvm::dyn_cast_if_present<AnyFunctionType>(
decl->getInterfaceType())) {
if (ft->hasExtInfo() && ft->hasSendingResult()) {
Printer << "transferring ";
Printer << "sending ";
}
}
}
Expand Down Expand Up @@ -6652,9 +6653,9 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

Printer << " -> ";

if (!Options.SuppressTransferringArgsAndResults && T->hasExtInfo() &&
if (!Options.SuppressSendingArgsAndResults && T->hasExtInfo() &&
T->hasSendingResult()) {
Printer.printKeyword("transferring ", Options);
Printer.printKeyword("sending ", Options);
}

if (T->hasLifetimeDependenceInfo()) {
Expand Down
4 changes: 4 additions & 0 deletions lib/AST/ASTWalker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2340,6 +2340,10 @@ bool Traversal::visitTransferringTypeRepr(TransferringTypeRepr *T) {
return doIt(T->getBase());
}

bool Traversal::visitSendingTypeRepr(SendingTypeRepr *T) {
return doIt(T->getBase());
}

bool Traversal::visitCompileTimeConstTypeRepr(CompileTimeConstTypeRepr *T) {
return doIt(T->getBase());
}
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10232,7 +10232,8 @@ FuncDecl *FuncDecl::create(ASTContext &Context, SourceLoc StaticLoc,
ClangNode());
FD->setParameters(BodyParams);
FD->FnRetType = TypeLoc(ResultTyR);
if (llvm::isa_and_nonnull<TransferringTypeRepr>(ResultTyR))
if (llvm::isa_and_nonnull<TransferringTypeRepr>(ResultTyR) ||
llvm::isa_and_nonnull<SendingTypeRepr>(ResultTyR))
FD->setSendingResult();
return FD;
}
Expand Down
11 changes: 6 additions & 5 deletions lib/AST/FeatureSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,8 +644,9 @@ UNINTERESTING_FEATURE(BitwiseCopyable)
UNINTERESTING_FEATURE(FixedArrays)
UNINTERESTING_FEATURE(GroupActorErrors)

static bool usesFeatureTransferringArgsAndResults(Decl *decl) {
auto functionTypeUsesTransferring = [](Decl *decl) {
UNINTERESTING_FEATURE(TransferringArgsAndResults)
static bool usesFeatureSendingArgsAndResults(Decl *decl) {
auto functionTypeUsesSending = [](Decl *decl) {
return usesTypeMatching(decl, [](Type type) {
auto fnType = type->getAs<AnyFunctionType>();
if (!fnType)
Expand All @@ -666,17 +667,17 @@ static bool usesFeatureTransferringArgsAndResults(Decl *decl) {
return true;
}

if (functionTypeUsesTransferring(pd))
if (functionTypeUsesSending(pd))
return true;
}

if (auto *fDecl = dyn_cast<FuncDecl>(decl)) {
// First check for param decl results.
if (llvm::any_of(fDecl->getParameters()->getArray(), [](ParamDecl *pd) {
return usesFeatureTransferringArgsAndResults(pd);
return usesFeatureSendingArgsAndResults(pd);
}))
return true;
if (functionTypeUsesTransferring(decl))
if (functionTypeUsesSending(decl))
return true;
}

Expand Down
1 change: 1 addition & 0 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3152,6 +3152,7 @@ directReferencesForTypeRepr(Evaluator &evaluator,
case TypeReprKind::ResultDependsOn:
case TypeReprKind::LifetimeDependentReturn:
case TypeReprKind::Transferring:
case TypeReprKind::Sending:
return result;

case TypeReprKind::Fixed:
Expand Down
3 changes: 3 additions & 0 deletions lib/AST/TypeRepr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,6 +850,9 @@ void SpecifierTypeRepr::printImpl(ASTPrinter &Printer,
case TypeReprKind::Transferring:
Printer.printKeyword("transferring", Opts, " ");
break;
case TypeReprKind::Sending:
Printer.printKeyword("sending", Opts, " ");
break;
case TypeReprKind::CompileTimeConst:
Printer.printKeyword("_const", Opts, " ");
break;
Expand Down
2 changes: 2 additions & 0 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,8 @@ void importer::getNormalInvocationArguments(
// is supported.
if (LangOpts.hasFeature(Feature::TransferringArgsAndResults))
invocationArgStrs.push_back("-D__SWIFT_ATTR_SUPPORTS_TRANSFERRING=1");
if (LangOpts.hasFeature(Feature::SendingArgsAndResults))
invocationArgStrs.push_back("-D__SWIFT_ATTR_SUPPORTS_SENDING=1");

if (searchPathOpts.getSDKPath().empty()) {
invocationArgStrs.push_back("-Xclang");
Expand Down
11 changes: 11 additions & 0 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8062,6 +8062,17 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
continue;
}

if (swiftAttr->getAttribute() == "sending") {
// Swallow this if the feature is not enabled.
if (!SwiftContext.LangOpts.hasFeature(Feature::SendingArgsAndResults))
continue;
auto *funcDecl = dyn_cast<FuncDecl>(MappedDecl);
if (!funcDecl)
continue;
funcDecl->setSendingResult();
continue;
}

if (swiftAttr->getAttribute() == "sensitive") {
if (!SwiftContext.LangOpts.hasFeature(Feature::Sensitive))
continue;
Expand Down
11 changes: 11 additions & 0 deletions lib/ClangImporter/ImportType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2602,6 +2602,17 @@ static ParamDecl *getParameterInfo(ClangImporter::Implementation *impl,
}
}

// If TransferringArgsAndResults are enabled and we have a transferring
// argument, set that the param was transferring.
if (paramInfo->getASTContext().LangOpts.hasFeature(
Feature::SendingArgsAndResults)) {
if (auto *attr = param->getAttr<clang::SwiftAttrAttr>()) {
if (attr->getAttribute() == "sending") {
paramInfo->setSending();
}
}
}

// Foreign references are already references so they don't need to be passed
// as inout.
paramInfo->setSpecifier(isInOut && !swiftParamTy->isForeignReferenceType()
Expand Down
Loading

0 comments on commit b780ff6

Please sign in to comment.