Infinite loop in createInstance() caused by Copy Constructors #99
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Create instance (as invoked by the any() matcher) loops infinitely if any of the parameters of the "easiest constructor" are the same type as the class we are trying to construct (as one might expect from a copy constructor). This can be triggered by creating a primary constructor with more than one non-array parameters and a copy constructor (containing only a single parameter). Create instance will treat the copy constructor as the easiest one and try to use it. However, this will cause create instance to be called again on the same class with the same result. This would also apply to any constructor that takes in an object of its same type (not just copy constructors). Let's call these self-referential constructors.
The simplest fix (included here) is to remove all self-referential constructors from the set of easiest constructors. I believe this is sound because there must be at least one non-self-referential constructor in order to get the initial object to copy and create instance still works when all constructors are private (implying there must be at least one constructor it can call).
One additional note from looking through this code. The easiest constructor is always determined by the number of parameters plus some additional filters. However, if all parameters have a default value, wouldn't that be the easiest constructor to use? This isn't addressed in this code. The goals of this may be better served if you could sort by the number of non-optional parameters. It is easy enough to do, but I wanted to make sure I understood the objective of the method before making the change.