If a flatmap value has a count of 1 and no other attributes, it usually
indicates the equivalent configuration of an empty (or default value)
set block. Treat this as containing a single zero value object and
insert that into the set.
The flatmap shim was lazily adding duplicate items and letting cty.Set
clear them out, but if those duplicates contains unknown values they
can't be checked for equality and will end up remaining in the set.
When creating a flatmap from a cty.Value, there may be Null collections
which don't need to be added to the flatmap at all. Skip over these to
avoid panicking in ElementIterator with a Null value.
A nil flatmap will be encoded as a NullVal of the correct type. When
Converting a NullVal back to a flatmap, return nil immediately rather
than attempting to build the values.
Previously unknown values were round-tripping through flatmap and coming
out as known strings containing the UnknownVariableValue. (The classic bug
that, ironically, was one of the big reasons to write cty!)
Now we properly handle unknown values in both directions: going in to
flatmap we write UnknownVariableValue at the appropriate key (as the count
for sequences or maps) and then coming out of flatmap we turn
UnknownVariableValue back into a cty unknown value of the requested type.
These particular shims will have a pretty limited lifetime in mainline
Terraform code (primarily to stub out the new expression evaluator against
the old state structs until the new format is implemented) but will live
on for some time in state migration and provider plugin compatibility
shims.