6
6
use crate :: db:: HirDatabase ;
7
7
use crate :: generics:: { generics, Generics } ;
8
8
use crate :: {
9
- AliasTy , Const , ConstScalar , DynTyExt , FnPointer , GenericArg , GenericArgData , Interner ,
10
- Lifetime , LifetimeData , Ty , TyKind ,
9
+ AliasTy , Const , ConstScalar , DynTyExt , GenericArg , GenericArgData , Interner , Lifetime ,
10
+ LifetimeData , Ty , TyKind ,
11
11
} ;
12
12
use base_db:: ra_salsa:: Cycle ;
13
13
use chalk_ir:: Mutability ;
14
14
use hir_def:: data:: adt:: StructFlags ;
15
15
use hir_def:: { AdtId , GenericDefId , GenericParamId , VariantId } ;
16
16
use std:: fmt;
17
17
use std:: ops:: Not ;
18
+ use stdx:: never;
18
19
use triomphe:: Arc ;
19
20
20
21
pub ( crate ) fn variances_of ( db : & dyn HirDatabase , def : GenericDefId ) -> Option < Arc < [ Variance ] > > {
@@ -156,9 +157,19 @@ impl Variance {
156
157
( x, Variance :: Bivariant ) | ( Variance :: Bivariant , x) => x,
157
158
}
158
159
}
160
+
161
+ pub fn invariant ( self ) -> Self {
162
+ self . xform ( Variance :: Invariant )
163
+ }
164
+
165
+ pub fn covariant ( self ) -> Self {
166
+ self . xform ( Variance :: Covariant )
167
+ }
168
+
169
+ pub fn contravariant ( self ) -> Self {
170
+ self . xform ( Variance :: Contravariant )
171
+ }
159
172
}
160
- #[ derive( Copy , Clone , Debug ) ]
161
- struct InferredIndex ( usize ) ;
162
173
163
174
struct Context < ' db > {
164
175
db : & ' db dyn HirDatabase ,
@@ -193,12 +204,12 @@ impl Context<'_> {
193
204
}
194
205
GenericDefId :: FunctionId ( f) => {
195
206
let subst = self . generics . placeholder_subst ( self . db ) ;
196
- self . add_constraints_from_sig2 (
197
- & self
198
- . db
207
+ self . add_constraints_from_sig (
208
+ self . db
199
209
. callable_item_signature ( f. into ( ) )
200
210
. substitute ( Interner , & subst)
201
- . params_and_return ,
211
+ . params_and_return
212
+ . iter ( ) ,
202
213
Variance :: Covariant ,
203
214
) ;
204
215
}
@@ -216,41 +227,15 @@ impl Context<'_> {
216
227
217
228
// Functions are permitted to have unused generic parameters: make those invariant.
218
229
if let GenericDefId :: FunctionId ( _) = self . generics . def ( ) {
219
- for variance in & mut variances {
220
- if * variance == Variance :: Bivariant {
221
- * variance = Variance :: Invariant ;
222
- }
223
- }
230
+ variances
231
+ . iter_mut ( )
232
+ . filter ( |& & mut v| v == Variance :: Bivariant )
233
+ . for_each ( |v| * v = Variance :: Invariant ) ;
224
234
}
225
235
226
236
variances
227
237
}
228
238
229
- fn contravariant ( & mut self , variance : Variance ) -> Variance {
230
- variance. xform ( Variance :: Contravariant )
231
- }
232
-
233
- fn invariant ( & mut self , variance : Variance ) -> Variance {
234
- variance. xform ( Variance :: Invariant )
235
- }
236
-
237
- fn add_constraints_from_invariant_args ( & mut self , args : & [ GenericArg ] , variance : Variance ) {
238
- tracing:: debug!(
239
- "add_constraints_from_invariant_args(args={:?}, variance={:?})" ,
240
- args,
241
- variance
242
- ) ;
243
- let variance_i = self . invariant ( variance) ;
244
-
245
- for k in args {
246
- match k. data ( Interner ) {
247
- GenericArgData :: Lifetime ( lt) => self . add_constraints_from_region ( lt, variance_i) ,
248
- GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i) ,
249
- GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance_i) ,
250
- }
251
- }
252
- }
253
-
254
239
/// Adds constraints appropriate for an instance of `ty` appearing
255
240
/// in a context with the generics defined in `generics` and
256
241
/// ambient variance `variance`
@@ -260,39 +245,31 @@ impl Context<'_> {
260
245
TyKind :: Scalar ( _) | TyKind :: Never | TyKind :: Str | TyKind :: Foreign ( ..) => {
261
246
// leaf type -- noop
262
247
}
263
-
264
248
TyKind :: FnDef ( ..) | TyKind :: Coroutine ( ..) | TyKind :: Closure ( ..) => {
265
- panic ! ( "Unexpected unnameable type in variance computation: {ty :?}" ) ;
249
+ never ! ( "Unexpected unnameable type in variance computation: {:?}" , ty ) ;
266
250
}
267
-
268
251
TyKind :: Ref ( mutbl, lifetime, ty) => {
269
252
self . add_constraints_from_region ( lifetime, variance) ;
270
253
self . add_constraints_from_mt ( ty, * mutbl, variance) ;
271
254
}
272
-
273
255
TyKind :: Array ( typ, len) => {
274
256
self . add_constraints_from_const ( len, variance) ;
275
257
self . add_constraints_from_ty ( typ, variance) ;
276
258
}
277
-
278
259
TyKind :: Slice ( typ) => {
279
260
self . add_constraints_from_ty ( typ, variance) ;
280
261
}
281
-
282
262
TyKind :: Raw ( mutbl, ty) => {
283
263
self . add_constraints_from_mt ( ty, * mutbl, variance) ;
284
264
}
285
-
286
265
TyKind :: Tuple ( _, subtys) => {
287
266
for subty in subtys. type_parameters ( Interner ) {
288
267
self . add_constraints_from_ty ( & subty, variance) ;
289
268
}
290
269
}
291
-
292
270
TyKind :: Adt ( def, args) => {
293
271
self . add_constraints_from_args ( def. 0 . into ( ) , args. as_slice ( Interner ) , variance) ;
294
272
}
295
-
296
273
TyKind :: Alias ( AliasTy :: Opaque ( opaque) ) => {
297
274
self . add_constraints_from_invariant_args (
298
275
opaque. substitution . as_slice ( Interner ) ,
@@ -313,7 +290,6 @@ impl Context<'_> {
313
290
TyKind :: OpaqueType ( _, subst) => {
314
291
self . add_constraints_from_invariant_args ( subst. as_slice ( Interner ) , variance) ;
315
292
}
316
-
317
293
TyKind :: Dyn ( it) => {
318
294
// The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
319
295
self . add_constraints_from_region ( & it. lifetime , variance) ;
@@ -352,20 +328,33 @@ impl Context<'_> {
352
328
// Chalk has no params, so use placeholders for now?
353
329
TyKind :: Placeholder ( index) => {
354
330
let idx = crate :: from_placeholder_idx ( self . db , * index) ;
355
- let inferred = InferredIndex ( self . generics . type_or_const_param_idx ( idx) . unwrap ( ) ) ;
356
- self . constrain ( inferred , variance) ;
331
+ let index = self . generics . type_or_const_param_idx ( idx) . unwrap ( ) ;
332
+ self . constrain ( index , variance) ;
357
333
}
358
334
TyKind :: Function ( f) => {
359
- self . add_constraints_from_sig ( f, variance) ;
335
+ self . add_constraints_from_sig (
336
+ f. substitution . 0 . iter ( Interner ) . filter_map ( move |p| p. ty ( Interner ) ) ,
337
+ variance,
338
+ ) ;
360
339
}
361
-
362
340
TyKind :: Error => {
363
341
// we encounter this when walking the trait references for object
364
342
// types, where we use Error as the Self type
365
343
}
366
-
367
344
TyKind :: CoroutineWitness ( ..) | TyKind :: BoundVar ( ..) | TyKind :: InferenceVar ( ..) => {
368
- panic ! ( "unexpected type encountered in variance inference: {:?}" , ty) ;
345
+ never ! ( "unexpected type encountered in variance inference: {:?}" , ty)
346
+ }
347
+ }
348
+ }
349
+
350
+ fn add_constraints_from_invariant_args ( & mut self , args : & [ GenericArg ] , variance : Variance ) {
351
+ let variance_i = variance. invariant ( ) ;
352
+
353
+ for k in args {
354
+ match k. data ( Interner ) {
355
+ GenericArgData :: Lifetime ( lt) => self . add_constraints_from_region ( lt, variance_i) ,
356
+ GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i) ,
357
+ GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance_i) ,
369
358
}
370
359
}
371
360
}
@@ -378,27 +367,19 @@ impl Context<'_> {
378
367
args : & [ GenericArg ] ,
379
368
variance : Variance ,
380
369
) {
381
- tracing:: debug!(
382
- "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})" ,
383
- def_id,
384
- args,
385
- variance
386
- ) ;
387
-
388
370
// We don't record `inferred_starts` entries for empty generics.
389
371
if args. is_empty ( ) {
390
372
return ;
391
373
}
392
374
if def_id == self . generics . def ( ) {
393
375
// HACK: Workaround for the trivial cycle salsa case (see
394
376
// recursive_one_bivariant_more_non_bivariant_params test)
395
- let variance_i = variance. xform ( Variance :: Bivariant ) ;
396
377
for k in args {
397
378
match k. data ( Interner ) {
398
379
GenericArgData :: Lifetime ( lt) => {
399
- self . add_constraints_from_region ( lt, variance_i )
380
+ self . add_constraints_from_region ( lt, Variance :: Bivariant )
400
381
}
401
- GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i ) ,
382
+ GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, Variance :: Bivariant ) ,
402
383
GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance) ,
403
384
}
404
385
}
@@ -408,12 +389,13 @@ impl Context<'_> {
408
389
} ;
409
390
410
391
for ( i, k) in args. iter ( ) . enumerate ( ) {
411
- let variance_i = variance. xform ( variances[ i] ) ;
412
392
match k. data ( Interner ) {
413
393
GenericArgData :: Lifetime ( lt) => {
414
- self . add_constraints_from_region ( lt, variance_i)
394
+ self . add_constraints_from_region ( lt, variance. xform ( variances[ i] ) )
395
+ }
396
+ GenericArgData :: Ty ( ty) => {
397
+ self . add_constraints_from_ty ( ty, variance. xform ( variances[ i] ) )
415
398
}
416
- GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i) ,
417
399
GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance) ,
418
400
}
419
401
}
@@ -435,20 +417,17 @@ impl Context<'_> {
435
417
436
418
/// Adds constraints appropriate for a function with signature
437
419
/// `sig` appearing in a context with ambient variance `variance`
438
- fn add_constraints_from_sig ( & mut self , sig : & FnPointer , variance : Variance ) {
439
- let contra = self . contravariant ( variance) ;
440
- let mut tys = sig. substitution . 0 . iter ( Interner ) . filter_map ( move |p| p. ty ( Interner ) ) ;
441
- self . add_constraints_from_ty ( tys. next_back ( ) . unwrap ( ) , variance) ;
442
- for input in tys {
443
- self . add_constraints_from_ty ( input, contra) ;
444
- }
445
- }
446
-
447
- fn add_constraints_from_sig2 ( & mut self , sig : & [ Ty ] , variance : Variance ) {
448
- let contra = self . contravariant ( variance) ;
449
- let mut tys = sig. iter ( ) ;
450
- self . add_constraints_from_ty ( tys. next_back ( ) . unwrap ( ) , variance) ;
451
- for input in tys {
420
+ fn add_constraints_from_sig < ' a > (
421
+ & mut self ,
422
+ mut sig_tys : impl DoubleEndedIterator < Item = & ' a Ty > ,
423
+ variance : Variance ,
424
+ ) {
425
+ let contra = variance. contravariant ( ) ;
426
+ let Some ( output) = sig_tys. next_back ( ) else {
427
+ return never ! ( "function signature has no return type" ) ;
428
+ } ;
429
+ self . add_constraints_from_ty ( output, variance) ;
430
+ for input in sig_tys {
452
431
self . add_constraints_from_ty ( input, contra) ;
453
432
}
454
433
}
@@ -462,27 +441,23 @@ impl Context<'_> {
462
441
variance
463
442
) ;
464
443
match region. data ( Interner ) {
465
- // FIXME: chalk has no params?
466
444
LifetimeData :: Placeholder ( index) => {
467
445
let idx = crate :: lt_from_placeholder_idx ( self . db , * index) ;
468
- let inferred = InferredIndex ( self . generics . lifetime_idx ( idx) . unwrap ( ) ) ;
446
+ let inferred = self . generics . lifetime_idx ( idx) . unwrap ( ) ;
469
447
self . constrain ( inferred, variance) ;
470
448
}
471
449
LifetimeData :: Static => { }
472
-
473
450
LifetimeData :: BoundVar ( ..) => {
474
451
// Either a higher-ranked region inside of a type or a
475
452
// late-bound function parameter.
476
453
//
477
454
// We do not compute constraints for either of these.
478
455
}
479
-
480
456
LifetimeData :: Error => { }
481
-
482
457
LifetimeData :: Phantom ( ..) | LifetimeData :: InferenceVar ( ..) | LifetimeData :: Erased => {
483
458
// We don't expect to see anything but 'static or bound
484
459
// regions when visiting member types or method types.
485
- panic ! (
460
+ never ! (
486
461
"unexpected region encountered in variance \
487
462
inference: {:?}",
488
463
region
@@ -494,26 +469,23 @@ impl Context<'_> {
494
469
/// Adds constraints appropriate for a mutability-type pair
495
470
/// appearing in a context with ambient variance `variance`
496
471
fn add_constraints_from_mt ( & mut self , ty : & Ty , mt : Mutability , variance : Variance ) {
497
- match mt {
498
- Mutability :: Mut => {
499
- let invar = self . invariant ( variance) ;
500
- self . add_constraints_from_ty ( ty, invar) ;
501
- }
502
-
503
- Mutability :: Not => {
504
- self . add_constraints_from_ty ( ty, variance) ;
505
- }
506
- }
472
+ self . add_constraints_from_ty (
473
+ ty,
474
+ match mt {
475
+ Mutability :: Mut => variance. invariant ( ) ,
476
+ Mutability :: Not => variance,
477
+ } ,
478
+ ) ;
507
479
}
508
480
509
- fn constrain ( & mut self , inferred : InferredIndex , variance : Variance ) {
481
+ fn constrain ( & mut self , index : usize , variance : Variance ) {
510
482
tracing:: debug!(
511
483
"constrain(index={:?}, variance={:?}, to={:?})" ,
512
- inferred ,
513
- self . variances[ inferred . 0 ] ,
484
+ index ,
485
+ self . variances[ index ] ,
514
486
variance
515
487
) ;
516
- self . variances [ inferred . 0 ] = self . variances [ inferred . 0 ] . glb ( variance) ;
488
+ self . variances [ index ] = self . variances [ index ] . glb ( variance) ;
517
489
}
518
490
}
519
491
@@ -967,6 +939,22 @@ fn bar<'min,'max>(v: SomeStruct<&'min ()>)
967
939
) ;
968
940
}
969
941
942
+ #[ test]
943
+ fn invalid_arg_counts ( ) {
944
+ check (
945
+ r#"
946
+ struct S<T>(T);
947
+ struct S2<T>(S<>);
948
+ struct S3<T>(S<T, T>);
949
+ "# ,
950
+ expect ! [ [ r#"
951
+ S[T: covariant]
952
+ S2[T: bivariant]
953
+ S3[T: covariant]
954
+ "# ] ] ,
955
+ ) ;
956
+ }
957
+
970
958
#[ test]
971
959
fn recursive_one_bivariant_more_non_bivariant_params ( ) {
972
960
// FIXME: This is wrong, this should be `BivariantPartialIndirect[T: bivariant, U: covariant]` (likewise for Wrapper)
0 commit comments