Skip to content

Commit 01d4eeb

Browse files
authored
Merge pull request #4028 from swiftwasm/main
[pull] swiftwasm from main
2 parents cdaa37b + 88fb8c2 commit 01d4eeb

22 files changed

+228
-112
lines changed

include/swift/AST/Attr.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ SIMPLE_DECL_ATTR(dynamicCallable, DynamicCallable,
150150
OnNominalType |
151151
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
152152
6)
153-
SIMPLE_DECL_ATTR(main, MainType,
153+
DECL_ATTR(main, MainType,
154154
OnClass | OnStruct | OnEnum | OnExtension |
155155
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove,
156156
7)

include/swift/AST/Attr.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,25 @@ class ObjCAttr final : public DeclAttribute,
915915
}
916916
};
917917

918+
class MainTypeAttr final : public DeclAttribute {
919+
public:
920+
MainTypeAttr(bool isImplicit)
921+
: DeclAttribute(DAK_MainType, SourceLoc(), SourceLoc(), isImplicit) {}
922+
923+
MainTypeAttr(SourceLoc AtLoc, SourceLoc NameLoc)
924+
: DeclAttribute(DAK_MainType, AtLoc,
925+
SourceRange(AtLoc.isValid() ? AtLoc : NameLoc, NameLoc),
926+
/*Implicit=*/false) {}
927+
928+
MainTypeAttr(SourceLoc NameLoc)
929+
: DeclAttribute(DAK_MainType, SourceLoc(), SourceRange(NameLoc, NameLoc),
930+
/*Implicit=*/false) {}
931+
932+
static bool classof(const DeclAttribute *DA) {
933+
return DA->getKind() == DAK_MainType;
934+
}
935+
};
936+
918937
class PrivateImportAttr final
919938
: public DeclAttribute {
920939
StringRef SourceFile;

include/swift/AST/DiagnosticsSema.def

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4575,17 +4575,36 @@ NOTE(protocol_isolated_to_global_actor_here,none,
45754575

45764576
ERROR(isolated_parameter_not_actor,none,
45774577
"'isolated' parameter has non-actor type %0", (Type))
4578-
4578+
45794579
WARNING(non_sendable_param_type,none,
4580-
"cannot pass argument of non-sendable type %0 across actors",
4581-
(Type))
4580+
"non-sendable type %0 %select{passed in call to %4 %2 %3|"
4581+
"passed in implicitly asynchronous call to %4 %2 %3|"
4582+
"in parameter of %4 %2 %3 satisfying non-isolated protocol "
4583+
"requirement|"
4584+
"in parameter of %4 '@objc' %2 %3}1 cannot cross actor boundary",
4585+
(Type, unsigned, DescriptiveDeclKind, DeclName, ActorIsolation))
4586+
WARNING(non_sendable_call_param_type,none,
4587+
"non-sendable type %0 passed in %select{implicitly asynchronous |}1"
4588+
"call to %2 function cannot cross actor boundary",
4589+
(Type, bool, ActorIsolation))
45824590
WARNING(non_sendable_result_type,none,
4583-
"cannot call function returning non-sendable type %0 across "
4584-
"actors", (Type))
4591+
"non-sendable type %0 returned by %select{call to %4 %2 %3|"
4592+
"implicitly asynchronous call to %4 %2 %3|"
4593+
"%4 %2 %3 satisfying non-isolated protocol requirement|"
4594+
"%4 '@objc' %2 %3}1 cannot cross actor boundary",
4595+
(Type, unsigned, DescriptiveDeclKind, DeclName, ActorIsolation))
4596+
WARNING(non_sendable_call_result_type,none,
4597+
"non-sendable type %0 returned by %select{implicitly asynchronous |}1"
4598+
"call to %2 function cannot cross actor boundary",
4599+
(Type, bool, ActorIsolation))
45854600
WARNING(non_sendable_property_type,none,
4586-
"cannot use %1 %2 with a non-sendable type %0 "
4587-
"%select{across actors|from concurrently-executed code}3",
4588-
(Type, DescriptiveDeclKind, DeclName, bool))
4601+
"non-sendable type %0 in %select{"
4602+
"%select{asynchronous access to %5 %1 %2|"
4603+
"implicitly asynchronous access to %5 %1 %2|"
4604+
"conformance of %5 %1 %2 to non-isolated protocol requirement|"
4605+
"%5 '@objc' %1 %2}4|captured local %1 %2}3 cannot "
4606+
"cross %select{actor|task}3 boundary",
4607+
(Type, DescriptiveDeclKind, DeclName, bool, unsigned, ActorIsolation))
45894608
WARNING(non_sendable_keypath_capture,none,
45904609
"cannot form key path that captures non-sendable type %0",
45914610
(Type))

