Skip to content

Commit eed84ab

Browse files
committed
Sema: Add TVO_CanBindToNoEscape
We have a systemic class of issues where noescape types end up bound to type variables in places that should not. The existing diagnostic for this is ad-hoc and duplicated in several places but it doesn't actually address the root cause of the problem. For now, I've changed all call sites of createTypeVariable() to set the new flag. I plan on removing enough occurrences of the flag to replicate the old diagnostics. Then we can continue to refine this over time.
1 parent 7d2c5e1 commit eed84ab

File tree

11 files changed

+251
-107
lines changed

11 files changed

+251
-107
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/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)