@@ -102,6 +102,8 @@ pub fn push_auto_trait_impls<I: Interner>(
102
102
} ) ;
103
103
}
104
104
105
+ // TODO add Floundered error instead of using Option
106
+
105
107
/// Given some goal `goal` that must be proven, along with
106
108
/// its `environment`, figures out the program clauses that apply
107
109
/// to this goal from the Rust program. So for example if the goal
@@ -111,7 +113,7 @@ pub(crate) fn program_clauses_for_goal<'db, I: Interner>(
111
113
db : & ' db dyn RustIrDatabase < I > ,
112
114
environment : & Environment < I > ,
113
115
goal : & DomainGoal < I > ,
114
- ) -> Vec < ProgramClause < I > > {
116
+ ) -> Option < Vec < ProgramClause < I > > > {
115
117
debug_heading ! (
116
118
"program_clauses_for_goal(goal={:?}, environment={:?})" ,
117
119
goal,
@@ -121,13 +123,13 @@ pub(crate) fn program_clauses_for_goal<'db, I: Interner>(
121
123
122
124
let mut vec = vec ! [ ] ;
123
125
vec. extend ( db. custom_clauses ( ) ) ;
124
- program_clauses_that_could_match ( db, environment, goal, & mut vec) ;
126
+ program_clauses_that_could_match ( db, environment, goal, & mut vec) ? ;
125
127
program_clauses_for_env ( db, environment, & mut vec) ;
126
128
vec. retain ( |c| c. could_match ( interner, goal) ) ;
127
129
128
130
debug ! ( "vec = {:#?}" , vec) ;
129
131
130
- vec
132
+ Some ( vec)
131
133
}
132
134
133
135
/// Returns a set of program clauses that could possibly match
@@ -139,17 +141,26 @@ fn program_clauses_that_could_match<I: Interner>(
139
141
environment : & Environment < I > ,
140
142
goal : & DomainGoal < I > ,
141
143
clauses : & mut Vec < ProgramClause < I > > ,
142
- ) {
144
+ ) -> Option < ( ) > {
143
145
let interner = db. interner ( ) ;
144
146
let builder = & mut ClauseBuilder :: new ( db, clauses) ;
145
147
146
148
match goal {
147
149
DomainGoal :: Holds ( WhereClause :: Implemented ( trait_ref) ) => {
148
150
let trait_id = trait_ref. trait_id ;
149
151
152
+ let trait_datum = db. trait_datum ( trait_id) ;
153
+
154
+ if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
155
+ let self_ty = trait_ref. self_type_parameter ( interner) ;
156
+ if self_ty. bound ( interner) . is_some ( ) || self_ty. inference_var ( interner) . is_some ( ) {
157
+ return None ;
158
+ }
159
+ }
160
+
150
161
// This is needed for the coherence related impls, as well
151
162
// as for the `Implemented(Foo) :- FromEnv(Foo)` rule.
152
- db . trait_datum ( trait_id ) . to_program_clauses ( builder) ;
163
+ trait_datum. to_program_clauses ( builder) ;
153
164
154
165
for impl_id in db. impls_for_trait (
155
166
trait_ref. trait_id ,
@@ -168,8 +179,8 @@ fn program_clauses_that_could_match<I: Interner>(
168
179
push_auto_trait_impls ( builder, trait_id, struct_id) ;
169
180
}
170
181
}
171
- TyData :: InferenceVar ( _) => {
172
- panic ! ( "auto-traits should flounder if nothing is known" )
182
+ TyData :: InferenceVar ( _) | TyData :: BoundVar ( _ ) => {
183
+ return None ;
173
184
}
174
185
_ => { }
175
186
}
@@ -262,12 +273,12 @@ fn program_clauses_that_could_match<I: Interner>(
262
273
}
263
274
DomainGoal :: WellFormed ( WellFormed :: Ty ( ty) )
264
275
| DomainGoal :: IsUpstream ( ty)
265
- | DomainGoal :: DownstreamType ( ty) => match_ty ( builder, environment, ty) ,
276
+ | DomainGoal :: DownstreamType ( ty) => match_ty ( builder, environment, ty) ? ,
266
277
DomainGoal :: IsFullyVisible ( ty) | DomainGoal :: IsLocal ( ty) => {
267
- match_ty ( builder, environment, ty)
278
+ match_ty ( builder, environment, ty) ?
268
279
}
269
280
DomainGoal :: FromEnv ( _) => ( ) , // Computed in the environment
270
- DomainGoal :: Normalize ( Normalize { alias, ty : _ } ) => {
281
+ DomainGoal :: Normalize ( Normalize { alias, ty } ) => {
271
282
// Normalize goals derive from `AssociatedTyValue` datums,
272
283
// which are found in impls. That is, if we are
273
284
// normalizing (e.g.) `<T as Iterator>::Item>`, then
@@ -282,6 +293,26 @@ fn program_clauses_that_could_match<I: Interner>(
282
293
let associated_ty_datum = db. associated_ty_data ( alias. associated_ty_id ) ;
283
294
let trait_id = associated_ty_datum. trait_id ;
284
295
let trait_parameters = db. trait_parameters_from_projection ( alias) ;
296
+
297
+ if let TyData :: Apply ( ApplicationTy {
298
+ name : TypeName :: AssociatedType ( _) ,
299
+ ..
300
+ } ) = ty. data ( interner)
301
+ {
302
+ // TODO this is probably wrong
303
+ // Associated types will never *normalize* to an associated type placeholder.
304
+ // It's important that we return early here so that we don't flounder in this case.
305
+ return Some ( ( ) ) ;
306
+ }
307
+
308
+ let trait_datum = builder. db . trait_datum ( trait_id) ;
309
+ if trait_datum. is_non_enumerable_trait ( ) || trait_datum. is_auto_trait ( ) {
310
+ let self_ty = alias. self_type_parameter ( interner) ;
311
+ if self_ty. bound ( interner) . is_some ( ) || self_ty. inference_var ( interner) . is_some ( ) {
312
+ return None ;
313
+ }
314
+ }
315
+
285
316
push_program_clauses_for_associated_type_values_in_impls_of (
286
317
builder,
287
318
trait_id,
@@ -293,6 +324,8 @@ fn program_clauses_that_could_match<I: Interner>(
293
324
. to_program_clauses ( builder) ,
294
325
DomainGoal :: Compatible ( ( ) ) => ( ) ,
295
326
} ;
327
+
328
+ Some ( ( ) )
296
329
}
297
330
298
331
/// Generate program clauses from the associated-type values
@@ -353,9 +386,9 @@ fn match_ty<I: Interner>(
353
386
builder : & mut ClauseBuilder < ' _ , I > ,
354
387
environment : & Environment < I > ,
355
388
ty : & Ty < I > ,
356
- ) {
389
+ ) -> Option < ( ) > {
357
390
let interner = builder. interner ( ) ;
358
- match ty. data ( interner) {
391
+ Some ( match ty. data ( interner) {
359
392
TyData :: Apply ( application_ty) => match_type_name ( builder, application_ty. name ) ,
360
393
TyData :: Placeholder ( _) => {
361
394
builder. push_clause ( WellFormed :: Ty ( ty. clone ( ) ) , Some ( FromEnv :: Ty ( ty. clone ( ) ) ) ) ;
@@ -370,12 +403,12 @@ fn match_ty<I: Interner>(
370
403
. substitution
371
404
. iter ( interner)
372
405
. map ( |p| p. assert_ty_ref ( interner) )
373
- . for_each ( |ty| match_ty ( builder, environment, & ty) )
406
+ . map ( |ty| match_ty ( builder, environment, & ty) )
407
+ . collect :: < Option < _ > > ( ) ?;
374
408
}
375
- TyData :: BoundVar ( _) => { }
376
- TyData :: InferenceVar ( _) => panic ! ( "should have floundered" ) ,
409
+ TyData :: BoundVar ( _) | TyData :: InferenceVar ( _) => return None ,
377
410
TyData :: Dyn ( _) => { }
378
- }
411
+ } )
379
412
}
380
413
381
414
fn match_type_name < I : Interner > ( builder : & mut ClauseBuilder < ' _ , I > , name : TypeName < I > ) {
0 commit comments