Skip to content

Introduce "can bind to noescape" bit on TypeVariableType #24082

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 17, 2019
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: 3 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3044,6 +3044,9 @@ ERROR(general_noescape_to_escaping,none,
ERROR(converting_noescape_to_type,none,
"converting non-escaping value to %0 may allow it to escape",
(Type))
ERROR(unknown_escaping_use_of_noescape,none,
"using non-escaping value in a context where it may escape",
())

ERROR(capture_across_type_decl,none,
"%0 declaration cannot close over value %1 defined in outer scope",
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/TypeAlignments.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ namespace swift {
constexpr size_t TypeAlignInBits = 3;
constexpr size_t PatternAlignInBits = 3;
constexpr size_t SILFunctionAlignInBits = 2;
constexpr size_t TypeVariableAlignInBits = 4;
}

namespace llvm {
Expand Down Expand Up @@ -95,7 +96,7 @@ LLVM_DECLARE_TYPE_ALIGNMENT(swift::ExtensionDecl, swift::DeclAlignInBits)

LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeBase, swift::TypeAlignInBits)
LLVM_DECLARE_TYPE_ALIGNMENT(swift::ArchetypeType, swift::TypeAlignInBits)
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeVariableType, swift::TypeAlignInBits)
LLVM_DECLARE_TYPE_ALIGNMENT(swift::TypeVariableType, swift::TypeVariableAlignInBits)

LLVM_DECLARE_TYPE_ALIGNMENT(swift::Stmt, swift::StmtAlignInBits)
LLVM_DECLARE_TYPE_ALIGNMENT(swift::BraceStmt, swift::StmtAlignInBits)
Expand Down
10 changes: 7 additions & 3 deletions include/swift/AST/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,11 @@ class alignas(1 << TypeAlignInBits) TypeBase {
ID : 32 - NumTypeBaseBits,

/// Type variable options.
Options : 3,
Options : 4,

/// Index into the list of type variables, as used by the
/// constraint graph.
GraphIndex : 29
GraphIndex : 28
);

SWIFT_INLINE_BITFIELD(SILFunctionType, TypeBase, NumSILExtInfoBits+3+1+2,
Expand Down Expand Up @@ -5060,13 +5060,15 @@ END_CAN_TYPE_WRAPPER(Name##StorageType, ReferenceStorageType)
#undef REF_STORAGE_HELPER

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

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

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

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

// Implement isa/cast/dyncast/etc.
Expand Down
16 changes: 8 additions & 8 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2430,10 +2430,7 @@ static bool isEscaping(Type type) {
FunctionTypeRepresentation::CFunctionPointer)
return false;

if (funcType->getExtInfo().isNoEscape())
return false;

return true;
return !funcType->getExtInfo().isNoEscape();
}

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

switch (flags.getValueOwnership()) {
case ValueOwnership::Default:
Expand All @@ -2460,6 +2455,9 @@ static void printParameterFlags(ASTPrinter &printer, PrintOptions options,
printer.printKeyword("__owned", options, " ");
break;
}

if (!options.excludeAttrKind(TAK_escaping) && escaping)
printer << "@escaping ";
}

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

void visitParenType(ParenType *T) {
Printer << "(";
printParameterFlags(Printer, Options, T->getParameterFlags(), false);
printParameterFlags(Printer, Options, T->getParameterFlags(),
/*escaping*/ false);
visit(T->getUnderlyingType()->getInOutObjectType());
Printer << ")";
}
Expand Down Expand Up @@ -3587,7 +3586,8 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
visit(TD.getVarargBaseTy());
Printer << "...";
} else {
printParameterFlags(Printer, Options, TD.getParameterFlags(), false);
printParameterFlags(Printer, Options, TD.getParameterFlags(),
/*escaping*/ false);
visit(EltType);
}
}
Expand Down
8 changes: 5 additions & 3 deletions lib/Sema/CSDiag.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4008,7 +4008,8 @@ namespace {
auto resultLocator =
cs.getConstraintLocator(expr, ConstraintLocator::FunctionResult);
auto resultType = cs.createTypeVariable(resultLocator,
TVO_CanBindToLValue);
TVO_CanBindToLValue |
TVO_CanBindToNoEscape);

auto locator = cs.getConstraintLocator(expr);
cs.addConstraint(ConstraintKind::FunctionResult,
Expand Down Expand Up @@ -4464,7 +4465,8 @@ bool FailureDiagnosis::diagnoseTrailingClosureErrors(ApplyExpr *callExpr) {
} else if (auto *typeVar = resultType->getAs<TypeVariableType>()) {
auto tv = cs.createTypeVariable(cs.getConstraintLocator(expr),
TVO_CanBindToLValue |
TVO_PrefersSubtypeBinding);
TVO_PrefersSubtypeBinding |
TVO_CanBindToNoEscape);

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

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

bool builtConstraints(ConstraintSystem &cs, Expr *expr) override {
auto *locator = cs.getConstraintLocator(expr);
auto valueType = cs.createTypeVariable(locator);
auto valueType = cs.createTypeVariable(locator, TVO_CanBindToNoEscape);

auto keyPathType =
BoundGenericClassType::get(Decl, ParentType, {RootType, valueType});
Expand Down
22 changes: 13 additions & 9 deletions lib/Sema/CSDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,17 +401,21 @@ bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {
return true;
}

auto path = getLocator()->getPath();
if (path.empty())
return false;
GenericTypeParamType *paramTy = nullptr;

auto &last = path.back();
if (last.getKind() != ConstraintLocator::GenericParameter)
return false;
auto path = getLocator()->getPath();
if (!path.empty()) {
auto &last = path.back();
if (last.getKind() == ConstraintLocator::GenericParameter)
paramTy = last.getGenericParameter();
}

auto *paramTy = last.getGenericParameter();
emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
paramTy);
if (paramTy) {
emitDiagnostic(anchor->getLoc(), diag::converting_noescape_to_type,
paramTy);
} else {
emitDiagnostic(anchor->getLoc(), diag::unknown_escaping_use_of_noescape);
}
return true;
}

Expand Down
Loading