This is still going to be problematic. Any time you have a loop that modifies a container, the program will not type check without subtyping on union types, and even then will require finding the fixed point of the collection type. If there are multiple branches through the program it will have to merge the types from each possible branch into the fixed point calculation. Whether this type system would be sound is uncertain, so would require proof.
I am still not sure what problem you are trying to fix, as in I don’t really see how this union of all types in the collection is any better than a boxed trait. Yes you save having to define all the types that are a member of that “big” trait, and you can check the specific trait memberships on entry to functions, but I am not sure this is a big saving in boilerplate. I don’t think this is DRY, because you are not repeating this list of traits, but I will admit it is a form of boilerplate.
However the Rust approach is to explicitly write types and traits (it only has local type inference). Haskell can infer function types and traits/type-classes automatically. In Haskell if you write a function that uses “get_area” it knows to add the HasArea requirement to the inferred type signature of the function. Rust could do this too if they wanted (inferring trait bounds is a lot simpler than type inference) and only require annotation in the case of a trait function name abiguity. It seems to me Rusts decision to require function type signatures with traits results in far more boilerplate than listing the traits for a runtime polymorphic collection, so of you wanted to reduce boilerplate then that would be the first thing to change.
I think infact there is a simpler solution, and that is to allow new trait bounds to be added to traits, that would solve the expression “problem” (I don’t really think it’s much of a problem) in the same way without changing the type system.
extend Shape : HasHeight
This would have to be scope limited (say to the current module) but would force all types in Shape to also implement HasHeight, so all functions in this module can use the HasHeight trait functions on members of a collection of boxed shapes. This would achieve the same thing you want without introducing union types, or a global hash or anything like that.
The remaining problem is that we don’t know all the types that implement Shape, so we cannot check all the members of Shape implement Height, even though we could provide local impl of HasHeight for each type here in this module the compiler cannot know we have got them all, because some other module could put types in Shape the source of which is not available to the compiler. Maybe this could be checked at linktime depending on what the header information stored during separate compilation is. It might be worth finding this out as a next step. Finally the worst case is a runtime check, which I think would put most people off the idea.
What is missing in all of this are some good motivating examples. There needs to be some real programs you or other people are trying to write with Rust that have hit this problem and would benefit from a solution. I don’t see lots of questions in the forum about how the limitations of boxed traits is causing problems for developers. I think you might want to search to see if you can find evidence that this is a practical problem. If you can find that evidence, then I would suggest looking into the link-time information Rust used to see if a runtime check could be avoided. If both those conditions are met, then it might be worth writing an RFC to see how the Rust implementation community feel about this feature.