Skip to content

Commit 6972f83

Browse files
authored
Merge pull request #24082 from slavapestov/typevar-noescape-fix
Introduce "can bind to noescape" bit on TypeVariableType
2 parents 4ab605e + f3bb3d9 commit 6972f83

15 files changed

+299
-1806
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3044,6 +3044,9 @@ ERROR(general_noescape_to_escaping,none,
30443044
ERROR(converting_noescape_to_type,none,
30453045
"converting non-escaping value to %0 may allow it to escape",
30463046
(Type))
3047+
ERROR(unknown_escaping_use_of_noescape,none,
3048+
"using non-escaping value in a context where it may escape",
3049+
())
30473050

30483051
ERROR(capture_across_type_decl,none,
30493052
"%0 declaration cannot close over value %1 defined in outer scope",

include/swift/AST/TypeAlignments.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ namespace swift {
5858
constexpr size_t TypeAlignInBits = 3;
5959
constexpr size_t PatternAlignInBits = 3;
6060
constexpr size_t SILFunctionAlignInBits = 2;
61+
constexpr size_t TypeVariableAlignInBits = 4;
6162
}
6263

6364
namespace llvm {
@@ -95,7 +96,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::ExtensionDecl, swift::DeclAlignInBits)
9596

9697
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeBase, swift::TypeAlignInBits)
9798
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ArchetypeType, swift::TypeAlignInBits)
98-
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeVariableType, swift::TypeAlignInBits)
99+
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeVariableType, swift::TypeVariableAlignInBits)
99100

100101
LLVM_DECLARE_TYPE_ALIGNMENT(swift::Stmt, swift::StmtAlignInBits)
101102
LLVM_DECLARE_TYPE_ALIGNMENT(swift::BraceStmt, swift::StmtAlignInBits)

include/swift/AST/Types.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,11 @@ class alignas(1 << TypeAlignInBits) TypeBase {
329329
ID : 32 - NumTypeBaseBits,
330330

331331
/// Type variable options.
332-
Options : 3,
332+
Options : 4,
333333

334334
/// Index into the list of type variables, as used by the
335335
/// constraint graph.
336-
GraphIndex : 29
336+
GraphIndex : 28
337337
);
338338

339339
SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+3+1+2,
@@ -5060,13 +5060,15 @@ END_CAN_TYPE_WRAPPER(Name##StorageType, ReferenceStorageType)
50605060
#undef REF_STORAGE_HELPER
50615061

50625062
/// A type variable used during type checking.
5063-
class TypeVariableType : public TypeBase {
5063+
class alignas(1 << TypeVariableAlignInBits)
5064+
TypeVariableType : public TypeBase {
50645065
// Note: We can't use llvm::TrailingObjects here because the trailing object
50655066
// type is opaque.
50665067

50675068
TypeVariableType(const ASTContext &C, unsigned ID)
50685069
: TypeBase(TypeKind::TypeVariable, &C,
50695070
RecursiveTypeProperties::HasTypeVariable) {
5071+
// Note: the ID may overflow, but its only used for printing.
50705072
Bits.TypeVariableType.ID = ID;
50715073
}
50725074

@@ -5103,6 +5105,8 @@ class TypeVariableType : public TypeBase {
51035105
return reinterpret_cast<Implementation *>(this + 1);
51045106
}
51055107

5108+
/// Type variable IDs are not globally unique and are only meant as a visual
5109+
/// aid when dumping AST.
51065110
unsigned getID() const { return Bits.TypeVariableType.ID; }
51075111

51085112
// Implement isa/cast/dyncast/etc.

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2430,10 +2430,7 @@ static bool isEscaping(Type type) {
24302430
FunctionTypeRepresentation::CFunctionPointer)
24312431
return false;
24322432

2433-
if (funcType->getExtInfo().isNoEscape())
2434-
return false;
2435-
2436-
return true;
2433+
return !funcType->getExtInfo().isNoEscape();
24372434
}
24382435

24392436
return false;
@@ -2443,8 +2440,6 @@ static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
24432440
ParameterTypeFlags flags, bool escaping) {
24442441
if (!options.excludeAttrKind(TAK_autoclosure) && flags.isAutoClosure())
24452442
printer << "@autoclosure ";
2446-
if (!options.excludeAttrKind(TAK_escaping) && escaping)
2447-
printer << "@escaping ";
24482443

24492444
switch (flags.getValueOwnership()) {
24502445
case ValueOwnership::Default:
@@ -2460,6 +2455,9 @@ static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
24602455
printer.printKeyword("__owned", options, " ");
24612456
break;
24622457
}
2458+
2459+
if (!options.excludeAttrKind(TAK_escaping) && escaping)
2460+
printer << "@escaping ";
24632461
}
24642462

24652463
void PrintAST::visitVarDecl(VarDecl *decl) {
@@ -3556,7 +3554,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35563554

35573555
void visitParenType(ParenType *T) {
35583556
Printer << "(";
3559-
printParameterFlags(Printer, Options, T->getParameterFlags(), false);
3557+
printParameterFlags(Printer, Options, T->getParameterFlags(),
3558+
/*escaping*/ false);
35603559
visit(T->getUnderlyingType()->getInOutObjectType());
35613560
Printer << ")";
35623561
}
@@ -3587,7 +3586,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
35873586
visit(TD.getVarargBaseTy());
35883587
Printer << "...";
35893588
} else {
3590-
printParameterFlags(Printer, Options, TD.getParameterFlags(), false);
3589+
printParameterFlags(Printer, Options, TD.getParameterFlags(),
3590+
/*escaping*/ false);
35913591
visit(EltType);
35923592
}
35933593
}

