Skip to content

Commit 3d8a9d4

Browse files
committed
Implement same type checking at runtime
1 parent 2c703ee commit 3d8a9d4

File tree

6 files changed

+94
-19
lines changed

6 files changed

+94
-19
lines changed

include/swift/Demangling/TypeDecoder.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,9 @@ class TypeDecoder {
877877
case NodeKind::DependentGenericParamType: {
878878
auto depth = Node->getChild(0)->getIndex();
879879
auto index = Node->getChild(1)->getIndex();
880-
return Builder.createGenericTypeParameterType(depth, index);
880+
return TypeLookupErrorOr<BuiltType>(
881+
Builder.createGenericTypeParameterType(depth, index),
882+
/*ignoreValueCheck*/ true);
881883
}
882884
case NodeKind::EscapingObjCBlock:
883885
case NodeKind::ObjCBlock:

include/swift/Demangling/TypeLookupError.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ template <typename T> class TypeLookupErrorOr {
172172
public:
173173
TypeLookupErrorOr() : Value(TypeLookupError("freshly constructed error")) {}
174174

175-
TypeLookupErrorOr(const T &t) : Value(t) {
176-
if (!t)
175+
TypeLookupErrorOr(const T &t, bool ignoreValueCheck = false) : Value(t) {
176+
if (!t && !ignoreValueCheck)
177177
Value = TypeLookupError("unknown error");
178178
}
179179

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,7 +2443,12 @@ class DecodedMetadataBuilder {
24432443
}
24442444

24452445
TypeLookupErrorOr<BuiltType> createIntegerType(intptr_t value) {
2446-
return BuiltType(value);
2446+
// Note: We explicitly ignore the value check here because when the
2447+
// integer happens to be '0', we'll compare a MetadataPackOrValue against
2448+
// 'nullptr' which this is. We know this is still a good value for
2449+
// integers.
2450+
return TypeLookupErrorOr<BuiltType>(BuiltType(value),
2451+
/*ignoreValueCheck*/ true);
24472452
}
24482453

24492454
TypeLookupErrorOr<BuiltType> createNegativeIntegerType(intptr_t value) {
@@ -2785,7 +2790,7 @@ swift::getTypePackByMangledName(StringRef typeName,
27852790
return type.getType().getMetadataPack();
27862791
}
27872792

2788-
TypeLookupErrorOr<size_t>
2793+
TypeLookupErrorOr<intptr_t>
27892794
swift::getTypeValueByMangledName(StringRef typeName,
27902795
const void *const *origArgumentVector,
27912796
SubstGenericParameterFn substGenericParam,
@@ -2800,15 +2805,14 @@ swift::getTypeValueByMangledName(StringRef typeName,
28002805
substWitnessTable);
28012806
auto type = Demangle::decodeMangledType(builder, node);
28022807

2803-
if (type.isError()) {
2808+
if (type.isError())
28042809
return *type.getError();
2805-
}
2806-
2807-
if (!type.getType()) {
2808-
return TypeLookupError("NULL type but no error provided");
2809-
}
28102810

2811-
return type.getType().getValue();
2811+
// Note: We explicitly ignore the value check here because when the
2812+
// integer happens to be '0', we'll do '!value' which in this case converts
2813+
// the integer to a boolean, but '0' is a valid value.
2814+
return TypeLookupErrorOr<intptr_t>(type.getType().getValue(),
2815+
/*ignoreValueCheck*/ true);
28122816
}
28132817

28142818
// ==== Function metadata functions ----------------------------------------------

stdlib/public/runtime/Private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ class TypeInfo {
523523
/// \p substWitnessTable Function that provides witness tables given a
524524
/// particular dependent conformance index.
525525
SWIFT_RUNTIME_LIBRARY_VISIBILITY
526-
TypeLookupErrorOr<size_t> getTypeValueByMangledName(
526+
TypeLookupErrorOr<intptr_t> getTypeValueByMangledName(
527527
StringRef typeName,
528528
const void * const *arguments,
529529
SubstGenericParameterFn substGenericParam,

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,8 +1654,51 @@ checkGenericValueRequirement(const GenericRequirementDescriptor &req,
16541654
SubstGenericParameterFn substGenericParam,
16551655
SubstDependentWitnessTableFn substWitnessTable,
16561656
llvm::SmallVectorImpl<InvertibleProtocolSet> &suppressed) {
1657-
// FIXME: implement
1658-
return std::nullopt;
1657+
assert(req.getFlags().isValueRequirement());
1658+
1659+
// Make sure we understand the requirement we're dealing with.
1660+
if (!req.hasKnownKind())
1661+
return TypeLookupError("unknown kind");
1662+
1663+
// Resolve the subject generic value.
1664+
auto result = swift::getTypeValueByMangledName(
1665+
req.getParam(), extraArguments.data(),
1666+
substGenericParam, substWitnessTable);
1667+
1668+
if (result.getError())
1669+
return *result.getError();
1670+
1671+
auto subjectValue = result.getType();
1672+
1673+
// Check the requirement.
1674+
switch (req.getKind()) {
1675+
case GenericRequirementKind::SameType: {
1676+
// Resolve the constraint generic value.
1677+
auto result = swift::getTypeValueByMangledName(
1678+
req.getMangledTypeName(), extraArguments.data(),
1679+
substGenericParam, substWitnessTable);
1680+
1681+
if (result.getError())
1682+
return *result.getError();
1683+
1684+
auto constraintValue = result.getType();
1685+
1686+
if (subjectValue != constraintValue) {
1687+
return TYPE_LOOKUP_ERROR_FMT(
1688+
"subject value %" PRIiPTR " does not match constraint value %" PRIiPTR,
1689+
subjectValue,
1690+
constraintValue);
1691+
}
1692+
1693+
return std::nullopt;
1694+
}
1695+
1696+
default: {
1697+
// Value requirements can only be same type'd at the moment.
1698+
return TYPE_LOOKUP_ERROR_FMT("unknown value generic requirement kind %u",
1699+
(unsigned)req.getKind());
1700+
}
1701+
}
16591702
}
16601703

16611704
static std::optional<TypeLookupError>

test/Runtime/check_create_type.swift

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking)
1+
// RUN: %target-run-simple-swift(-Xfrontend -disable-availability-checking -enable-experimental-feature ValueGenerics)
22
// REQUIRES: executable_test
33

44
// UNSUPPORTED: CPU=arm64e
@@ -13,6 +13,8 @@ struct Variadic<each T> {
1313
struct Nested<U, each V: Equatable> {}
1414
}
1515

16+
struct Value<let N: Int, let M: Int> {}
17+
1618
@_silgen_name("swift_allocateMetadataPack")
1719
func allocateMetadataPack(
1820
_ packPointer: UnsafeRawPointer,
@@ -30,7 +32,7 @@ func metaPointer(_ x: Any.Type) -> UnsafeRawPointer {
3032
unsafeBitCast(x, to: UnsafeRawPointer.self)
3133
}
3234

33-
testSuite.test("_swift_checkedCreateType non-variadic") {
35+
testSuite.test("_swift_instantiateCheckedGenericMetadata non-variadic") {
3436
let dictMeta = unsafeBitCast(
3537
[Int: Int].self as Any.Type,
3638
to: UnsafeRawPointer.self
@@ -53,7 +55,7 @@ testSuite.test("_swift_checkedCreateType non-variadic") {
5355
}
5456
}
5557

56-
testSuite.test("_swift_checkedCreateType variadic") {
58+
testSuite.test("_swift_instantiateCheckedGenericMetadata variadic") {
5759
let variMeta = unsafeBitCast(
5860
Variadic< >.self as Any.Type,
5961
to: UnsafeRawPointer.self
@@ -84,7 +86,7 @@ testSuite.test("_swift_checkedCreateType variadic") {
8486
}
8587
}
8688

87-
testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
89+
testSuite.test("_swift_instantiateCheckedGenericMetadata variadic nested with requirements") {
8890
let nestedMeta = unsafeBitCast(
8991
Variadic< >.Nested<()>.self as Any.Type,
9092
to: UnsafeRawPointer.self
@@ -271,4 +273,28 @@ testSuite.test("_swift_instantiateCheckedGenericMetadata concrete generic types
271273
}
272274
}
273275

276+
extension Value where N == M {
277+
struct NestedNEqualsM {}
278+
}
279+
280+
testSuite.test("_swift_instantiateCheckedGenericMetadata value generics") {
281+
let nestedMeta1 = metaPointer(Value<0, 0>.NestedNEqualsM.self)
282+
let nestedDesc1 = nestedMeta1.load(
283+
fromByteOffset: MemoryLayout<Int>.size,
284+
as: UnsafeRawPointer.self
285+
)
286+
287+
let genericArgs1: [Int] = [123]
288+
289+
genericArgs1.withUnsafeBufferPointer {
290+
let nested = _instantiateCheckedGenericMetadata(
291+
nestedDesc1,
292+
UnsafeRawPointer($0.baseAddress!),
293+
UInt($0.count)
294+
)
295+
296+
expectTrue(nested == Value<123, 123>.NestedNEqualsM.self)
297+
}
298+
}
299+
274300
runAllTests()

0 commit comments

Comments
 (0)