Skip to content

Commit 1c17ccf

Browse files
committed
AST: Add TypeBase::isNoEscape()
1 parent e214156 commit 1c17ccf

File tree

4 files changed

+53
-34
lines changed

4 files changed

+53
-34
lines changed

include/swift/AST/Types.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -622,10 +622,14 @@ class alignas(1 << TypeAlignInBits) TypeBase {
622622
return getRecursiveProperties().isLValue();
623623
}
624624

625-
/// Is a type with these properties materializable: that is, is it a
626-
/// first-class value type?
625+
/// Is this a first-class value type, meaning it is not an InOutType or a
626+
/// tuple type containing an InOutType?
627627
bool isMaterializable();
628628

629+
/// Is this a non-escaping type, that is, a non-escaping function type or a
630+
/// tuple type containing a non-escaping type?
631+
bool isNoEscape() const;
632+
629633
/// Determine whether the type is dependent on DynamicSelf.
630634
bool hasDynamicSelfType() const {
631635
return getRecursiveProperties().hasDynamicSelf();

lib/AST/Type.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3079,6 +3079,24 @@ const DependentMemberType *TypeBase::findUnresolvedDependentMemberType() {
30793079
return unresolvedDepMemTy;
30803080
}
30813081

3082+
bool TypeBase::isNoEscape() const {
3083+
auto type = getCanonicalType();
3084+
3085+
if (auto silFuncTy = dyn_cast<SILFunctionType>(type))
3086+
return silFuncTy->isNoEscape();
3087+
3088+
if (auto funcTy = dyn_cast<FunctionType>(type))
3089+
return funcTy->isNoEscape();
3090+
3091+
if (auto tupleTy = dyn_cast<TupleType>(type)) {
3092+
for (auto eltTy : tupleTy.getElementTypes())
3093+
if (eltTy->isNoEscape())
3094+
return true;
3095+
}
3096+
3097+
return false;
3098+
}
3099+
30823100
static Type getConcreteTypeForSuperclassTraversing(Type t) {
30833101
if (t->isExistentialType()) {
30843102
return t->getExistentialLayout().getSuperclass();

lib/Sema/CSSimplify.cpp

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1641,12 +1641,12 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
16411641
return getTypeMatchFailure(locator);
16421642

16431643
// FIXME; Feels like a hack...nothing actually "conforms" here, and
1644-
// we need to disallow conversions from @noescape functions to Any.
1644+
// we need to disallow conversions from types containing @noescape
1645+
// functions to Any.
16451646

16461647
// Conformance to 'Any' always holds.
16471648
if (type2->isAny()) {
1648-
auto *fnTy = type1->getAs<FunctionType>();
1649-
if (!fnTy || !fnTy->isNoEscape())
1649+
if (!type1->isNoEscape())
16501650
return getTypeMatchSuccess();
16511651

16521652
if (shouldAttemptFixes()) {
@@ -1835,21 +1835,19 @@ ConstraintSystem::matchTypesBindTypeVar(
18351835
return getTypeMatchFailure(locator);
18361836
}
18371837

1838-
// Disallow bindings of noescape functions to type variables that
1839-
// represent an opened archetype. If we allowed this it would allow
1840-
// the noescape function to potentially escape.
1841-
if (auto *fnTy = type->getAs<FunctionType>()) {
1842-
if (fnTy->isNoEscape() && typeVar->getImpl().getGenericParameter()) {
1843-
if (shouldAttemptFixes()) {
1844-
auto *fix = MarkExplicitlyEscaping::create(
1845-
*this, getConstraintLocator(locator));
1846-
if (recordFix(fix))
1847-
return getTypeMatchFailure(locator);
1848-
1849-
// Allow no-escape function to be bound with recorded fix.
1850-
} else {
1838+
// Disallow bindings of types containing noescape functions to type
1839+
// variables that represent an opened generic parameter. If we allowed
1840+
// this it would allow noescape functions to potentially escape.
1841+
if (type->isNoEscape() && typeVar->getImpl().getGenericParameter()) {
1842+
if (shouldAttemptFixes()) {
1843+
auto *fix = MarkExplicitlyEscaping::create(
1844+
*this, getConstraintLocator(locator));
1845+
if (recordFix(fix))
18511846
return getTypeMatchFailure(locator);
1852-
}
1847+
1848+
// Allow no-escape function to be bound with recorded fix.
1849+
} else {
1850+
return getTypeMatchFailure(locator);
18531851
}
18541852
}
18551853

@@ -2413,23 +2411,21 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
24132411
type2->isExistentialType()) {
24142412

24152413
// Penalize conversions to Any, and disallow conversions of
2416-
// noescape functions to Any.
2414+
// types containing noescape functions to Any.
24172415
if (kind >= ConstraintKind::Conversion && type2->isAny()) {
2418-
if (auto *fnTy = type1->getAs<FunctionType>()) {
2419-
if (fnTy->isNoEscape()) {
2420-
if (shouldAttemptFixes()) {
2421-
auto &ctx = getASTContext();
2422-
auto *fix = MarkExplicitlyEscaping::create(
2423-
*this, getConstraintLocator(locator), ctx.TheAnyType);
2424-
if (recordFix(fix))
2425-
return getTypeMatchFailure(locator);
2426-
2427-
// Allow 'no-escape' functions to be converted to 'Any'
2428-
// with a recorded fix that helps us to properly diagnose
2429-
// such situations.
2430-
} else {
2416+
if (type1->isNoEscape()) {
2417+
if (shouldAttemptFixes()) {
2418+
auto &ctx = getASTContext();
2419+
auto *fix = MarkExplicitlyEscaping::create(
2420+
*this, getConstraintLocator(locator), ctx.TheAnyType);
2421+
if (recordFix(fix))
24312422
return getTypeMatchFailure(locator);
2432-
}
2423+
2424+
// Allow 'no-escape' functions to be converted to 'Any'
2425+
// with a recorded fix that helps us to properly diagnose
2426+
// such situations.
2427+
} else {
2428+
return getTypeMatchFailure(locator);
24332429
}
24342430
}
24352431

test/attr/attr_noescape.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ func takesNoEscapeClosure(_ fn : () -> Int) {
4949
_ = "\(takesArray([fn]))" // expected-error {{using non-escaping parameter 'fn' in a context expecting an @escaping closure}}
5050

5151
assignToGlobal(fn) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
52+
assignToGlobal((fn, fn)) // expected-error {{converting non-escaping value to 'T' may allow it to escape}}
5253
}
5354

5455
class SomeClass {

0 commit comments

Comments
 (0)