@@ -47,9 +47,8 @@ class ObjectValueProvider(
4747 description : FuzzedDescription ,
4848 type : FuzzedType
4949 ) = sequence {
50- val classId = type.classId
51- findAccessibleCreators(description, classId).forEach { creatorExecutableId ->
52- yield (createValue(classId, creatorExecutableId, description))
50+ findAccessibleCreators(description, type).forEach { creatorExecutableId ->
51+ yield (createValue(type.classId, creatorExecutableId, description))
5352 }
5453 }
5554
@@ -164,7 +163,8 @@ class AbstractsObjectValueProvider(
164163 }
165164 val jClass = sc.id.jClass
166165 return isAccessible(jClass, description.description.packageName) &&
167- findAccessibleCreators(description, jClass.id).any()
166+ findAccessibleCreators(description, toFuzzerType(jClass, description.typeCache)).any() &&
167+ jClass.let { toFuzzerType(it, description.typeCache).isDefinitelySubtypeOf(description, type) }
168168 } catch (ignore: Throwable ) {
169169 return false
170170 }
@@ -186,12 +186,27 @@ class AbstractsObjectValueProvider(
186186 }
187187}
188188
189- private fun findAccessibleCreators (description : FuzzedDescription , classId : ClassId ): Sequence <ExecutableId > =
190- (classId.allConstructors + (classId.jClass.methods
191- .filter { it.isStatic && it.returnType.id.isSubtypeOf(classId) }
192- .map { it.executableId })
189+ private fun findAccessibleCreators (
190+ description : FuzzedDescription ,
191+ neededType : FuzzedType
192+ ): Sequence <ExecutableId > =
193+ (neededType.classId.allConstructors + (neededType.classId.jClass.methods
194+ .filter {
195+ it.isStatic && toFuzzerType(it.genericReturnType, description.typeCache)
196+ .isDefinitelySubtypeOf(description, neededType)
197+ }
198+ .map { it.executableId })
193199 ).filter { isAccessible(it.executable, description.description.packageName) }
194200
201+ /* *
202+ * NOTE: this function takes conservative when generics are involved.
203+ *
204+ * For example, `false` may be returned when [this] is `List<T>` or `ArrayList<T>` while [other] is `List<String>`.
205+ */
206+ // TODO should be reworked with accurate generic matching
207+ private fun FuzzedType.isDefinitelySubtypeOf (description : FuzzedDescription , other : FuzzedType ): Boolean =
208+ classId.isSubtypeOf(other.classId) && traverseHierarchy(description.typeCache).contains(other)
209+
195210internal class PublicSetterGetter (
196211 val setter : Method ,
197212 val getter : Method ,
0 commit comments