AST: Add TypeBase::isNoEscape()

This commit is contained in:
Slava Pestov
2019-04-07 22:38:31 -04:00
parent e214156abf
commit 1c17ccfd3c
4 changed files with 53 additions and 34 deletions

View File

@@ -1641,12 +1641,12 @@ ConstraintSystem::matchExistentialTypes(Type type1, Type type2,
return getTypeMatchFailure(locator);
// FIXME; Feels like a hack...nothing actually "conforms" here, and
// we need to disallow conversions from @noescape functions to Any.
// we need to disallow conversions from types containing @noescape
// functions to Any.
// Conformance to 'Any' always holds.
if (type2->isAny()) {
auto *fnTy = type1->getAs<FunctionType>();
if (!fnTy || !fnTy->isNoEscape())
if (!type1->isNoEscape())
return getTypeMatchSuccess();
if (shouldAttemptFixes()) {
@@ -1835,21 +1835,19 @@ ConstraintSystem::matchTypesBindTypeVar(
return getTypeMatchFailure(locator);
}
// Disallow bindings of noescape functions to type variables that
// represent an opened archetype. If we allowed this it would allow
// the noescape function to potentially escape.
if (auto *fnTy = type->getAs<FunctionType>()) {
if (fnTy->isNoEscape() && typeVar->getImpl().getGenericParameter()) {
if (shouldAttemptFixes()) {
auto *fix = MarkExplicitlyEscaping::create(
*this, getConstraintLocator(locator));
if (recordFix(fix))
return getTypeMatchFailure(locator);
// Allow no-escape function to be bound with recorded fix.
} else {
// Disallow bindings of types containing noescape functions to type
// variables that represent an opened generic parameter. If we allowed
// this it would allow noescape functions to potentially escape.
if (type->isNoEscape() && typeVar->getImpl().getGenericParameter()) {
if (shouldAttemptFixes()) {
auto *fix = MarkExplicitlyEscaping::create(
*this, getConstraintLocator(locator));
if (recordFix(fix))
return getTypeMatchFailure(locator);
}
// Allow no-escape function to be bound with recorded fix.
} else {
return getTypeMatchFailure(locator);
}
}
@@ -2413,23 +2411,21 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
type2->isExistentialType()) {
// Penalize conversions to Any, and disallow conversions of
// noescape functions to Any.
// types containing noescape functions to Any.
if (kind >= ConstraintKind::Conversion && type2->isAny()) {
if (auto *fnTy = type1->getAs<FunctionType>()) {
if (fnTy->isNoEscape()) {
if (shouldAttemptFixes()) {
auto &ctx = getASTContext();
auto *fix = MarkExplicitlyEscaping::create(
*this, getConstraintLocator(locator), ctx.TheAnyType);
if (recordFix(fix))
return getTypeMatchFailure(locator);
// Allow 'no-escape' functions to be converted to 'Any'
// with a recorded fix that helps us to properly diagnose
// such situations.
} else {
if (type1->isNoEscape()) {
if (shouldAttemptFixes()) {
auto &ctx = getASTContext();
auto *fix = MarkExplicitlyEscaping::create(
*this, getConstraintLocator(locator), ctx.TheAnyType);
if (recordFix(fix))
return getTypeMatchFailure(locator);
}
// Allow 'no-escape' functions to be converted to 'Any'
// with a recorded fix that helps us to properly diagnose
// such situations.
} else {
return getTypeMatchFailure(locator);
}
}