Details
-
Task
-
Status: Resolved
-
Normal
-
Resolution: Fixed
-
None
-
None
-
None
-
Needs Assessment
Description
When a user calls the Puppet functions `map`, `each`, etc. we create a Puppet Iterator and proxy requests through it to the wrapped Ruby object. When creating a Puppet Iterator in this way we recursively infer the type of the entire collection passed in.
Some times these Iterators are directly exposed to users (via the non-block arities of `reverse_each` and `step`). Unfortunately, where we expose Iterators they may use all of Puppet's type system and may be specialized like "Iterator[String]" or "Iterator[Variant[Hash[String,String],Undef]]". Consequently, to be backwards compatible we will need to recursively check the type for these invocations. (Maybe we can deprecate and remove them in Puppet 7??)
In every other case the Iterator is not exposed to the user. Either the original collection, a new, modified collection, or elements of one of the afore mentioned collections is returned.
The method invoked in Puppet functions to create the Iterators is `Iterable.asserted_iterable`, and as far as I can tell, it does additional type checking that the dispatcher doesn't do and then largely discards the computed type information. We should should probably keep the call to asserted_iterable (assuming the additional type checking is a good thing to do there), but make it non-recursive where possible.
Note, `asserted_iterable` defers to `Iterable.on` to do a lot of this work, `Iterable.on` is used by other aspects of the type system so we might want to keep existing calls to `Iterable.on` backwards compatible with those invocations. (We might also want to look into whether or not those calls are unnecessarily doing recursive type inference.)