Skip to content

Commit a2e3e7c

Browse files
authored
Merge pull request #4801 from DougGregor/measurement-custom-anyhashable-3-0
[3.0] Fix casting to Measurement and introduce custom AnyHashable support
2 parents 01bf682 + c7612b9 commit a2e3e7c

File tree

4 files changed

+47
-7
lines changed

4 files changed

+47
-7
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4176,7 +4176,7 @@ ConstraintSystem::simplifyRestrictedConstraint(ConversionRestrictionKind restric
41764176
}
41774177

41784178
// If the bridged value type is generic, the generic arguments
4179-
// must match the
4179+
// must either match or be bridged.
41804180
// FIXME: This should be an associated type of the protocol.
41814181
if (auto bgt1 = type2->getAs<BoundGenericType>()) {
41824182
if (bgt1->getDecl() == TC.Context.getArrayDecl()) {
@@ -4219,7 +4219,7 @@ ConstraintSystem::simplifyRestrictedConstraint(ConversionRestrictionKind restric
42194219
locator.withPathElement(
42204220
LocatorPathElt::getGenericArgument(0))));
42214221
} else {
4222-
llvm_unreachable("unhandled generic bridged type");
4222+
// Nothing special to do; matchTypes will match generic arguments.
42234223
}
42244224
}
42254225

stdlib/public/SDK/Foundation/Measurement.swift

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,6 @@ extension Measurement : _ObjectiveCBridgeable {
227227
}
228228
}
229229

230-
/*
231-
FIXME(id-as-any): can't write this code because of:
232-
<rdar://problem/27539951> "unhandled generic bridged type" when bridging NSMeasurement
233-
234230
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
235231
extension NSMeasurement : _HasCustomAnyHashableRepresentation {
236232
// Must be @nonobjc to avoid infinite recursion during bridging.
@@ -239,7 +235,6 @@ extension NSMeasurement : _HasCustomAnyHashableRepresentation {
239235
return AnyHashable(self as Measurement)
240236
}
241237
}
242-
*/
243238

244239
// This workaround is required for the time being, because Swift doesn't support covariance for Measurement (26607639)
245240
@available(OSX 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)

test/1_stdlib/TestMeasurement.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,34 @@ class TestMeasurement : TestMeasurementSuper {
147147
expectTrue(fiveKM < sevenThousandM)
148148
expectTrue(fiveKM <= fiveThousandM)
149149
}
150+
151+
func test_AnyHashableContainingMeasurement() {
152+
let values: [Measurement<UnitLength>] = [
153+
Measurement(value: 100, unit: UnitLength.meters),
154+
Measurement(value: 100, unit: UnitLength.kilometers),
155+
Measurement(value: 100, unit: UnitLength.kilometers),
156+
]
157+
let anyHashables = values.map(AnyHashable.init)
158+
expectEqual(Measurement<UnitLength>.self, type(of: anyHashables[0].base))
159+
expectEqual(Measurement<UnitLength>.self, type(of: anyHashables[1].base))
160+
expectEqual(Measurement<UnitLength>.self, type(of: anyHashables[2].base))
161+
expectNotEqual(anyHashables[0], anyHashables[1])
162+
expectEqual(anyHashables[1], anyHashables[2])
163+
}
164+
165+
func test_AnyHashableCreatedFromNSMeasurement() {
166+
let values: [NSMeasurement] = [
167+
NSMeasurement(doubleValue: 100, unit: UnitLength.meters),
168+
NSMeasurement(doubleValue: 100, unit: UnitLength.kilometers),
169+
NSMeasurement(doubleValue: 100, unit: UnitLength.kilometers),
170+
]
171+
let anyHashables = values.map(AnyHashable.init)
172+
expectEqual(Measurement<Unit>.self, type(of: anyHashables[0].base))
173+
expectEqual(Measurement<Unit>.self, type(of: anyHashables[1].base))
174+
expectEqual(Measurement<Unit>.self, type(of: anyHashables[2].base))
175+
expectNotEqual(anyHashables[0], anyHashables[1])
176+
expectEqual(anyHashables[1], anyHashables[2])
177+
}
150178
}
151179

152180
#if !FOUNDATION_XCTEST
@@ -159,6 +187,8 @@ if #available(OSX 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *) {
159187
MeasurementTests.test("testMeasurementFormatter") { TestMeasurement().testMeasurementFormatter() }
160188
MeasurementTests.test("testEquality") { TestMeasurement().testEquality() }
161189
MeasurementTests.test("testComparison") { TestMeasurement().testComparison() }
190+
MeasurementTests.test("test_AnyHashableContainingMeasurement") { TestMeasurement().test_AnyHashableContainingMeasurement() }
191+
MeasurementTests.test("test_AnyHashableCreatedFromNSMeasurement") { TestMeasurement().test_AnyHashableCreatedFromNSMeasurement() }
162192
runAllTests()
163193
}
164194
#endif

test/ClangModules/objc_bridging_custom.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,18 @@ class TestObjCProtoImpl : NSObject, TestObjCProto {
211211
return nil
212212
}
213213
}
214+
215+
// Check explicit conversions for bridged generic types.
216+
// rdar://problem/27539951
217+
func testExplicitConversion(objc: APPManufacturerInfo<NSString>,
218+
swift: ManufacturerInfo<NSString>) {
219+
// Bridging to Swift
220+
let _ = objc as ManufacturerInfo<NSString>
221+
let _ = objc as ManufacturerInfo<NSNumber> // expected-error{{cannot convert value of type 'APPManufacturerInfo<NSString>' to type 'ManufacturerInfo<NSNumber>' in coercion}}
222+
let _ = objc as ManufacturerInfo<NSObject> // expected-error{{cannot convert value of type 'APPManufacturerInfo<NSString>' to type 'ManufacturerInfo<NSObject>' in coercion}}
223+
224+
// Bridging to Objective-C
225+
let _ = swift as APPManufacturerInfo<NSString>
226+
let _ = swift as APPManufacturerInfo<NSNumber> // expected-error{{cannot convert value of type 'ManufacturerInfo<NSString>' to type 'APPManufacturerInfo<NSNumber>' in coercion}}
227+
let _ = swift as APPManufacturerInfo<NSObject> // expected-error{{cannot convert value of type 'ManufacturerInfo<NSString>' to type 'APPManufacturerInfo<NSObject>' in coercion}}
228+
}

0 commit comments

Comments
 (0)