66use crate :: db:: HirDatabase ;
77use crate :: generics:: { generics, Generics } ;
88use 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 ,
1111} ;
1212use base_db:: ra_salsa:: Cycle ;
1313use chalk_ir:: Mutability ;
1414use hir_def:: data:: adt:: StructFlags ;
1515use hir_def:: { AdtId , GenericDefId , GenericParamId , VariantId } ;
1616use std:: fmt;
1717use std:: ops:: Not ;
18+ use stdx:: never;
1819use triomphe:: Arc ;
1920
2021pub ( crate ) fn variances_of ( db : & dyn HirDatabase , def : GenericDefId ) -> Option < Arc < [ Variance ] > > {
@@ -156,9 +157,19 @@ impl Variance {
156157 ( x, Variance :: Bivariant ) | ( Variance :: Bivariant , x) => x,
157158 }
158159 }
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+ }
159172}
160- #[ derive( Copy , Clone , Debug ) ]
161- struct InferredIndex ( usize ) ;
162173
163174struct Context < ' db > {
164175 db : & ' db dyn HirDatabase ,
@@ -193,12 +204,12 @@ impl Context<'_> {
193204 }
194205 GenericDefId :: FunctionId ( f) => {
195206 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
199209 . callable_item_signature ( f. into ( ) )
200210 . substitute ( Interner , & subst)
201- . params_and_return ,
211+ . params_and_return
212+ . iter ( ) ,
202213 Variance :: Covariant ,
203214 ) ;
204215 }
@@ -216,41 +227,15 @@ impl Context<'_> {
216227
217228 // Functions are permitted to have unused generic parameters: make those invariant.
218229 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 ) ;
224234 }
225235
226236 variances
227237 }
228238
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-
254239 /// Adds constraints appropriate for an instance of `ty` appearing
255240 /// in a context with the generics defined in `generics` and
256241 /// ambient variance `variance`
@@ -260,39 +245,31 @@ impl Context<'_> {
260245 TyKind :: Scalar ( _) | TyKind :: Never | TyKind :: Str | TyKind :: Foreign ( ..) => {
261246 // leaf type -- noop
262247 }
263-
264248 TyKind :: FnDef ( ..) | TyKind :: Coroutine ( ..) | TyKind :: Closure ( ..) => {
265- panic ! ( "Unexpected unnameable type in variance computation: {ty :?}" ) ;
249+ never ! ( "Unexpected unnameable type in variance computation: {:?}" , ty ) ;
266250 }
267-
268251 TyKind :: Ref ( mutbl, lifetime, ty) => {
269252 self . add_constraints_from_region ( lifetime, variance) ;
270253 self . add_constraints_from_mt ( ty, * mutbl, variance) ;
271254 }
272-
273255 TyKind :: Array ( typ, len) => {
274256 self . add_constraints_from_const ( len, variance) ;
275257 self . add_constraints_from_ty ( typ, variance) ;
276258 }
277-
278259 TyKind :: Slice ( typ) => {
279260 self . add_constraints_from_ty ( typ, variance) ;
280261 }
281-
282262 TyKind :: Raw ( mutbl, ty) => {
283263 self . add_constraints_from_mt ( ty, * mutbl, variance) ;
284264 }
285-
286265 TyKind :: Tuple ( _, subtys) => {
287266 for subty in subtys. type_parameters ( Interner ) {
288267 self . add_constraints_from_ty ( & subty, variance) ;
289268 }
290269 }
291-
292270 TyKind :: Adt ( def, args) => {
293271 self . add_constraints_from_args ( def. 0 . into ( ) , args. as_slice ( Interner ) , variance) ;
294272 }
295-
296273 TyKind :: Alias ( AliasTy :: Opaque ( opaque) ) => {
297274 self . add_constraints_from_invariant_args (
298275 opaque. substitution . as_slice ( Interner ) ,
@@ -313,7 +290,6 @@ impl Context<'_> {
313290 TyKind :: OpaqueType ( _, subst) => {
314291 self . add_constraints_from_invariant_args ( subst. as_slice ( Interner ) , variance) ;
315292 }
316-
317293 TyKind :: Dyn ( it) => {
318294 // The type `dyn Trait<T> +'a` is covariant w/r/t `'a`:
319295 self . add_constraints_from_region ( & it. lifetime , variance) ;
@@ -352,20 +328,33 @@ impl Context<'_> {
352328 // Chalk has no params, so use placeholders for now?
353329 TyKind :: Placeholder ( index) => {
354330 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) ;
357333 }
358334 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+ ) ;
360339 }
361-
362340 TyKind :: Error => {
363341 // we encounter this when walking the trait references for object
364342 // types, where we use Error as the Self type
365343 }
366-
367344 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) ,
369358 }
370359 }
371360 }
@@ -378,27 +367,19 @@ impl Context<'_> {
378367 args : & [ GenericArg ] ,
379368 variance : Variance ,
380369 ) {
381- tracing:: debug!(
382- "add_constraints_from_args(def_id={:?}, args={:?}, variance={:?})" ,
383- def_id,
384- args,
385- variance
386- ) ;
387-
388370 // We don't record `inferred_starts` entries for empty generics.
389371 if args. is_empty ( ) {
390372 return ;
391373 }
392374 if def_id == self . generics . def ( ) {
393375 // HACK: Workaround for the trivial cycle salsa case (see
394376 // recursive_one_bivariant_more_non_bivariant_params test)
395- let variance_i = variance. xform ( Variance :: Bivariant ) ;
396377 for k in args {
397378 match k. data ( Interner ) {
398379 GenericArgData :: Lifetime ( lt) => {
399- self . add_constraints_from_region ( lt, variance_i )
380+ self . add_constraints_from_region ( lt, Variance :: Bivariant )
400381 }
401- GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i ) ,
382+ GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, Variance :: Bivariant ) ,
402383 GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance) ,
403384 }
404385 }
@@ -408,12 +389,13 @@ impl Context<'_> {
408389 } ;
409390
410391 for ( i, k) in args. iter ( ) . enumerate ( ) {
411- let variance_i = variance. xform ( variances[ i] ) ;
412392 match k. data ( Interner ) {
413393 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] ) )
415398 }
416- GenericArgData :: Ty ( ty) => self . add_constraints_from_ty ( ty, variance_i) ,
417399 GenericArgData :: Const ( val) => self . add_constraints_from_const ( val, variance) ,
418400 }
419401 }
@@ -435,20 +417,17 @@ impl Context<'_> {
435417
436418 /// Adds constraints appropriate for a function with signature
437419 /// `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 {
452431 self . add_constraints_from_ty ( input, contra) ;
453432 }
454433 }
@@ -462,27 +441,23 @@ impl Context<'_> {
462441 variance
463442 ) ;
464443 match region. data ( Interner ) {
465- // FIXME: chalk has no params?
466444 LifetimeData :: Placeholder ( index) => {
467445 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 ( ) ;
469447 self . constrain ( inferred, variance) ;
470448 }
471449 LifetimeData :: Static => { }
472-
473450 LifetimeData :: BoundVar ( ..) => {
474451 // Either a higher-ranked region inside of a type or a
475452 // late-bound function parameter.
476453 //
477454 // We do not compute constraints for either of these.
478455 }
479-
480456 LifetimeData :: Error => { }
481-
482457 LifetimeData :: Phantom ( ..) | LifetimeData :: InferenceVar ( ..) | LifetimeData :: Erased => {
483458 // We don't expect to see anything but 'static or bound
484459 // regions when visiting member types or method types.
485- panic ! (
460+ never ! (
486461 "unexpected region encountered in variance \
487462 inference: {:?}",
488463 region
@@ -494,26 +469,23 @@ impl Context<'_> {
494469 /// Adds constraints appropriate for a mutability-type pair
495470 /// appearing in a context with ambient variance `variance`
496471 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+ ) ;
507479 }
508480
509- fn constrain ( & mut self , inferred : InferredIndex , variance : Variance ) {
481+ fn constrain ( & mut self , index : usize , variance : Variance ) {
510482 tracing:: debug!(
511483 "constrain(index={:?}, variance={:?}, to={:?})" ,
512- inferred ,
513- self . variances[ inferred . 0 ] ,
484+ index ,
485+ self . variances[ index ] ,
514486 variance
515487 ) ;
516- self . variances [ inferred . 0 ] = self . variances [ inferred . 0 ] . glb ( variance) ;
488+ self . variances [ index ] = self . variances [ index ] . glb ( variance) ;
517489 }
518490}
519491
@@ -967,6 +939,22 @@ fn bar<'min,'max>(v: SomeStruct<&'min ()>)
967939 ) ;
968940 }
969941
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+
970958 #[ test]
971959 fn recursive_one_bivariant_more_non_bivariant_params ( ) {
972960 // FIXME: This is wrong, this should be `BivariantPartialIndirect[T: bivariant, U: covariant]` (likewise for Wrapper)
0 commit comments