@@ -104,6 +104,69 @@ pub fn push_auto_trait_impls<I: Interner>(
104
104
} ) ;
105
105
}
106
106
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
+
107
170
/// Given some goal `goal` that must be proven, along with
108
171
/// its `environment`, figures out the program clauses that apply
109
172
/// 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>(
161
224
162
225
if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
163
226
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 ( )
165
231
|| self_ty. inference_var ( interner) . is_some ( )
166
232
{
167
233
return Err ( Floundered ) ;
0 commit comments