@@ -104,6 +104,69 @@ pub fn push_auto_trait_impls<I: Interner>(
104104 } ) ;
105105}
106106
107+ /// Leak auto traits for opaque types, just like `push_auto_trait_impls` does for structs.
108+ ///
109+ /// For example, given the following program:
110+ ///
111+ /// ```notrust
112+ /// #[auto] trait Send { }
113+ /// trait Trait { }
114+ /// struct Bar { }
115+ /// opaque type Foo: Trait = Bar
116+ /// ```
117+ /// Checking the goal `Foo: Send` would generate the following:
118+ ///
119+ /// ```notrust
120+ /// Foo: Send :- Bar: Send
121+ /// ```
122+ pub fn push_auto_trait_impls_opaque < I : Interner > (
123+ builder : & mut ClauseBuilder < ' _ , I > ,
124+ auto_trait_id : TraitId < I > ,
125+ opaque_id : OpaqueTyId < I > ,
126+ ) {
127+ debug_heading ! (
128+ "push_auto_trait_impls_opaque({:?}, {:?})" ,
129+ auto_trait_id,
130+ opaque_id
131+ ) ;
132+
133+ let opaque_ty_datum = & builder. db . opaque_ty_data ( opaque_id) ;
134+ let interner = builder. interner ( ) ;
135+
136+ // Must be an auto trait.
137+ assert ! ( builder. db. trait_datum( auto_trait_id) . is_auto_trait( ) ) ;
138+
139+ // Auto traits never have generic parameters of their own (apart from `Self`).
140+ assert_eq ! (
141+ builder. db. trait_datum( auto_trait_id) . binders. len( interner) ,
142+ 1
143+ ) ;
144+
145+ let binders = opaque_ty_datum. bound . map_ref ( |b| & b. hidden_ty ) ;
146+ builder. push_binders ( & binders, |builder, hidden_ty| {
147+ let self_ty: Ty < _ > = ApplicationTy {
148+ name : opaque_id. cast ( interner) ,
149+ substitution : builder. substitution_in_scope ( ) ,
150+ }
151+ . intern ( interner) ;
152+
153+ // trait_ref = `OpaqueType<...>: MyAutoTrait`
154+ let auto_trait_ref = TraitRef {
155+ trait_id : auto_trait_id,
156+ substitution : Substitution :: from1 ( interner, self_ty) ,
157+ } ;
158+
159+ // OpaqueType<...>: MyAutoTrait :- HiddenType: MyAutoTrait
160+ builder. push_clause (
161+ auto_trait_ref,
162+ std:: iter:: once ( TraitRef {
163+ trait_id : auto_trait_id,
164+ substitution : Substitution :: from1 ( interner, hidden_ty. clone ( ) ) ,
165+ } ) ,
166+ ) ;
167+ } ) ;
168+ }
169+
107170/// Given some goal `goal` that must be proven, along with
108171/// its `environment`, figures out the program clauses that apply
109172/// to this goal from the Rust program. So for example if the goal
@@ -161,7 +224,10 @@ fn program_clauses_that_could_match<I: Interner>(
161224
162225 if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
163226 let self_ty = trait_ref. self_type_parameter ( interner) ;
164- if self_ty. bound_var ( interner) . is_some ( )
227+
228+ if let TyData :: Alias ( AliasTy :: Opaque ( opaque_ty) ) = self_ty. data ( interner) {
229+ push_auto_trait_impls_opaque ( builder, trait_id, opaque_ty. opaque_ty_id )
230+ } else if self_ty. bound_var ( interner) . is_some ( )
165231 || self_ty. inference_var ( interner) . is_some ( )
166232 {
167233 return Err ( Floundered ) ;
0 commit comments