lib/Sema/CSDiag.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4008,7 +4008,8 @@ namespace {
40084008
auto resultLocator =
40094009
cs.getConstraintLocator(expr, ConstraintLocator::FunctionResult);
40104010
auto resultType = cs.createTypeVariable(resultLocator,
4011-
TVO_CanBindToLValue);
4011+
TVO_CanBindToLValue |
4012+
TVO_CanBindToNoEscape);
40124013

40134014
auto locator = cs.getConstraintLocator(expr);
40144015
cs.addConstraint(ConstraintKind::FunctionResult,
@@ -4464,7 +4465,8 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
44644465
} else if (auto *typeVar = resultType->getAs<TypeVariableType>()) {
44654466
auto tv = cs.createTypeVariable(cs.getConstraintLocator(expr),
44664467
TVO_CanBindToLValue |
4467-
TVO_PrefersSubtypeBinding);
4468+
TVO_PrefersSubtypeBinding |
4469+
TVO_CanBindToNoEscape);
44684470

44694471
auto extInfo = FunctionType::ExtInfo().withThrows();
44704472

@@ -6182,7 +6184,7 @@ bool FailureDiagnosis::visitKeyPathExpr(KeyPathExpr *KPE) {
61826184

61836185
bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
61846186
auto *locator = cs.getConstraintLocator(expr);
6185-
auto valueType = cs.createTypeVariable(locator);
6187+
auto valueType = cs.createTypeVariable(locator, TVO_CanBindToNoEscape);
61866188

61876189
auto keyPathType =
61886190
BoundGenericClassType::get(Decl, ParentType, {RootType, valueType});

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -401,17 +401,21 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {
401401
return true;
402402
}
403403

404-
auto path = getLocator()->getPath();
405-
if (path.empty())
406-
return false;
404+
GenericTypeParamType *paramTy = nullptr;
407405

408-
auto &last = path.back();
409-
if (last.getKind() != ConstraintLocator::GenericParameter)
410-
return false;
406+
auto path = getLocator()->getPath();
407+
if (!path.empty()) {
408+
auto &last = path.back();
409+
if (last.getKind() == ConstraintLocator::GenericParameter)
410+
paramTy = last.getGenericParameter();
411+
}
411412

412-
auto *paramTy = last.getGenericParameter();
413-
emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
414-
paramTy);
413+
if (paramTy) {
414+
emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
415+
paramTy);
416+
} else {
417+
emitDiagnostic(anchor->getLoc(), diag::unknown_escaping_use_of_noescape);
418+
}
415419
return true;
416420
}
417421

0 commit comments

Comments
 (0)