Skip to content

Commit d54ee5d

Browse files
authored
Merge pull request #65744 from hamishknight/second-place
2 parents 1426980 + c0e0139 commit d54ee5d

File tree

5 files changed

+70
-18
lines changed

5 files changed

+70
-18
lines changed

include/swift/AST/Types.h

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,13 @@ class RecursiveTypeProperties {
173173
/// This type contains an ElementArchetype.
174174
HasElementArchetype = 0x4000,
175175

176-
Last_Property = HasElementArchetype
176+
/// Whether the type is allocated in the constraint solver arena. This can
177+
/// differ from \c HasTypeVariable for types such as placeholders, which do
178+
/// not have type variables, but we still want to allocate in the solver if
179+
/// they have a type variable originator.
180+
SolverAllocated = 0x8000,
181+
182+
Last_Property = SolverAllocated
177183
};
178184
enum { BitWidth = countBitsUsed(Property::Last_Property) };
179185

@@ -224,6 +230,12 @@ class RecursiveTypeProperties {
224230
/// opened element archetype?
225231
bool hasElementArchetype() const { return Bits & HasElementArchetype; }
226232

233+
/// Whether the type is allocated in the constraint solver arena. This can
234+
/// differ from \c hasTypeVariable() for types such as placeholders, which
235+
/// do not have type variables, but we still want to allocate in the solver if
236+
/// they have a type variable originator.
237+
bool isSolverAllocated() const { return Bits & SolverAllocated; }
238+
227239
/// Does a type with these properties structurally contain a local
228240
/// archetype?
229241
bool hasLocalArchetype() const {
@@ -501,6 +513,8 @@ class alignas(1 << TypeAlignInBits) TypeBase
501513
}
502514

503515
void setRecursiveProperties(RecursiveTypeProperties properties) {
516+
assert(!(properties.hasTypeVariable() && !properties.isSolverAllocated()) &&
517+
"type variables must be solver allocated!");
504518
Bits.TypeBase.Properties = properties.getBits();
505519
assert(Bits.TypeBase.Properties == properties.getBits() && "Bits dropped!");
506520
}
@@ -6714,8 +6728,9 @@ TypeVariableType : public TypeBase {
67146728
// type is opaque.
67156729

67166730
TypeVariableType(const ASTContext &C, unsigned ID)
6717-
: TypeBase(TypeKind::TypeVariable, &C,
6718-
RecursiveTypeProperties::HasTypeVariable) {
6731+
: TypeBase(TypeKind::TypeVariable, &C,
6732+
RecursiveTypeProperties::HasTypeVariable |
6733+
RecursiveTypeProperties::SolverAllocated) {
67196734
// Note: the ID may overflow (current limit is 2^20 - 1).
67206735
Bits.TypeVariableType.ID = ID;
67216736
if (Bits.TypeVariableType.ID != ID) {
@@ -6774,6 +6789,8 @@ DEFINE_EMPTY_CAN_TYPE_WRAPPER(TypeVariableType, Type)
67746789
/// because the expression is ambiguous. This type is only used by the
67756790
/// constraint solver and transformed into UnresolvedType to be used in AST.
67766791
class PlaceholderType : public TypeBase {
6792+
// NOTE: If you add a new Type-based originator, you'll need to update the
6793+
// recursive property logic in PlaceholderType::get.
67776794
using Originator =
67786795
llvm::PointerUnion<TypeVariableType *, DependentMemberType *, VarDecl *,
67796796
ErrorExpr *, PlaceholderTypeRepr *>;

lib/AST/ASTContext.cpp

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,7 @@ struct ASTContext::Implementation {
430430
llvm::DenseMap<Type, InOutType*> InOutTypes;
431431
llvm::DenseMap<std::pair<Type, void*>, DependentMemberType *>
432432
DependentMemberTypes;
433+
llvm::DenseMap<void *, PlaceholderType *> PlaceholderTypes;
433434
llvm::DenseMap<Type, DynamicSelfType *> DynamicSelfTypes;
434435
llvm::DenseMap<std::pair<EnumDecl*, Type>, EnumType*> EnumTypes;
435436
llvm::DenseMap<std::pair<StructDecl*, Type>, StructType*> StructTypes;
@@ -1811,9 +1812,8 @@ bool ASTContext::hadError() const {
18111812

18121813
/// Retrieve the arena from which we should allocate storage for a type.
18131814
static AllocationArena getArena(RecursiveTypeProperties properties) {
1814-
bool hasTypeVariable = properties.hasTypeVariable();
1815-
return hasTypeVariable ? AllocationArena::ConstraintSolver
1816-
: AllocationArena::Permanent;
1815+
return properties.isSolverAllocated() ? AllocationArena::ConstraintSolver
1816+
: AllocationArena::Permanent;
18171817
}
18181818

18191819
void ASTContext::addSearchPath(StringRef searchPath, bool isFramework,
@@ -3117,15 +3117,43 @@ Type ErrorType::get(Type originalType) {
31173117
void *mem = ctx.Allocate(sizeof(ErrorType) + sizeof(Type),
31183118
alignof(ErrorType), arena);
31193119
RecursiveTypeProperties properties = RecursiveTypeProperties::HasError;
3120-
if (originalProperties.hasTypeVariable())
3121-
properties |= RecursiveTypeProperties::HasTypeVariable;
3120+
3121+
// We need to preserve the solver allocated bit, to ensure any wrapping
3122+
// types are solver allocated too.
3123+
if (originalProperties.isSolverAllocated())
3124+
properties |= RecursiveTypeProperties::SolverAllocated;
3125+
31223126
return entry = new (mem) ErrorType(ctx, originalType, properties);
31233127
}
31243128

31253129
Type PlaceholderType::get(ASTContext &ctx, Originator originator) {
31263130
assert(originator);
3127-
return new (ctx, AllocationArena::Permanent)
3128-
PlaceholderType(ctx, originator, RecursiveTypeProperties::HasPlaceholder);
3131+
3132+
auto originatorProps = [&]() -> RecursiveTypeProperties {
3133+
if (auto *tv = originator.dyn_cast<TypeVariableType *>())
3134+
return tv->getRecursiveProperties();
3135+
3136+
if (auto *depTy = originator.dyn_cast<DependentMemberType *>())
3137+
return depTy->getRecursiveProperties();
3138+
3139+
return RecursiveTypeProperties();
3140+
}();
3141+
auto arena = getArena(originatorProps);
3142+
3143+
auto &cache = ctx.getImpl().getArena(arena).PlaceholderTypes;
3144+
auto &entry = cache[originator.getOpaqueValue()];
3145+
if (entry)
3146+
return entry;
3147+
3148+
RecursiveTypeProperties properties = RecursiveTypeProperties::HasPlaceholder;
3149+
3150+
// We need to preserve the solver allocated bit, to ensure any wrapping
3151+
// types are solver allocated too.
3152+
if (originatorProps.isSolverAllocated())
3153+
properties |= RecursiveTypeProperties::SolverAllocated;
3154+
3155+
entry = new (ctx, arena) PlaceholderType(ctx, originator, properties);
3156+
return entry;
31293157
}
31303158

31313159
BuiltinIntegerType *BuiltinIntegerType::get(BuiltinIntegerWidth BitWidth,
@@ -3943,7 +3971,7 @@ isAnyFunctionTypeCanonical(ArrayRef<AnyFunctionType::Param> params,
39433971
static RecursiveTypeProperties
39443972
getGenericFunctionRecursiveProperties(ArrayRef<AnyFunctionType::Param> params,
39453973
Type result) {
3946-
static_assert(RecursiveTypeProperties::BitWidth == 15,
3974+
static_assert(RecursiveTypeProperties::BitWidth == 16,
39473975
"revisit this if you add new recursive type properties");
39483976
RecursiveTypeProperties properties;
39493977

@@ -4604,7 +4632,7 @@ CanSILFunctionType SILFunctionType::get(
46044632
void *mem = ctx.Allocate(bytes, alignof(SILFunctionType));
46054633

46064634
RecursiveTypeProperties properties;
4607-
static_assert(RecursiveTypeProperties::BitWidth == 15,
4635+
static_assert(RecursiveTypeProperties::BitWidth == 16,
46084636
"revisit this if you add new recursive type properties");
46094637
for (auto &param : params)
46104638
properties |= param.getInterfaceType()->getRecursiveProperties();

lib/Sema/CSApply.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8475,8 +8475,8 @@ namespace {
84758475
exprType = solution.simplifyType(exprType);
84768476
// assert((!expr->getType() || expr->getType()->isEqual(exprType)) &&
84778477
// "Mismatched types!");
8478-
assert(!exprType->hasTypeVariable() &&
8479-
"Should not write type variable into expression!");
8478+
assert(!exprType->getRecursiveProperties().isSolverAllocated() &&
8479+
"Should not write solver allocated type into expression!");
84808480
assert(!exprType->hasPlaceholder() &&
84818481
"Should not write type placeholders into expression!");
84828482
expr->setType(exprType);
@@ -8486,8 +8486,10 @@ namespace {
84868486
Type componentType;
84878487
if (cs.hasType(kp, i)) {
84888488
componentType = solution.simplifyType(cs.getType(kp, i));
8489-
assert(!componentType->hasTypeVariable() &&
8490-
"Should not write type variable into key-path component");
8489+
assert(
8490+
!componentType->getRecursiveProperties().isSolverAllocated() &&
8491+
"Should not write solver allocated type into key-path "
8492+
"component!");
84918493
assert(!componentType->hasPlaceholder() &&
84928494
"Should not write type placeholder into key-path component");
84938495
kp->getMutableComponents()[i].setComponentType(componentType);

test/Constraints/rdar44770297.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ func foo<T: P>(_: () throws -> T) -> T.A? { // expected-note {{where 'T' = 'Neve
88
fatalError()
99
}
1010

11-
let _ = foo() {fatalError()} & nil // expected-error {{global function 'foo' requires that 'Never' conform to 'P'}}
11+
let _ = foo() {fatalError()} & nil
12+
// expected-error@-1 {{global function 'foo' requires that 'Never' conform to 'P'}}
13+
// expected-error@-2 {{value of optional type 'Never.A?' must be unwrapped to a value of type 'Never.A'}}
14+
// expected-note@-3 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
15+
// expected-note@-4 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}

validation-test/Sema/type_checker_crashers_fixed/issue-65360.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ let _: () -> Void = {
1313
// expected-error@-1 {{cannot convert value of type 'Any?' to specified type '(_, _)}}
1414
}
1515

16-
let _: () -> Void = { // expected-error {{unable to infer closure type in the current context}}
16+
let _: () -> Void = {
1717
for case (0)? in [a] {}
1818
for case (0, 0) in [a] {}
19+
// expected-error@-1 {{cannot convert value of type 'Any?' to expected element type '(_, _)'}}
1920
}

0 commit comments

Comments
 (0)