Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🍒 [5.6] backtrack on part of SE-327 dealing with default-value exprs #41967

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -4475,10 +4475,6 @@ ERROR(global_actor_from_nonactor_context,none,
"%0 %1 isolated to global actor %2 can not be %select{referenced|mutated|used 'inout'}4"
" from %select{this|a non-isolated}3%select{| synchronous}5 context",
(DescriptiveDeclKind, DeclName, Type, bool, unsigned, bool))
ERROR(global_actor_from_initializing_expr,none,
"expression requiring global actor %0 cannot appear in "
"default-value expression of %1 %2",
(Type, DescriptiveDeclKind, DeclName))
ERROR(actor_isolated_call,none,
"call to %0 function in a synchronous %1 context",
(ActorIsolation, ActorIsolation))
Expand Down
19 changes: 2 additions & 17 deletions lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8667,24 +8667,9 @@ ActorIsolation swift::getActorIsolationOfContext(DeclContext *dc) {
if (auto *vd = dyn_cast_or_null<ValueDecl>(dc->getAsDecl()))
return getActorIsolation(vd);

// In the context of the initializing or default-value expression of a
// stored property, the isolation varies between global and type members:
// - For a static stored property, the isolation matches the VarDecl.
// - For a field of a nominal type, the expression is not isolated.
// Without this distinction, a nominal can have non-async initializers
// with various kinds of isolation, so an impossible constraint can be
// created. See SE-0327 for details.
if (auto *var = dc->getNonLocalVarDecl()) {

// Isolation officially changes, as described above, in Swift 6+
if (dc->getASTContext().isSwiftVersionAtLeast(6) &&
var->isInstanceMember() &&
!var->getAttrs().hasAttribute<LazyAttr>()) {
return ActorIsolation::forUnspecified();
}

if (auto *var = dc->getNonLocalVarDecl())
return getActorIsolation(var);
}


if (auto *closure = dyn_cast<AbstractClosureExpr>(dc)) {
switch (auto isolation = closure->getActorIsolation()) {
Expand Down
61 changes: 2 additions & 59 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1299,57 +1299,6 @@ namespace {
return getDeclContext()->getParentModule();
}

/// In Swift 6, global-actor isolation is not carried-over to the
/// initializing expressions of non-static instance properties.
/// The actual change happens in \c getActorIsolationOfContext ,
/// but this function exists to warn users of Swift 5 about this
/// isolation change, so that they can prepare ahead-of-time.
void warnAboutGlobalActorIsoChangeInSwift6(const ActorIsolation &reqIso,
const Expr *user) {
if (ctx.isSwiftVersionAtLeast(6))
return;

// Check our context stack for a PatternBindingInitializer environment.
DeclContext const* withinDC = nullptr;
for (auto dc = contextStack.rbegin(); dc != contextStack.rend(); dc++) {
if (isa<PatternBindingInitializer>(*dc)) {
withinDC = *dc;
break;
}
}

// Not within a relevant decl context.
if (!withinDC)
return;

// Check if this PatternBindingInitializer's isolation would change
// in Swift 6+
if (auto *var = withinDC->getNonLocalVarDecl()) {
if (var->isInstanceMember() &&
!var->getAttrs().hasAttribute<LazyAttr>()) {
// At this point, we know the isolation will change in Swift 6.
// So, let's check if that change will cause an error.

auto dcIso = getActorIsolationOfContext(
const_cast<DeclContext*>(withinDC));

// If the isolation granted in Swift 5 is for a global actor, and
// the expression requires that global actor's isolation, then it will
// become an error in Swift 6.
if (dcIso.isGlobalActor() && dcIso == reqIso) {
ctx.Diags.diagnose(user->getLoc(),
diag::global_actor_from_initializing_expr,
reqIso.getGlobalActor(),
var->getDescriptiveKind(), var->getName())
.highlight(user->getSourceRange())
// make it a warning and attach the "this will become an error..."
// to the message. The error in Swift 6 will not be this diagnostic.
.warnUntilSwiftVersion(6);
}
}
}
}

/// Determine whether code in the given use context might execute
/// concurrently with code in the definition context.
bool mayExecuteConcurrentlyWith(
Expand Down Expand Up @@ -2192,12 +2141,8 @@ namespace {
// we are within that global actor already.
Optional<ActorIsolation> unsatisfiedIsolation;
if (Type globalActor = fnType->getGlobalActor()) {
if (getContextIsolation().isGlobalActor() &&
getContextIsolation().getGlobalActor()->isEqual(globalActor)) {
warnAboutGlobalActorIsoChangeInSwift6(
ActorIsolation::forGlobalActor(globalActor, false),
apply);
} else {
if (!(getContextIsolation().isGlobalActor() &&
getContextIsolation().getGlobalActor()->isEqual(globalActor))) {
unsatisfiedIsolation = ActorIsolation::forGlobalActor(
globalActor, /*unsafe=*/false);
}
Expand Down Expand Up @@ -2333,8 +2278,6 @@ namespace {
auto contextIsolation = getInnermostIsolatedContext(declContext);
if (contextIsolation.isGlobalActor() &&
contextIsolation.getGlobalActor()->isEqual(globalActor)) {

warnAboutGlobalActorIsoChangeInSwift6(contextIsolation, context);
return false;
}

Expand Down
6 changes: 3 additions & 3 deletions test/Concurrency/global_actor_inference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -587,9 +587,9 @@ func replacesDynamicOnMainActor() {
// ----------------------------------------------------------------------

class Cutter {
@MainActor var x = useFooInADefer() // expected-warning {{expression requiring global actor 'MainActor' cannot appear in default-value expression of property 'x'; this is an error in Swift 6}}
@MainActor var x = useFooInADefer()
@MainActor var y = { () -> Bool in
var z = statefulThingy // expected-warning {{expression requiring global actor 'MainActor' cannot appear in default-value expression of property 'y'; this is an error in Swift 6}}
var z = statefulThingy
return z
}()
}
Expand All @@ -601,7 +601,7 @@ class Butter {
nonisolated let b = statefulThingy // expected-error {{var 'statefulThingy' isolated to global actor 'MainActor' can not be referenced from a non-isolated synchronous context}}

var c: Int = {
return getGlobal7() // expected-warning {{expression requiring global actor 'SomeGlobalActor' cannot appear in default-value expression of property 'c'; this is an error in Swift 6}}
return getGlobal7()
}()

lazy var d: Int = getGlobal7()
Expand Down
20 changes: 12 additions & 8 deletions test/Concurrency/property_initializers_swift6.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@

// REQUIRES: asserts

@MainActor
func mainActorFn() -> Int { return 0 } // expected-note 2 {{calls to global function 'mainActorFn()' from outside of its actor context are implicitly asynchronous}}
@globalActor
actor GlobalActor {
static let shared = GlobalActor()
}

@GlobalActor
func globalActorFn() -> Int { return 0 } // expected-note {{calls to global function 'globalActorFn()' from outside of its actor context are implicitly asynchronous}}

@MainActor
@GlobalActor
class C {
var x: Int = mainActorFn() // expected-error {{call to main actor-isolated global function 'mainActorFn()' in a synchronous nonisolated context}}
var x: Int = globalActorFn()

lazy var y: Int = mainActorFn()
lazy var y: Int = globalActorFn()

static var z: Int = mainActorFn()
static var z: Int = globalActorFn()
}

@MainActor
var x: Int = mainActorFn() // expected-error {{call to main actor-isolated global function 'mainActorFn()' in a synchronous nonisolated context}}
var x: Int = globalActorFn() // expected-error {{call to global actor 'GlobalActor'-isolated global function 'globalActorFn()' in a synchronous nonisolated context}}
17 changes: 17 additions & 0 deletions validation-test/Sema/SwiftUI/radar88971160.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// RUN: %target-typecheck-verify-swift -target %target-cpu-apple-macosx10.15 -swift-version 5
// REQUIRES: objc_interop
// REQUIRES: OS=macosx

import SwiftUI

@MainActor
class ContentState: ObservableObject { }

struct SomeView: View {
@StateObject private var contentState = ContentState()

var body: some View {
Text("Hello, world!")
}
}