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