Skip to content

Commit 6d75fac

Browse files
authored
Merge pull request #61862 from kavon/isolated-param-holes-100039019
Fix inconsistencies with `isolated` parameters.
2 parents 454019a + 3b3bdaf commit 6d75fac

File tree

6 files changed

+288
-12
lines changed

6 files changed

+288
-12
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4832,6 +4832,22 @@ NOTE(protocol_isolated_to_global_actor_here,none,
48324832

48334833
ERROR(isolated_parameter_not_actor,none,
48344834
"'isolated' parameter has non-actor type %0", (Type))
4835+
ERROR(isolated_parameter_duplicate,none,
4836+
"cannot have more than one 'isolated' parameter", ())
4837+
ERROR(isolated_parameter_duplicate_type,none,
4838+
"function type cannot have more than one 'isolated' parameter", ())
4839+
NOTE(isolated_parameter_previous_note,none,
4840+
"previous 'isolated' parameter %0", (DeclName))
4841+
ERROR(isolated_parameter_combined_global_actor_attr,none,
4842+
"%0 with 'isolated' parameter cannot have a global actor",
4843+
(DescriptiveDeclKind))
4844+
ERROR(isolated_parameter_closure_combined_global_actor_attr,none,
4845+
"closure with 'isolated' parameter %0 cannot have a global actor", (DeclName))
4846+
ERROR(isolated_parameter_global_actor_type,none,
4847+
"function type cannot have global actor and 'isolated' parameter", ())
4848+
ERROR(isolated_parameter_combined_nonisolated,none,
4849+
"%0 with 'isolated' parameter cannot be 'nonisolated'",
4850+
(DescriptiveDeclKind))
48354851

48364852
WARNING(non_sendable_param_type,none,
48374853
"non-sendable type %0 %select{passed in call to %4 %2 %3|"

lib/Sema/TypeCheckAttr.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6960,8 +6960,24 @@ class ClosureAttributeChecker
69606960
// Check whether this custom attribute is the global actor attribute.
69616961
auto globalActorAttr = evaluateOrDefault(
69626962
ctx.evaluator, GlobalActorAttributeRequest{closure}, None);
6963-
if (globalActorAttr && globalActorAttr->first == attr)
6964-
return;
6963+
6964+
if (globalActorAttr && globalActorAttr->first == attr) {
6965+
// if there is an `isolated` parameter, then this global-actor attribute
6966+
// is invalid.
6967+
for (auto param : *closure->getParameters()) {
6968+
if (param->isIsolated()) {
6969+
param->diagnose(
6970+
diag::isolated_parameter_closure_combined_global_actor_attr,
6971+
param->getName())
6972+
.fixItRemove(attr->getRangeWithAt())
6973+
.warnUntilSwiftVersion(6);
6974+
attr->setInvalid();
6975+
break; // don't need to complain about this more than once.
6976+
}
6977+
}
6978+
6979+
return; // it's OK
6980+
}
69656981

69666982
// Otherwise, it's an error.
69676983
std::string typeName;

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,6 +3099,7 @@ void swift::checkFunctionActorIsolation(AbstractFunctionDecl *decl) {
30993099
if (auto superInit = ctor->getSuperInitCall())
31003100
superInit->walk(checker);
31013101
}
3102+
31023103
if (decl->getAttrs().hasAttribute<DistributedActorAttr>()) {
31033104
if (auto func = dyn_cast<FuncDecl>(decl)) {
31043105
checkDistributedFunction(func);
@@ -3708,6 +3709,39 @@ static Optional<unsigned> getIsolatedParamIndex(ValueDecl *value) {
37083709
return None;
37093710
}
37103711

3712+
/// Verifies rules about `isolated` parameters for the given decl. There is more
3713+
/// checking about these in TypeChecker::checkParameterList.
3714+
///
3715+
/// This function is focused on rules that apply when it's a declaration with
3716+
/// an isolated parameter, rather than some generic parameter list in a
3717+
/// DeclContext.
3718+
///
3719+
/// This function assumes the value already contains an isolated parameter.
3720+
static void checkDeclWithIsolatedParameter(ValueDecl *value) {
3721+
// assume there is an isolated parameter.
3722+
assert(getIsolatedParamIndex(value));
3723+
3724+
// Suggest removing global-actor attributes written on it, as its ignored.
3725+
if (auto attr = value->getGlobalActorAttr()) {
3726+
if (!attr->first->isImplicit()) {
3727+
value->diagnose(diag::isolated_parameter_combined_global_actor_attr,
3728+
value->getDescriptiveKind())
3729+
.fixItRemove(attr->first->getRangeWithAt())
3730+
.warnUntilSwiftVersion(6);
3731+
}
3732+
}
3733+
3734+
// Suggest removing `nonisolated` as it is also ignored
3735+
if (auto attr = value->getAttrs().getAttribute<NonisolatedAttr>()) {
3736+
if (!attr->isImplicit()) {
3737+
value->diagnose(diag::isolated_parameter_combined_nonisolated,
3738+
value->getDescriptiveKind())
3739+
.fixItRemove(attr->getRangeWithAt())
3740+
.warnUntilSwiftVersion(6);
3741+
}
3742+
}
3743+
}
3744+
37113745
ActorIsolation ActorIsolationRequest::evaluate(
37123746
Evaluator &evaluator, ValueDecl *value) const {
37133747
// If this declaration has actor-isolated "self", it's isolated to that
@@ -3721,6 +3755,8 @@ ActorIsolation ActorIsolationRequest::evaluate(
37213755
// If this declaration has an isolated parameter, it's isolated to that
37223756
// parameter.
37233757
if (auto paramIdx = getIsolatedParamIndex(value)) {
3758+
checkDeclWithIsolatedParameter(value);
3759+
37243760
// FIXME: This doesn't allow us to find an Actor or DistributedActor
37253761
// bound on the parameter type effectively.
37263762
auto param = getParameterList(value)->get(*paramIdx);

lib/Sema/TypeCheckDeclPrimary.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3480,6 +3480,8 @@ void TypeChecker::typeCheckDecl(Decl *D, bool LeaveClosureBodiesUnchecked) {
34803480

34813481
void TypeChecker::checkParameterList(ParameterList *params,
34823482
DeclContext *owner) {
3483+
Optional<ParamDecl*> firstIsolatedParam;
3484+
bool diagnosedDuplicateIsolatedParam = false;
34833485
for (auto param: *params) {
34843486
checkDeclAttributes(param);
34853487

@@ -3496,6 +3498,32 @@ void TypeChecker::checkParameterList(ParameterList *params,
34963498
}
34973499
}
34983500

3501+
// check for well-formed isolated parameters.
3502+
if (!diagnosedDuplicateIsolatedParam) {
3503+
if (param->isIsolated()) {
3504+
if (firstIsolatedParam) {
3505+
// cannot have more than one isolated parameter (SE-0313)
3506+
param->diagnose(diag::isolated_parameter_duplicate)
3507+
.highlight(param->getSourceRange())
3508+
.warnUntilSwiftVersion(6);
3509+
// I'd love to describe the context in which there is an isolated parameter,
3510+
// we had a DescriptiveDeclContextKind, but that only
3511+
// exists for Decls.
3512+
3513+
auto prevIso = firstIsolatedParam.value();
3514+
prevIso
3515+
->diagnose(diag::isolated_parameter_previous_note,
3516+
prevIso->getName())
3517+
.highlight(prevIso->getSourceRange());
3518+
3519+
// no need to complain about any further `isolated` params
3520+
diagnosedDuplicateIsolatedParam = true;
3521+
} else {
3522+
firstIsolatedParam = param; // save first one we've seen.
3523+
}
3524+
}
3525+
}
3526+
34993527
// Opaque types cannot occur in parameter position.
35003528
Type interfaceType = param->getInterfaceType();
35013529
if (interfaceType->hasTypeParameter()) {

lib/Sema/TypeCheckType.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2516,6 +2516,20 @@ TypeResolver::resolveOpenedExistentialArchetype(
25162516
return archetypeType;
25172517
}
25182518

2519+
/// \returns true iff the # of isolated params is > \c lowerBound
2520+
static bool hasMoreIsolatedParamsThan(FunctionTypeRepr* fnTy, unsigned lowerBound) {
2521+
unsigned count = 0;
2522+
for (auto arg : fnTy->getArgsTypeRepr()->getElements()) {
2523+
if (isa<IsolatedTypeRepr>(arg.Type))
2524+
count += 1;
2525+
2526+
if (count > lowerBound)
2527+
break;
2528+
}
2529+
2530+
return count > lowerBound;
2531+
}
2532+
25192533
NeverNullType
25202534
TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
25212535
TypeResolutionOptions options) {
@@ -2545,7 +2559,7 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
25452559
// Resolve global actor.
25462560
CustomAttr *globalActorAttr = nullptr;
25472561
Type globalActor;
2548-
if (isa<FunctionTypeRepr>(repr)) {
2562+
if (auto fnTy = dyn_cast<FunctionTypeRepr>(repr)) {
25492563
auto foundGlobalActor = checkGlobalActorAttributes(
25502564
repr->getLoc(), getDeclContext(),
25512565
std::vector<CustomAttr *>(
@@ -2555,6 +2569,15 @@ TypeResolver::resolveAttributedType(TypeAttributes &attrs, TypeRepr *repr,
25552569
globalActor = resolveType(globalActorAttr->getTypeRepr(), options);
25562570
if (globalActor->hasError())
25572571
globalActor = Type();
2572+
2573+
// make sure there is no `isolated` parameter in the type
2574+
if (globalActorAttr->isValid()) {
2575+
if (globalActor && hasMoreIsolatedParamsThan(fnTy, 0)) {
2576+
diagnose(repr->getLoc(), diag::isolated_parameter_global_actor_type)
2577+
.warnUntilSwiftVersion(6);
2578+
globalActorAttr->setInvalid();
2579+
}
2580+
}
25582581
}
25592582
}
25602583

@@ -3298,6 +3321,17 @@ NeverNullType TypeResolver::resolveASTFunctionType(
32983321
if (auto *genericParams = repr->getGenericParams())
32993322
saveGenericParams.emplace(this->genericParams, genericParams);
33003323

3324+
// can't have more than 1 isolated parameter.
3325+
if (!repr->isWarnedAbout() && hasMoreIsolatedParamsThan(repr, 1)) {
3326+
diagnose(repr->getLoc(), diag::isolated_parameter_duplicate_type)
3327+
.warnUntilSwiftVersion(6);
3328+
3329+
if (getASTContext().LangOpts.isSwiftVersionAtLeast(6))
3330+
return ErrorType::get(getASTContext());
3331+
else
3332+
repr->setWarned();
3333+
}
3334+
33013335
// Diagnose a couple of things that we can parse in SIL mode but we don't
33023336
// allow in formal types.
33033337
if (auto patternParams = repr->getPatternGenericParams()) {

0 commit comments

Comments
 (0)