[ClangImporter] Generic parameters can be Hashable too! (#10900)

aa215e7e54 made sure we didn't try to construct Sets and Dictionaries
with a non-Hashable key. However, that commit was a little too
restrictive: there was no handling for imported generic parameters
that were constrained to inherit from NSObject. Fortunately,
recovering that information is fairly straightforward.

rdar://problem/33222646
diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp
index c195326..28771e7 100644
--- a/lib/ClangImporter/ImportType.cpp
+++ b/lib/ClangImporter/ImportType.cpp
@@ -2417,6 +2417,15 @@
   if (!NSObjectType)
     return false;
 
+  // Match generic parameters against their bounds.
+  if (auto *genericTy = type->getAs<GenericTypeParamType>()) {
+    if (auto *generic = genericTy->getDecl()) {
+      type = generic->getSuperclass();
+      if (!type)
+        return false;
+    }
+  }
+
   // Class type or existential that inherits from NSObject.
   if (NSObjectType->isExactSuperclassOf(type))
     return true;
diff --git a/test/ClangImporter/Inputs/custom-modules/ObjCBridgeNonconforming.h b/test/ClangImporter/Inputs/custom-modules/ObjCBridgeNonconforming.h
index e68e7b1..9f49a39 100644
--- a/test/ClangImporter/Inputs/custom-modules/ObjCBridgeNonconforming.h
+++ b/test/ClangImporter/Inputs/custom-modules/ObjCBridgeNonconforming.h
@@ -4,3 +4,26 @@
 @interface ObjCBridgeNonconforming
 @property NSSet<NSDictionary<NSString *, id> *> * _Nonnull foo;
 @end
+
+@interface ObjCBridgeGeneric<Element> : NSObject
+@property NSSet<Element> * _Nonnull foo;
+@end
+
+@interface ElementBase : NSObject
+@end
+@protocol ExtraElementProtocol
+@end
+@interface ElementConcrete : ElementBase <ExtraElementProtocol>
+@end
+
+@interface ObjCBridgeGenericConstrained<Element: ElementBase *> : NSObject
+@property NSSet<Element> * _Nonnull foo;
+@end
+
+@interface ObjCBridgeGenericInsufficientlyConstrained<Element: id <NSObject>> : NSObject
+@property NSSet<Element> * _Nonnull foo;
+@end
+
+@interface ObjCBridgeGenericConstrainedExtra<Element: NSObject <ExtraElementProtocol> *> : NSObject
+@property NSSet<Element> * _Nonnull foo;
+@end
diff --git a/test/ClangImporter/objc_bridging_generics.swift b/test/ClangImporter/objc_bridging_generics.swift
index 6e15c0d..6fee23f 100644
--- a/test/ClangImporter/objc_bridging_generics.swift
+++ b/test/ClangImporter/objc_bridging_generics.swift
@@ -398,3 +398,14 @@
 func testNonconforming(bnc: ObjCBridgeNonconforming) {
   let _: Int = bnc.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}}
 }
+
+func testHashableGenerics(
+    any: ObjCBridgeGeneric<ElementConcrete>,
+    constrained: ObjCBridgeGenericConstrained<ElementConcrete>,
+    insufficient: ObjCBridgeGenericInsufficientlyConstrained<ElementConcrete>,
+    extra: ObjCBridgeGenericConstrainedExtra<ElementConcrete>) {
+  let _: Int = any.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}}
+  let _: Int = constrained.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}}
+  let _: Int = insufficient.foo // expected-error{{cannot convert value of type 'Set<AnyHashable>' to specified type 'Int'}}
+  let _: Int = extra.foo // expected-error{{cannot convert value of type 'Set<ElementConcrete>' to specified type 'Int'}}
+}