Skip to content

Commit 6f05e61

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 93d79ba + 4b3c821 commit 6f05e61

File tree

5 files changed

+90
-91
lines changed

5 files changed

+90
-91
lines changed

lib/Sema/CSBindings.cpp

Lines changed: 73 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,25 @@ bool ConstraintSystem::PotentialBindings::isViable(
206206
return true;
207207
}
208208

209+
static bool hasNilLiteralConstraint(TypeVariableType *typeVar,
210+
ConstraintSystem &CS) {
211+
// Look for a literal-conformance constraint on the type variable.
212+
llvm::SetVector<Constraint *> constraints;
213+
CS.getConstraintGraph().gatherConstraints(
214+
typeVar, constraints, ConstraintGraph::GatheringKind::EquivalenceClass,
215+
[](Constraint *constraint) -> bool {
216+
return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
217+
constraint->getProtocol()->isSpecificProtocol(
218+
KnownProtocolKind::ExpressibleByNilLiteral);
219+
});
220+
221+
for (auto constraint : constraints)
222+
if (CS.simplifyType(constraint->getFirstType())->isEqual(typeVar))
223+
return true;
224+
225+
return false;
226+
}
227+
209228
Optional<ConstraintSystem::PotentialBinding>
210229
ConstraintSystem::getPotentialBindingForRelationalConstraint(
211230
PotentialBindings &result, Constraint *constraint,
@@ -291,22 +310,27 @@ ConstraintSystem::getPotentialBindingForRelationalConstraint(
291310

292311
// Check whether we can perform this binding.
293312
// FIXME: this has a super-inefficient extraneous simplifyType() in it.
294-
bool isNilLiteral = false;
295-
bool *isNilLiteralPtr = nullptr;
296-
if (!addOptionalSupertypeBindings && kind == AllowedBindingKind::Supertypes)
297-
isNilLiteralPtr = &isNilLiteral;
298-
if (auto boundType = checkTypeOfBinding(typeVar, type, isNilLiteralPtr)) {
313+
if (auto boundType = checkTypeOfBinding(typeVar, type)) {
299314
type = *boundType;
300315
if (type->hasTypeVariable())
301316
result.InvolvesTypeVariables = true;
302317
} else {
303-
// If the bound is a 'nil' literal type, add optional supertype bindings.
304-
if (isNilLiteral) {
305-
addOptionalSupertypeBindings = true;
318+
auto *bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>();
319+
320+
if (!bindingTypeVar)
306321
return None;
307-
}
308322

309323
result.InvolvesTypeVariables = true;
324+
325+
// If we've already set addOptionalSupertypeBindings, or we aren't
326+
// allowing supertype bindings, we're done.
327+
if (addOptionalSupertypeBindings || kind != AllowedBindingKind::Supertypes)
328+
return None;
329+
330+
// If the bound is a 'nil' literal type, add optional supertype bindings.
331+
if (hasNilLiteralConstraint(bindingTypeVar, *this))
332+
addOptionalSupertypeBindings = true;
333+
310334
return None;
311335
}
312336

@@ -724,6 +748,46 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) {
724748
return result;
725749
}
726750

751+
/// \brief Check whether the given type can be used as a binding for the given
752+
/// type variable.
753+
///
754+
/// \returns the type to bind to, if the binding is okay.
755+
Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
756+
Type type) {
757+
// Simplify the type.
758+
type = simplifyType(type);
759+
760+
// If the type references the type variable, don't permit the binding.
761+
SmallVector<TypeVariableType *, 4> referencedTypeVars;
762+
type->getTypeVariables(referencedTypeVars);
763+
if (count(referencedTypeVars, typeVar))
764+
return None;
765+
766+
// If type variable is not allowed to bind to `lvalue`,
767+
// let's check if type of potential binding has any
768+
// type variables, which are allowed to bind to `lvalue`,
769+
// and postpone such type from consideration.
770+
if (!typeVar->getImpl().canBindToLValue()) {
771+
for (auto *typeVar : referencedTypeVars) {
772+
if (typeVar->getImpl().canBindToLValue())
773+
return None;
774+
}
775+
}
776+
777+
// If the type is a type variable itself, don't permit the binding.
778+
if (auto *bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>())
779+
return None;
780+
781+
// Don't bind to a dependent member type, even if it's currently
782+
// wrapped in any number of optionals, because binding producer
783+
// might unwrap and try to attempt it directly later.
784+
if (type->lookThroughAllOptionalTypes()->is<DependentMemberType>())
785+
return None;
786+
787+
// Okay, allow the binding (with the simplified type).
788+
return type;
789+
}
790+
727791
// Given a possibly-Optional type, return the direct superclass of the
728792
// (underlying) type wrapped in the same number of optional levels as
729793
// type.

lib/Sema/CSSolver.cpp

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -61,73 +61,6 @@ TypeVariableType *ConstraintSystem::createTypeVariable(
6161
return tv;
6262
}
6363

64-
/// \brief Check whether the given type can be used as a binding for the given
65-
/// type variable.
66-
///
67-
/// \returns the type to bind to, if the binding is okay.
68-
Optional<Type> ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar,
69-
Type type,
70-
bool *isNilLiteral) {
71-
if (!type)
72-
return None;
73-
74-
// Simplify the type.
75-
type = simplifyType(type);
76-
77-
// If the type references the type variable, don't permit the binding.
78-
SmallVector<TypeVariableType *, 4> referencedTypeVars;
79-
type->getTypeVariables(referencedTypeVars);
80-
if (count(referencedTypeVars, typeVar))
81-
return None;
82-
83-
// If type variable is not allowed to bind to `lvalue`,
84-
// let's check if type of potential binding has any
85-
// type variables, which are allowed to bind to `lvalue`,
86-
// and postpone such type from consideration.
87-
if (!typeVar->getImpl().canBindToLValue()) {
88-
for (auto *typeVar : referencedTypeVars) {
89-
if (typeVar->getImpl().canBindToLValue())
90-
return None;
91-
}
92-
}
93-
94-
// If the type is a type variable itself, don't permit the binding.
95-
if (auto bindingTypeVar = type->getRValueType()->getAs<TypeVariableType>()) {
96-
if (isNilLiteral) {
97-
*isNilLiteral = false;
98-
99-
// Look for a literal-conformance constraint on the type variable.
100-
llvm::SetVector<Constraint *> constraints;
101-
getConstraintGraph().gatherConstraints(
102-
bindingTypeVar, constraints,
103-
ConstraintGraph::GatheringKind::EquivalenceClass,
104-
[](Constraint *constraint) -> bool {
105-
return constraint->getKind() == ConstraintKind::LiteralConformsTo &&
106-
constraint->getProtocol()->isSpecificProtocol(
107-
KnownProtocolKind::ExpressibleByNilLiteral);
108-
});
109-
110-
for (auto constraint : constraints) {
111-
if (simplifyType(constraint->getFirstType())->isEqual(bindingTypeVar)) {
112-
*isNilLiteral = true;
113-
break;
114-
}
115-
}
116-
}
117-
118-
return None;
119-
}
120-
121-
// Don't bind to a dependent member type, even if it's currently
122-
// wrapped in any number of optionals, because binding producer
123-
// might unwrap and try to attempt it directly later.
124-
if (type->lookThroughAllOptionalTypes()->is<DependentMemberType>())
125-
return None;
126-
127-
// Okay, allow the binding (with the simplified type).
128-
return type;
129-
}
130-
13164
Solution ConstraintSystem::finalize() {
13265
assert(solverState);
13366

lib/Sema/ConstraintSystem.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2984,8 +2984,7 @@ class ConstraintSystem {
29842984
}
29852985
};
29862986

