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
3 changes: 0 additions & 3 deletions include/swift/AST/ActorIsolation.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ class AbstractClosureExpr;
/// to avoid having to include Types.h.
bool areTypesEqual(Type type1, Type type2);

/// Determine whether the given type is suitable as a concurrent value type.
bool isSendableType(ModuleDecl *module, Type type);

/// Determines if the 'let' can be read from anywhere within the given module,
/// regardless of the isolation or async-ness of the context in which
/// the var is read.
Expand Down
19 changes: 19 additions & 0 deletions include/swift/AST/TypeCheckRequests.h
Original file line number Diff line number Diff line change
Expand Up @@ -2829,6 +2829,25 @@ class TypeWitnessRequest
void cacheResult(TypeWitnessAndDecl value) const;
};

class ReferencedAssociatedTypesRequest
: public SimpleRequest<ReferencedAssociatedTypesRequest,
TinyPtrVector<AssociatedTypeDecl *>(ValueDecl *),
RequestFlags::Cached> {
public:
using SimpleRequest::SimpleRequest;

private:
friend SimpleRequest;

// Evaluation.
TinyPtrVector<AssociatedTypeDecl *>
evaluate(Evaluator &evaluator, ValueDecl *req) const;

public:
// Caching.
bool isCached() const { return true; }
};

class ValueWitnessRequest
: public SimpleRequest<ValueWitnessRequest,
Witness(NormalProtocolConformance *, ValueDecl *),
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/TypeCheckerTypeIDZone.def
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,9 @@ SWIFT_REQUEST(TypeChecker, AssociatedConformanceRequest,
ProtocolConformanceRef(NormalProtocolConformance *,
Type, ProtocolDecl *, unsigned),
SeparatelyCached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ReferencedAssociatedTypesRequest,
TinyPtrVector<AssociatedTypeDecl *>(ValueDecl *),
Cached, NoLocationInfo)
SWIFT_REQUEST(TypeChecker, ValueWitnessRequest,
Witness(NormalProtocolConformance *, ValueDecl *),
SeparatelyCached, NoLocationInfo)
Expand Down
8 changes: 3 additions & 5 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -925,11 +925,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
/// Determines whether this type is an any actor type.
bool isAnyActorType();

/// Returns true if this type is a Sendable type.
bool isSendableType(DeclContext *declContext);

/// Returns true if this type is a Sendable type.
bool isSendableType(ModuleDecl *parentModule);
/// Returns true if this type conforms to Sendable, or if its a function type
/// that is @Sendable.
bool isSendableType();

