@@ -2971,7 +2971,28 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
2971
2971
tcx. mk_dynamic ( existential_predicates, region_b) ;
2972
2972
2973
2973
if tcx. features ( ) . trait_upcasting {
2974
- // Register obligations for `dyn TraitA1 [TraitA2...]: TraitB1 [TraitB2...]`.
2974
+ // Given that we are upcasting `dyn (TraitA1 + ... + TraitAn)` to
2975
+ // `dyn (TraitB1 + ... + TraitBn)`, register proof obligations like
2976
+ //
2977
+ // dyn (TraitA1 + ... + TraitAn): TraitB1
2978
+ // ...
2979
+ // dyn (TraitA1 + ... + TraitAn): TraitBn
2980
+ //
2981
+ // So, if for example we are upcasting `dyn (Foo + Send)` to `dyn (Bar + Send)`,
2982
+ // then we would check that `dyn (Foo + Send): Bar` and `dyn (Foo + Send): Send`
2983
+ // -- or at least we would, were it not for the slight pre-filter hack.
2984
+ //
2985
+ // The pre-filter hack removes cases where `TraitBi` is an auto-trait like
2986
+ // `Send`, so long as we see that auto-trait in the A type. In our example, this
2987
+ // would skip the dyn (Foo + Send): Send obligation. There are two reasons for
2988
+ // this. The first is efficiency -- this case trivially holds. The second is
2989
+ // because we would otherwise encounter ambiguity errors during bootstrap, owing
2990
+ // to the `rustc_datastructures::sync::Send` trait (which is not the same as the
2991
+ // standard `Send` trait). This trait has a `impl<T: ?Sized> Send for T` impl,
2992
+ // and thus we get an error when trying to choose between this impl versus and
2993
+ // the automatic impl that we prove from `dyn Traits`. This ambiguity is silly
2994
+ // (it doesn't matter which one we choose), but rather than resolve that in the
2995
+ // general case (which is subtle), we can screen it out here easily enough.
2975
2996
nested. extend (
2976
2997
data_b. iter ( )
2977
2998
// HACK(alexreg | nikomatsakis): we handle auto traits specially here
0 commit comments