2987-
Optional<Type> checkTypeOfBinding(TypeVariableType *typeVar, Type type,
2988-
bool *isNilLiteral = nullptr);
2987+
Optional<Type> checkTypeOfBinding(TypeVariableType *typeVar, Type type);
29892988
Optional<PotentialBindings> determineBestBindings();
29902989
Optional<ConstraintSystem::PotentialBinding>
29912990
getPotentialBindingForRelationalConstraint(

stdlib/public/runtime/Casting.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -635,23 +635,13 @@ static bool _dynamicCastToAnyHashable(OpaqueValue *destination,
635635

636636
// If we do find one, the cast succeeds.
637637

638-
// The intrinsic wants the value at +1, so we have to copy it into
639-
// a temporary.
640-
ValueBuffer buffer;
641-
bool mustDeallocBuffer = false;
642-
if (!(flags & DynamicCastFlags::TakeOnSuccess)) {
643-
auto *valueAddr = sourceType->allocateBufferIn(&buffer);
644-
source = sourceType->vw_initializeWithCopy(valueAddr, source);
645-
mustDeallocBuffer = true;
646-
}
647-
648638
// Initialize the destination.
649639
_swift_convertToAnyHashableIndirect(source, destination,
650640
sourceType, hashableConformance);
651641

652-
// Deallocate the buffer if we used it.
653-
if (mustDeallocBuffer) {
654-
sourceType->deallocateBufferIn(&buffer);
642+
// Destroy the value if requested.
643+
if (flags & DynamicCastFlags::TakeOnSuccess) {
644+
sourceType->vw_destroy(source);
655645
}
656646

657647
// The cast succeeded.
@@ -1932,6 +1922,9 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
19321922

19331923
#if !SWIFT_OBJC_INTEROP // __SwiftValue is a native class:
19341924
if (swift_unboxFromSwiftValueWithType(src, dest, targetType)) {
1925+
// Release the source if we need to.
1926+
if (flags & DynamicCastFlags::TakeOnSuccess)
1927+
srcType->vw_destroy(src);
19351928
return true;
19361929
}
19371930
#endif

test/stdlib/AnyHashableCasts.swift.gyb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ AnyHashableCasts.test("${valueExpr} as ${coercedType} as? ${castType}") {
123123
}
124124
% end
125125

126+
AnyHashableCasts.test("Casting to AnyHashable doesn't leak") {
127+
do {
128+
let tracked = LifetimeTracked(42)
129+
let anyHashable = AnyHashable(tracked)
130+
let anyObject = anyHashable as AnyObject
131+
_ = anyObject as? AnyHashable
132+
}
133+
expectEqual(LifetimeTracked.instances, 0)
134+
}
135+
126136
#if _runtime(_ObjC)
127137
// A wrapper type around Int that bridges to NSNumber.
128138
struct IntWrapper1: _SwiftNewtypeWrapper, Hashable, _ObjectiveCBridgeable {

0 commit comments

Comments
 (0)