lib/AST/Attr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -895,6 +895,14 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
895895
}
896896
return true;
897897

898+
case DAK_MainType: {
899+
// Don't print into SIL. Necessary bits have already been generated.
900+
if (Options.PrintForSIL)
901+
return false;
902+
Printer.printSimpleAttr(getAttrName(), /*needAt=*/true);
903+
return true;
904+
}
905+
898906
case DAK_SetterAccess:
899907
Printer.printKeyword(getAttrName(), Options, "(set)");
900908
return true;
@@ -1241,6 +1249,8 @@ StringRef DeclAttribute::getAttrName() const {
12411249
case DAK_ObjC:
12421250
case DAK_ObjCRuntimeName:
12431251
return "objc";
1252+
case DAK_MainType:
1253+
return "main";
12441254
case DAK_DynamicReplacement:
12451255
return "_dynamicReplacement";
12461256
case DAK_TypeEraser:

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,23 +1611,25 @@ void GenericSignature::verify(ArrayRef<Requirement> reqts) const {
16111611
break;
16121612

16131613
case RequirementKind::SameType: {
1614-
auto isCanonicalAnchor = [&](Type type) {
1615-
if (auto *dmt = type->getAs<DependentMemberType>())
1616-
return canSig->isCanonicalTypeInContext(dmt->getBase());
1614+
auto hasCanonicalOrConcreteParent = [&](Type type) {
1615+
if (auto *dmt = type->getAs<DependentMemberType>()) {
1616+
return (canSig->isCanonicalTypeInContext(dmt->getBase()) ||
1617+
canSig->isConcreteType(dmt->getBase()));
1618+
}
16171619
return type->is<GenericTypeParamType>();
16181620
};
16191621

16201622
auto firstType = reqt.getFirstType();
16211623
auto secondType = reqt.getSecondType();
1622-
if (!isCanonicalAnchor(firstType)) {
1624+
if (!hasCanonicalOrConcreteParent(firstType)) {
16231625
llvm::errs() << "Left hand side does not have a canonical parent: ";
16241626
reqt.dump(llvm::errs());
16251627
llvm::errs() << "\n";
16261628
abort();
16271629
}
16281630

16291631
if (reqt.getSecondType()->isTypeParameter()) {
1630-
if (!isCanonicalAnchor(secondType)) {
1632+
if (!hasCanonicalOrConcreteParent(secondType)) {
16311633
llvm::errs() << "Right hand side does not have a canonical parent: ";
16321634
reqt.dump(llvm::errs());
16331635
llvm::errs() << "\n";

lib/AST/RequirementMachine/GenericSignatureQueries.cpp

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -260,26 +260,38 @@ RequirementMachine::getLongestValidPrefix(const MutableTerm &term) const {
260260
/// concrete type).
261261
bool RequirementMachine::isCanonicalTypeInContext(Type type) const {
262262
// Look for non-canonical type parameters.
263-
return !type.findIf([&](Type component) -> bool {
264-
if (!component->isTypeParameter())
265-
return false;
263+
class Walker : public TypeWalker {
264+
const RequirementMachine &Self;
266265

267-
auto term = Context.getMutableTermForType(component->getCanonicalType(),
268-
/*proto=*/nullptr);
266+
public:
267+
explicit Walker(const RequirementMachine &self) : Self(self) {}
269268

270-
System.simplify(term);
271-
verify(term);
269+
Action walkToTypePre(Type component) override {
270+
if (!component->isTypeParameter())
271+
return Action::Continue;
272272

273-
auto *props = Map.lookUpProperties(term);
274-
if (!props)
275-
return false;
273+
auto term = Self.Context.getMutableTermForType(
274+
component->getCanonicalType(),
275+
/*proto=*/nullptr);
276276

277-
if (props->isConcreteType())
278-
return true;
277+
Self.System.simplify(term);
278+
Self.verify(term);
279279

280-
auto anchor = Context.getTypeForTerm(term, {});
281-
return CanType(anchor) != CanType(component);
282-
});
280+
auto anchor = Self.Context.getTypeForTerm(term, {});
281+
if (CanType(anchor) != CanType(component))
282+
return Action::Stop;
283+
284+
auto *props = Self.Map.lookUpProperties(term);
285+
if (props && props->isConcreteType())
286+
return Action::Stop;
287+
288+
// The parent of a canonical type parameter might be non-canonical
289+
// because it is concrete.
290+
return Action::SkipChildren;
291+
}
292+
};
293+
294+
return !type.walk(Walker(*this));
283295
}
284296

285297
/// Unlike most other queries, the input type can be any type, not just a

lib/Parse/ParseDecl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1943,6 +1943,11 @@ bool Parser::parseNewDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
19431943
break;
19441944
#include "swift/AST/Attr.def"
19451945

1946+
case DAK_MainType:
1947+
if (!DiscardAttribute)
1948+
Attributes.add(new (Context) MainTypeAttr(AtLoc, Loc));
1949+
break;
1950+
19461951
case DAK_Effects: {
19471952
auto kind = parseSingleAttrOption<EffectsKind>
19481953
(*this, Loc, AttrRange, AttrName, DK)

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -781,22 +781,26 @@ bool swift::diagnoseNonSendableTypes(
781781

782782
bool swift::diagnoseNonSendableTypesInReference(
783783
ConcreteDeclRef declRef, const DeclContext *fromDC, SourceLoc loc,
784-
ConcurrentReferenceKind refKind) {
784+
SendableCheckReason reason) {
785785
// For functions, check the parameter and result types.
786786
SubstitutionMap subs = declRef.getSubstitutions();
787787
if (auto function = dyn_cast<AbstractFunctionDecl>(declRef.getDecl())) {
788788
for (auto param : *function->getParameters()) {
789789
Type paramType = param->getInterfaceType().subst(subs);
790790
if (diagnoseNonSendableTypes(
791-
paramType, fromDC, loc, diag::non_sendable_param_type))
791+
paramType, fromDC, loc, diag::non_sendable_param_type,
792+
(unsigned)reason, function->getDescriptiveKind(),
793+
function->getName(), getActorIsolation(function)))
792794
return true;
793795
}
794796

795797
// Check the result type of a function.
796798
if (auto func = dyn_cast<FuncDecl>(function)) {
797799
Type resultType = func->getResultInterfaceType().subst(subs);
798800
if (diagnoseNonSendableTypes(
799-
resultType, fromDC, loc, diag::non_sendable_result_type))
801+
resultType, fromDC, loc, diag::non_sendable_result_type,
802+
(unsigned)reason, func->getDescriptiveKind(), func->getName(),
803+
getActorIsolation(func)))
800804
return true;
801805
}
802806

@@ -811,22 +815,28 @@ bool swift::diagnoseNonSendableTypesInReference(
811815
propertyType, fromDC, loc,
812816
diag::non_sendable_property_type,
813817
var->getDescriptiveKind(), var->getName(),
814-
var->isLocalCapture()))
818+
var->isLocalCapture(),
819+
(unsigned)reason,
820+
getActorIsolation(var)))
815821
return true;
816822
}
817823

818824
if (auto subscript = dyn_cast<SubscriptDecl>(declRef.getDecl())) {
819825
for (auto param : *subscript->getIndices()) {
820826
Type paramType = param->getInterfaceType().subst(subs);
821827
if (diagnoseNonSendableTypes(
822-
paramType, fromDC, loc, diag::non_sendable_param_type))
828+
paramType, fromDC, loc, diag::non_sendable_param_type,
829+
(unsigned)reason, subscript->getDescriptiveKind(),
830+
subscript->getName(), getActorIsolation(subscript)))
823831
return true;
824832
}
825833

826834
// Check the element type of a subscript.
827835
Type resultType = subscript->getElementInterfaceType().subst(subs);
828836
if (diagnoseNonSendableTypes(
829-
resultType, fromDC, loc, diag::non_sendable_result_type))
837+
resultType, fromDC, loc, diag::non_sendable_result_type,
838+
(unsigned)reason, subscript->getDescriptiveKind(),
839+
subscript->getName(), getActorIsolation(subscript)))
830840
return true;
831841

832842
return false;
@@ -1973,12 +1983,11 @@ namespace {
19731983
}
19741984

19751985
if (result == AsyncMarkingResult::FoundAsync) {
1976-
19771986
// Check for non-sendable types.
19781987
bool problemFound =
19791988
diagnoseNonSendableTypesInReference(
19801989
concDeclRef, getDeclContext(), declLoc,
1981-
ConcurrentReferenceKind::SynchronousAsAsyncCall);
1990+
SendableCheckReason::SynchronousAsAsync);
19821991
if (problemFound)
19831992
result = AsyncMarkingResult::NotSendable;
19841993
}
@@ -2104,18 +2113,32 @@ namespace {
21042113
}
21052114

21062115
// Check for sendability of the parameter types.
2107-
for (const auto &param : fnType->getParams()) {
2108-
// FIXME: Dig out the locations of the corresponding arguments.
2116+
auto params = fnType->getParams();
2117+
for (unsigned paramIdx : indices(params)) {
2118+
const auto &param = params[paramIdx];
2119+
2120+
// Dig out the location of the argument.
2121+
SourceLoc argLoc = apply->getLoc();
2122+
if (auto argList = apply->getArgs()) {
2123+
auto arg = argList->get(paramIdx);
2124+
if (arg.getStartLoc().isValid())
2125+
argLoc = arg.getStartLoc();
2126+
}
2127+
21092128
if (diagnoseNonSendableTypes(
2110-
param.getParameterType(), getDeclContext(), apply->getLoc(),
2111-
diag::non_sendable_param_type))
2129+
param.getParameterType(), getDeclContext(), argLoc,
2130+
diag::non_sendable_call_param_type,
2131+
apply->isImplicitlyAsync().hasValue(),
2132+
*unsatisfiedIsolation))
21122133
return true;
21132134
}
21142135