/// Determines whether this type conforms or inherits (if it's a protocol
/// type) from `DistributedActor`.
Expand Down
3 changes: 0 additions & 3 deletions include/swift/SIL/SILType.h
Original file line number Diff line number Diff line change
Expand Up @@ -891,9 +891,6 @@ class SILType {
/// Returns true if this function conforms to the Sendable protocol.
bool isSendable(SILFunction *fn) const;

ProtocolConformanceRef conformsToProtocol(SILFunction *fn,
ProtocolDecl *protocol) const;

/// False if SILValues of this type cannot be used outside the scope of their
/// lifetime dependence.
bool isEscapable() const;
Expand Down
26 changes: 21 additions & 5 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,12 +580,28 @@ bool TypeBase::isAnyActorType() {
return false;
}

bool TypeBase::isSendableType(DeclContext *ctx) {
return isSendableType(ctx->getParentModule());
}
bool TypeBase::isSendableType() {
auto proto = getASTContext().getProtocol(KnownProtocolKind::Sendable);
if (!proto)
return true;

// First check if we have a function type. If we do, check if it is
// Sendable. We do this since functions cannot conform to protocols.
if (auto *fas = getAs<SILFunctionType>())
return fas->isSendable();
if (auto *fas = getAs<AnyFunctionType>())
return fas->isSendable();

bool TypeBase::isSendableType(ModuleDecl *parentModule) {
return ::isSendableType(parentModule, Type(this));
auto conformance = proto->getParentModule()->checkConformance(this, proto);
if (conformance.isInvalid())
return false;

// Look for missing Sendable conformances.
return !conformance.forEachMissingConformance(
[](BuiltinProtocolConformance *missing) {
return missing->getProtocol()->isSpecificProtocol(
KnownProtocolKind::Sendable);
});
}

bool TypeBase::isDistributedActor() {
Expand Down
9 changes: 5 additions & 4 deletions lib/IDE/CompletionLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,8 @@ Type CompletionLookup::getTypeOfMember(const ValueDecl *VD,
// τ_1_0(U) => U }
auto subs = keyPathInfo.baseType->getMemberSubstitutions(SD);

// FIXME: The below should use substitution map substitution.

// If the keyPath result type has type parameters, that might affect the
// subscript result type.
auto keyPathResultTy =
Expand Down Expand Up @@ -800,21 +802,20 @@ void CompletionLookup::analyzeActorIsolation(
// If the reference is 'async', all types must be 'Sendable'.
if (Ctx.LangOpts.StrictConcurrencyLevel >= StrictConcurrency::Complete &&
implicitlyAsync && T) {
auto *M = CurrDeclContext->getParentModule();
if (isa<VarDecl>(VD)) {
if (!isSendableType(M, T)) {
if (!T->isSendableType()) {
NotRecommended = ContextualNotRecommendedReason::CrossActorReference;
}
} else {
assert(isa<FuncDecl>(VD) || isa<SubscriptDecl>(VD));
// Check if the result and the param types are all 'Sendable'.
auto *AFT = T->castTo<AnyFunctionType>();
if (!isSendableType(M, AFT->getResult())) {
if (!AFT->getResult()->isSendableType()) {
NotRecommended = ContextualNotRecommendedReason::CrossActorReference;
} else {
for (auto &param : AFT->getParams()) {
Type paramType = param.getPlainType();
if (!isSendableType(M, paramType)) {
if (!paramType->isSendableType()) {
NotRecommended =
ContextualNotRecommendedReason::CrossActorReference;
break;
Expand Down
4 changes: 3 additions & 1 deletion lib/IDE/IDETypeChecking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@ swift::getTopLevelDeclsForDisplay(ModuleDecl *M,
!accessScope.isPublic() && !accessScope.isPackage())
continue;

(void)swift::isSendableType(M, NTD->getDeclaredInterfaceType());
auto proto = M->getASTContext().getProtocol(KnownProtocolKind::Sendable);
if (proto)
(void) M->lookupConformance(NTD->getDeclaredInterfaceType(), proto);
}
}

Expand Down
7 changes: 1 addition & 6 deletions lib/SIL/IR/SILType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1250,11 +1250,6 @@ SILType SILType::removingMoveOnlyWrapperToBoxedType(const SILFunction *fn) {
return SILType::getPrimitiveObjectType(newBoxType);
}

ProtocolConformanceRef
SILType::conformsToProtocol(SILFunction *fn, ProtocolDecl *protocol) const {
return fn->getParentModule()->checkConformance(getASTType(), protocol);
}

bool SILType::isSendable(SILFunction *fn) const {
return getASTType()->isSendableType(fn->getParentModule());
return getASTType()->isSendableType();
}
11 changes: 5 additions & 6 deletions lib/SILOptimizer/Mandatory/FlowIsolation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ static bool accessIsConcurrencySafe(ModuleDecl *module,

// must be accessible from nonisolated and Sendable
return isLetAccessibleAnywhere(module, var)
&& isSendableType(module, var->getTypeInContext());
&& var->getTypeInContext()->isSendableType();
}

/// \returns true iff the ref_element_addr instruction is only used
Expand All @@ -517,11 +517,10 @@ static bool onlyDeinitAccess(RefElementAddrInst *inst) {
/// diagnostic if it is not Sendable. The diagnostic assumes that the access
/// is happening in a deinit that uses flow-isolation.
/// \returns true iff a diagnostic was emitted for this reference.
static bool diagnoseNonSendableFromDeinit(ModuleDecl *module,
RefElementAddrInst *inst) {
static bool diagnoseNonSendableFromDeinit(RefElementAddrInst *inst) {
VarDecl *var = inst->getField();
Type ty = var->getTypeInContext();
DeclContext* dc = inst->getFunction()->getDeclContext();
DeclContext *dc = inst->getFunction()->getDeclContext();

// FIXME: we should emit diagnostics in other modes using:
//
Expand All @@ -534,7 +533,7 @@ static bool diagnoseNonSendableFromDeinit(ModuleDecl *module,
!= StrictConcurrency::Complete)
return false;

if (isSendableType(module, ty))
if (ty->isSendableType())
return false;

auto &diag = var->getASTContext().Diags;
Expand Down Expand Up @@ -657,7 +656,7 @@ void AnalysisInfo::analyze(const SILArgument *selfParam) {
continue;

// emit a diagnostic and skip if it's non-sendable in a deinit
if (forDeinit && diagnoseNonSendableFromDeinit(module, refInst))
if (forDeinit && diagnoseNonSendableFromDeinit(refInst))
continue;

markPropertyUse(user);
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/CodeSynthesis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
auto type = var->getTypeInContext();
auto isolation = getActorIsolation(var);
if (isolation.isGlobalActor()) {
if (!isSendableType(decl->getModuleContext(), type) ||
if (!type->isSendableType() ||
var->getInitializerIsolation().isGlobalActor()) {
// If different isolated stored properties require different
// global actors, it is impossible to initialize this type.
Expand Down
3 changes: 1 addition & 2 deletions lib/Sema/ConstraintSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2806,8 +2806,7 @@ ConstraintSystem::getTypeOfMemberReference(
FunctionType::ExtInfo info;

if (Context.LangOpts.hasFeature(Feature::InferSendableFromCaptures)) {
if (isPartialApplication(locator) &&
isSendableType(DC->getParentModule(), baseOpenedTy)) {
if (isPartialApplication(locator) && baseOpenedTy->isSendableType()) {
// Add @Sendable to functions without conditional conformances
functionType =
functionType
Expand Down
24 changes: 19 additions & 5 deletions lib/Sema/IDETypeCheckingRequests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,20 +161,34 @@ static bool isMemberDeclAppliedInternal(const DeclContext *DC, Type BaseTy,
const GenericContext *genericDecl = VD->getAsGenericContext();
if (!genericDecl)
return true;

// The declaration may introduce inner generic parameters and requirements,
// or it may be nested in an outer generic context.
GenericSignature genericSig = genericDecl->getGenericSignature();
if (!genericSig)
return true;

// The context substitution map for the base type fixes the declaration's
// outer generic parameters.
auto *module = DC->getParentModule();
SubstitutionMap substMap = BaseTy->getContextSubstitutionMap(
auto substMap = BaseTy->getContextSubstitutionMap(
module, VD->getDeclContext());

// Note: we treat substitution failure as success, to avoid tripping
// up over generic parameters introduced by the declaration itself.
// The innermost generic parameters are mapped to error types.
unsigned innerDepth = genericSig.getGenericParams().back()->getDepth();
if (!genericDecl->isGeneric())
++innerDepth;

// We treat substitution failure as success, to ignore requirements
// that involve innermost generic parameters.
return checkRequirements(module,
genericSig.getRequirements(),
QuerySubstitutionMap{substMap}) !=
CheckRequirementsResult::RequirementFailure;
[&](SubstitutableType *type) -> Type {
auto *paramTy = cast<GenericTypeParamType>(type);
if (paramTy->getDepth() == innerDepth)
return ErrorType::get(DC->getASTContext());
return Type(paramTy).subst(substMap);
}) != CheckRequirementsResult::RequirementFailure;
}

bool
Expand Down
7 changes: 2 additions & 5 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6825,9 +6825,6 @@ void AttributeChecker::visitKnownToBeLocalAttr(KnownToBeLocalAttr *attr) {
}

void AttributeChecker::visitSendableAttr(SendableAttr *attr) {

auto dc = D->getDeclContext();

if ((isa<AbstractFunctionDecl>(D) || isa<AbstractStorageDecl>(D)) &&
!isAsyncDecl(cast<ValueDecl>(D))) {
auto value = cast<ValueDecl>(D);
Expand All @@ -6841,8 +6838,8 @@ void AttributeChecker::visitSendableAttr(SendableAttr *attr) {
}
// Prevent Sendable Attr from being added to methods of non-sendable types
if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(D)) {
if (auto selfdecl = funcDecl->getImplicitSelfDecl()) {
if (!isSendableType(dc->getParentModule(), selfdecl->getTypeInContext())) {
if (auto selfDecl = funcDecl->getImplicitSelfDecl()) {
if (!selfDecl->getTypeInContext()->isSendableType()) {
diagnose(attr->getLocation(), diag::nonsendable_instance_method)
.warnUntilSwiftVersion(6);
}
Expand Down
30 changes: 2 additions & 28 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -683,31 +683,6 @@ static bool isSendableClosure(
return false;
}

/// Determine whether the given type is suitable as a concurrent value type.
bool swift::isSendableType(ModuleDecl *module, Type type) {
auto proto = module->getASTContext().getProtocol(KnownProtocolKind::Sendable);
if (!proto)
return true;

// First check if we have a function type. If we do, check if it is
// Sendable. We do this since functions cannot conform to protocols.
if (auto *fas = type->getAs<SILFunctionType>())
return fas->isSendable();
if (auto *fas = type->getAs<AnyFunctionType>())
return fas->isSendable();

auto conformance = module->checkConformance(type, proto);
if (conformance.isInvalid())
return false;

// Look for missing Sendable conformances.
return !conformance.forEachMissingConformance(
[](BuiltinProtocolConformance *missing) {
return missing->getProtocol()->isSpecificProtocol(
KnownProtocolKind::Sendable);
});
}

/// Add Fix-It text for the given nominal type to adopt Sendable.
static void addSendableFixIt(
const NominalTypeDecl *nominal, InFlightDiagnostic &diag, bool unchecked) {
Expand Down Expand Up @@ -4741,8 +4716,7 @@ ActorIsolation ActorIsolationRequest::evaluate(
diagVar = originalVar;
}
if (var->isLet()) {
if (!isSendableType(var->getModuleContext(),
var->getInterfaceType())) {
if (!var->getInterfaceType()->isSendableType()) {
diagVar->diagnose(diag::shared_immutable_state_decl, diagVar)
.warnUntilSwiftVersion(6);
}
Expand Down Expand Up @@ -6356,7 +6330,7 @@ ActorReferenceResult ActorReferenceResult::forReference(
(!actorInstance || actorInstance->isSelf())) {
auto type =
fromDC->mapTypeIntoContext(declRef.getDecl()->getInterfaceType());
if (!isSendableType(fromDC->getParentModule(), type)) {
if (!type->isSendableType()) {
// Treat the decl isolation as 'preconcurrency' to downgrade violations
// to warnings, because violating Sendable here is accepted by the
// Swift 5.9 compiler.
Expand Down
2 changes: 1 addition & 1 deletion lib/Sema/TypeCheckDeclPrimary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1653,7 +1653,7 @@ static void diagnoseRetroactiveConformances(
proto->walkInheritedProtocols([&](ProtocolDecl *decl) {

// Get the original conformance of the extended type to this protocol.
auto conformanceRef = ext->getParentModule()->checkConformance(
auto conformanceRef = ext->getParentModule()->lookupConformance(
extendedType, decl);
if (!conformanceRef.isConcrete()) {

Expand Down
Loading