Skip to content
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
2 changes: 1 addition & 1 deletion include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ namespace swift {
bool UseMalloc = false;

/// Specifies how strict concurrency checking will be.
StrictConcurrency StrictConcurrencyLevel = StrictConcurrency::Targeted;
StrictConcurrency StrictConcurrencyLevel = StrictConcurrency::Minimal;

/// Enable experimental concurrency model.
bool EnableExperimentalConcurrency = false;
Expand Down
10 changes: 9 additions & 1 deletion include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ class TypeVariableType::Implementation {
/// expression.
bool isCodeCompletionToken() const;

/// Determine whether this type variable represents an opened opaque type.
bool isOpaqueType() const;

/// Retrieve the representative of the equivalence class to which this
/// type variable belongs.
///
Expand Down Expand Up @@ -977,6 +980,11 @@ struct AppliedBuilderTransform {
/// converted. Opaque types should be unopened.
Type bodyResultType;

/// If transform is applied to a closure, this type represents
/// contextual type the closure is converted type (e.g. a parameter
/// type or or pattern type).
Type contextualType;

/// The version of the original body with result builder applied
/// as AST transformation.
NullablePtr<BraceStmt> transformedBody;
Expand Down Expand Up @@ -5662,7 +5670,7 @@ class ConstraintSystem {
Optional<TypeMatchResult>
matchResultBuilder(AnyFunctionRef fn, Type builderType, Type bodyResultType,
ConstraintKind bodyResultConstraintKind,
ConstraintLocatorBuilder locator);
Type contextualType, ConstraintLocatorBuilder locator);

/// Matches a wrapped or projected value parameter type to its backing
/// property wrapper type by applying the property wrapper.
Expand Down
2 changes: 1 addition & 1 deletion include/swift/Threading/Impl/Darwin.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ inline void once_impl(once_t &predicate, void (*fn)(void *), void *context) {
// On Darwin, we want to use the reserved keys
#define SWIFT_THREADING_USE_RESERVED_TLS_KEYS 1

#if !(SWIFT_THREADING_IS_COMPATIBILITY_LIBRARY && __ARM_ARCH_7K__) && __has_include(<pthread/tsd_private.h>)
#if !(SWIFT_THREADING_IS_COMPATIBILITY_LIBRARY && (__ARM_ARCH_7K__ || __ARM64_ARCH_8_32__)) && __has_include(<pthread/tsd_private.h>)
} // namespace threading_impl
} // namespace swift

Expand Down
4 changes: 2 additions & 2 deletions lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -788,8 +788,8 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
} else if (Args.hasArg(OPT_warn_concurrency)) {
Opts.StrictConcurrencyLevel = StrictConcurrency::Complete;
} else {
// Default to "limited" checking in Swift 5.x.
Opts.StrictConcurrencyLevel = StrictConcurrency::Targeted;
// Default to minimal checking in Swift 5.x.
Opts.StrictConcurrencyLevel = StrictConcurrency::Minimal;
}

Opts.WarnImplicitOverrides =
Expand Down
30 changes: 16 additions & 14 deletions lib/SILGen/SILGenDistributed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,19 @@ static SILValue emitActorPropertyReference(
/// \param value the value to use when initializing the property.
static void initializeProperty(SILGenFunction &SGF, SILLocation loc,
SILValue actorSelf,
VarDecl* prop, SILValue value) {
VarDecl* prop, SILValue value,
IsTake_t isTake) {
Type formalType = SGF.F.mapTypeIntoContext(prop->getInterfaceType());
SILType loweredType = SGF.getLoweredType(formalType);

auto fieldAddr = emitActorPropertyReference(SGF, loc, actorSelf, prop);

if (loweredType.isAddressOnly(SGF.F)) {
SGF.B.createCopyAddr(loc, value, fieldAddr, IsNotTake, IsInitialization);
SGF.B.createCopyAddr(loc, value, fieldAddr, isTake, IsInitialization);
} else {
if (value->getType().isAddress()) {
SGF.emitSemanticLoadInto(loc, value, SGF.F.getTypeLowering(value->getType()),
fieldAddr, SGF.getTypeLowering(loweredType), IsTake, IsInitialization);
fieldAddr, SGF.getTypeLowering(loweredType), isTake, IsInitialization);
} else {
value = SGF.B.emitCopyValueOperation(loc, value);
SGF.B.emitStoreValueOperation(
Expand Down Expand Up @@ -152,10 +153,10 @@ static SILArgument *findFirstDistributedActorSystemArg(SILFunction &F) {
/// For the initialization of a local distributed actor instance, emits code to
/// initialize the instance's stored property corresponding to the system.
static void emitActorSystemInit(SILGenFunction &SGF,
ConstructorDecl *ctor,
SILLocation loc,
ManagedValue actorSelf,
SILValue systemValue) {
ConstructorDecl *ctor,
SILLocation loc,
ManagedValue actorSelf,
SILValue systemValue) {
assert(ctor->isImplicit() && "unexpected explicit dist actor init");
assert(ctor->isDesignatedInit());

Expand All @@ -166,9 +167,8 @@ static void emitActorSystemInit(SILGenFunction &SGF,
// exactly one ActorSystem-conforming argument to the constructor,
// so we grab the first one from the params.
VarDecl *var = classDecl->getDistributedActorSystemProperty();
assert(var);

initializeProperty(SGF, loc, actorSelf.getValue(), var, systemValue);

initializeProperty(SGF, loc, actorSelf.getValue(), var, systemValue, IsNotTake);
}

/// Emits the distributed actor's identity (`id`) initialization.
Expand Down Expand Up @@ -209,7 +209,7 @@ void SILGenFunction::emitDistActorIdentityInit(ConstructorDecl *ctor,
{ temp, selfMetatypeValue });

// --- initialize the property.
initializeProperty(*this, loc, borrowedSelfArg, var, temp);
initializeProperty(*this, loc, borrowedSelfArg, var, temp, IsTake);
}

// TODO(distributed): rename to DistributedActorID
Expand Down Expand Up @@ -443,14 +443,16 @@ void SILGenFunction::emitDistributedActorFactory(FuncDecl *fd) { // TODO(distrib
loc.markAutoGenerated();
auto *dc = fd->getDeclContext();
auto classDecl = dc->getSelfClassDecl();

initializeProperty(*this, loc, remote,
classDecl->getDistributedActorIDProperty(),
idArg);
idArg,
IsNotTake);

initializeProperty(*this, loc, remote,
classDecl->getDistributedActorSystemProperty(),
actorSystemArg);
actorSystemArg,
IsNotTake);

// ==== Branch to return the fully initialized remote instance
B.createBranch(loc, returnBB, {remote});
Expand Down
3 changes: 3 additions & 0 deletions lib/Sema/BuilderTransform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2311,6 +2311,7 @@ Optional<BraceStmt *> TypeChecker::applyResultBuilderBodyTransform(

if (auto result = cs.matchResultBuilder(
func, builderType, resultContextType, resultConstraintKind,
/*contextualType=*/Type(),
cs.getConstraintLocator(func->getBody()))) {
if (result->isFailure())
return nullptr;
Expand Down Expand Up @@ -2398,6 +2399,7 @@ Optional<ConstraintSystem::TypeMatchResult>
ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
Type bodyResultType,
ConstraintKind bodyResultConstraintKind,
Type contextualType,
ConstraintLocatorBuilder locator) {
builderType = simplifyType(builderType);
auto builder = builderType->getAnyNominal();
Expand Down Expand Up @@ -2522,6 +2524,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,

transformInfo.builderType = builderType;
transformInfo.bodyResultType = bodyResultType;
transformInfo.contextualType = contextualType;
transformInfo.transformedBody = transformedBody->second;

// Record the transformation.
Expand Down
55 changes: 55 additions & 0 deletions lib/Sema/CSBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,61 @@ bool BindingSet::favoredOverConjunction(Constraint *conjunction) const {
if (forClosureResult() || forGenericParameter())
return false;
}

auto *locator = conjunction->getLocator();
if (locator->directlyAt<ClosureExpr>()) {
auto *closure = castToExpr<ClosureExpr>(locator->getAnchor());

if (auto transform = CS.getAppliedResultBuilderTransform(closure)) {
// Conjunctions that represent closures with result builder transformed
// bodies could be attempted right after their resolution if they meet
// all of the following criteria:
//
// - Builder type doesn't have any unresolved generic parameters;
// - Closure doesn't have any parameters;
// - The contextual result type is either concrete or opaque type.
auto contextualType = transform->contextualType;
if (!(contextualType && contextualType->is<FunctionType>()))
return true;

auto *contextualFnType =
CS.simplifyType(contextualType)->castTo<FunctionType>();
{
auto resultType = contextualFnType->getResult();
if (resultType->hasTypeVariable()) {
auto *typeVar = resultType->getAs<TypeVariableType>();
// If contextual result type is represented by an opaque type,
// it's a strong indication that body is self-contained, otherwise
// closure might rely on external types flowing into the body for
// disambiguation of `build{Partial}Block` or `buildFinalResult`
// calls.
if (!(typeVar && typeVar->getImpl().isOpaqueType()))
return true;
}
}

// If some of the closure parameters are unresolved, the conjunction
// has to be delayed to give them a chance to be inferred.
if (llvm::any_of(contextualFnType->getParams(), [](const auto &param) {
return param.getPlainType()->hasTypeVariable();
}))
return true;

// Check whether conjunction has any unresolved type variables
// besides the variable that represents the closure.
//
// Conjunction could refer to declarations from outer context
// (i.e. a variable declared in the outer closure) or generic
// parameters of the builder type), if any of such references
// are not yet inferred the conjunction has to be delayed.
auto *closureType = CS.getType(closure)->castTo<TypeVariableType>();
return llvm::any_of(
conjunction->getTypeVariables(), [&](TypeVariableType *typeVar) {
return !(typeVar == closureType || CS.getFixedType(typeVar));
});
}
}

return true;
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10964,7 +10964,7 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
if (resultBuilderType) {
if (auto result = matchResultBuilder(
closure, resultBuilderType, closureType->getResult(),
ConstraintKind::Conversion, locator)) {
ConstraintKind::Conversion, contextualType, locator)) {
return result->isSuccess();
}
}
Expand Down
28 changes: 6 additions & 22 deletions lib/Sema/CSSyntacticElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1891,7 +1891,7 @@ class ResultBuilderRewriter : public SyntacticElementSolutionApplication {
NullablePtr<Stmt> transformIf(IfStmt *ifStmt, TypeJoinExpr *join,
unsigned index) {
// FIXME: Turn this into a condition once warning is an error.
(void)diagnoseMissingBuildWithAvailability(ifStmt);
(void)diagnoseMissingBuildWithAvailability(ifStmt, join);

auto *joinVar = join->getVar();

Expand Down Expand Up @@ -1993,7 +1993,8 @@ class ResultBuilderRewriter : public SyntacticElementSolutionApplication {
/// have had the chance to adopt buildLimitedAvailability(), we'll upgrade
/// this warning to an error.
LLVM_NODISCARD
bool diagnoseMissingBuildWithAvailability(IfStmt *ifStmt) {
bool diagnoseMissingBuildWithAvailability(IfStmt *ifStmt,
TypeJoinExpr *join) {
auto findAvailabilityCondition =
[](StmtCondition stmtCond) -> const StmtConditionElement * {
for (const auto &cond : stmtCond) {
Expand All @@ -2017,27 +2018,10 @@ class ResultBuilderRewriter : public SyntacticElementSolutionApplication {
return false;

SourceLoc loc = availabilityCond->getStartLoc();
Type bodyType;
if (availabilityCond->getAvailability()->isUnavailability()) {
BraceStmt *elseBody = nullptr;
// For #unavailable, we need to check the "else".
if (auto *innerIf = getAsStmt<IfStmt>(ifStmt->getElseStmt())) {
elseBody = castToStmt<BraceStmt>(innerIf->getThenStmt());
} else {
elseBody = castToStmt<BraceStmt>(ifStmt->getElseStmt());
}

Type elseBodyType =
solution.simplifyType(solution.getType(elseBody->getLastElement()));
bodyType = elseBodyType;
} else {
auto *thenBody = castToStmt<BraceStmt>(ifStmt->getThenStmt());
Type thenBodyType =
solution.simplifyType(solution.getType(thenBody->getLastElement()));
bodyType = thenBodyType;
}

auto builderType = solution.simplifyType(Transform.builderType);
// Since all of the branches of `if` statement have to join into the same
// type we can just use the type of the join variable here.
Type bodyType = solution.getResolvedType(join->getVar());

return bodyType.findIf([&](Type type) {
auto nominal = type->getAnyNominal();
Expand Down
16 changes: 16 additions & 0 deletions lib/Sema/TypeCheckConstraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ bool TypeVariableType::Implementation::isCodeCompletionToken() const {
return locator && locator->directlyAt<CodeCompletionExpr>();
}

bool TypeVariableType::Implementation::isOpaqueType() const {
if (!locator)
return false;

auto GP = locator->getLastElementAs<LocatorPathElt::GenericParameter>();
if (!GP)
return false;

if (auto *GPT = GP->getType()->getAs<GenericTypeParamType>()) {
auto *decl = GPT->getDecl();
return decl && decl->isOpaqueType();
}

return false;
}

void *operator new(size_t bytes, ConstraintSystem& cs,
size_t alignment) {
return cs.getAllocator().Allocate(bytes, alignment);
Expand Down
1 change: 1 addition & 0 deletions test/Concurrency/strict_concurrency_minimal.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %target-typecheck-verify-swift -strict-concurrency=minimal
// RUN: %target-typecheck-verify-swift
// REQUIRES: concurrency

class C1 { }
Expand Down
7 changes: 5 additions & 2 deletions test/Constraints/result_builder_availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ tuplify(true) { cond in
globalFuncAvailableOn10_52()
} else if false {
globalFuncAvailableOn10_52()
} else {
globalFuncAvailableOn10_52()
}
}
}
Expand Down Expand Up @@ -166,6 +164,11 @@ tuplifyWithAvailabilityErasure(true) { cond in
} else {
globalFuncAvailableOn10_52()
}

// https://github.com/apple/swift/issues/63764
if #unavailable(OSX 10.52) {
cond // Ok
}
}

// rdar://97533700 – Make sure we can prefer an unavailable buildPartialBlock if
Expand Down
Loading