21152136
// Check for sendability of the result type.
21162137
if (diagnoseNonSendableTypes(
21172138
fnType->getResult(), getDeclContext(), apply->getLoc(),
2118-
diag::non_sendable_result_type))
2139+
diag::non_sendable_call_result_type,
2140+
apply->isImplicitlyAsync().hasValue(),
2141+
*unsatisfiedIsolation))
21192142
return true;
21202143

21212144
return false;
@@ -2141,7 +2164,7 @@ namespace {
21412164
if (isCrossActor) {
21422165
return diagnoseNonSendableTypesInReference(
21432166
valueRef, getDeclContext(), loc,
2144-
ConcurrentReferenceKind::CrossActor);
2167+
SendableCheckReason::CrossActor);
21452168
}
21462169

21472170
// Call is implicitly asynchronous.
@@ -2482,7 +2505,7 @@ namespace {
24822505

24832506
return diagnoseNonSendableTypesInReference(
24842507
memberRef, getDeclContext(), memberLoc,
2485-
ConcurrentReferenceKind::CrossActor);
2508+
SendableCheckReason::CrossActor);
24862509
}
24872510

24882511
case ActorIsolationRestriction::ActorSelf: {

lib/Sema/TypeCheckConcurrency.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,21 @@ void checkPropertyWrapperActorIsolation(VarDecl *wrappedVar, Expr *expr);
7070
ClosureActorIsolation
7171
determineClosureActorIsolation(AbstractClosureExpr *closure);
7272

73-
/// Describes the kind of operation that introduced the concurrent refernece.
74-
enum class ConcurrentReferenceKind {
75-
/// A synchronous operation that was "promoted" to an asynchronous call
76-
/// because it was out of the actor's domain.
77-
SynchronousAsAsyncCall,
78-
/// A cross-actor reference.
73+
/// States the reason for checking the Sendability of a given declaration.
74+
enum class SendableCheckReason {
75+
/// A reference to an actor from outside that actor.
7976
CrossActor,
80-
/// A local capture referenced from concurrent code.
81-
LocalCapture,
82-
/// Concurrent function
83-
ConcurrentFunction,
84-
/// Nonisolated declaration.
85-
Nonisolated,
77+
78+
/// A synchronous operation that was "promoted" to an asynchronous one
79+
/// because it was out of the actor's domain.
80+
SynchronousAsAsync,
81+
82+
/// A protocol conformance where the witness/requirement have different
83+
/// actor isolation.
84+
Conformance,
85+
86+
/// The declaration is being exposed to Objective-C.
87+
ObjC,
8688
};
8789

8890
/// The isolation restriction in effect for a given declaration that is
@@ -241,7 +243,7 @@ bool contextRequiresStrictConcurrencyChecking(
241243
/// \returns true if an problem was detected, false otherwise.
242244
bool diagnoseNonSendableTypesInReference(
243245
ConcreteDeclRef declRef, const DeclContext *fromDC, SourceLoc loc,
244-
ConcurrentReferenceKind refKind);
246+
SendableCheckReason refKind);
245247

246248
/// Produce a diagnostic for a missing conformance to Sendable.
247249
void diagnoseMissingSendableConformance(

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ static bool checkObjCActorIsolation(const ValueDecl *VD,
439439
// FIXME: Substitution map?
440440
diagnoseNonSendableTypesInReference(
441441
const_cast<ValueDecl *>(VD), VD->getDeclContext(),
442-
VD->getLoc(), ConcurrentReferenceKind::CrossActor);
442+
VD->getLoc(), SendableCheckReason::ObjC);
443443
return false;
444444
case ActorIsolationRestriction::ActorSelf:
445445
// Actor-isolated functions cannot be @objc.

0 commit comments

Comments
 (0)