|
2 | 2 | //! chapter for more info. |
3 | 3 | //! |
4 | 4 | //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/variance.html |
| 5 | +//! |
| 6 | +//! The implementation here differs from rustc. Rustc does a crate wide fixpoint resolution |
| 7 | +//! as the algorithm for determining variance is a fixpoint computation with potential cycles that |
| 8 | +//! need to be resolved. rust-analyzer does not want a crate-wide analysis though as that would hurt |
| 9 | +//! incrementality too much and as such our query is based on a per item basis. |
| 10 | +//! |
| 11 | +//! This does unfortunately run into the issue that we can run into query cycles which salsa |
| 12 | +//! currently does not allow to be resolved via a fixpoint computation. This will likely be resolved |
| 13 | +//! by the next salsa version. If not, we will likely have to adapt and go with the rustc approach |
| 14 | +//! while installing firewall per item queries to prevent invalidation issues. |
5 | 15 |
|
6 | 16 | use crate::db::HirDatabase; |
7 | 17 | use crate::generics::{generics, Generics}; |
@@ -371,33 +381,19 @@ impl Context<'_> { |
371 | 381 | if args.is_empty() { |
372 | 382 | return; |
373 | 383 | } |
374 | | - if def_id == self.generics.def() { |
375 | | - // HACK: Workaround for the trivial cycle salsa case (see |
376 | | - // recursive_one_bivariant_more_non_bivariant_params test) |
377 | | - for k in args { |
378 | | - match k.data(Interner) { |
379 | | - GenericArgData::Lifetime(lt) => { |
380 | | - self.add_constraints_from_region(lt, Variance::Bivariant) |
381 | | - } |
382 | | - GenericArgData::Ty(ty) => self.add_constraints_from_ty(ty, Variance::Bivariant), |
383 | | - GenericArgData::Const(val) => self.add_constraints_from_const(val, variance), |
384 | | - } |
385 | | - } |
386 | | - } else { |
387 | | - let Some(variances) = self.db.variances_of(def_id) else { |
388 | | - return; |
389 | | - }; |
| 384 | + let Some(variances) = self.db.variances_of(def_id) else { |
| 385 | + return; |
| 386 | + }; |
390 | 387 |
|
391 | | - for (i, k) in args.iter().enumerate() { |
392 | | - match k.data(Interner) { |
393 | | - GenericArgData::Lifetime(lt) => { |
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])) |
398 | | - } |
399 | | - GenericArgData::Const(val) => self.add_constraints_from_const(val, variance), |
| 388 | + for (i, k) in args.iter().enumerate() { |
| 389 | + match k.data(Interner) { |
| 390 | + GenericArgData::Lifetime(lt) => { |
| 391 | + self.add_constraints_from_region(lt, variance.xform(variances[i])) |
| 392 | + } |
| 393 | + GenericArgData::Ty(ty) => { |
| 394 | + self.add_constraints_from_ty(ty, variance.xform(variances[i])) |
400 | 395 | } |
| 396 | + GenericArgData::Const(val) => self.add_constraints_from_const(val, variance), |
401 | 397 | } |
402 | 398 | } |
403 | 399 | } |
@@ -956,22 +952,17 @@ struct S3<T>(S<T, T>); |
956 | 952 | } |
957 | 953 |
|
958 | 954 | #[test] |
959 | | - fn recursive_one_bivariant_more_non_bivariant_params() { |
960 | | - // FIXME: This is wrong, this should be `BivariantPartialIndirect[T: bivariant, U: covariant]` (likewise for Wrapper) |
| 955 | + fn prove_fixedpoint() { |
| 956 | + // FIXME: This is wrong, this should be `FixedPoint[T: covariant, U: covariant, V: covariant]` |
961 | 957 | // This is a limitation of current salsa where a cycle may only set a fallback value to the |
962 | | - // query result which is not what we want! We want to treat the cycle call as fallback |
963 | | - // without setting the query result to the fallback. |
964 | | - // `BivariantPartial` works as we workaround for the trivial case of being self-referential |
| 958 | + // query result, but we need to solve a fixpoint here. The new salsa will have this |
| 959 | + // fortunately. |
965 | 960 | check( |
966 | 961 | r#" |
967 | | -struct BivariantPartial<T, U>(*const BivariantPartial<T, U>, U); |
968 | | -struct Wrapper<T, U>(BivariantPartialIndirect<T, U>); |
969 | | -struct BivariantPartialIndirect<T, U>(*const Wrapper<T, U>, U); |
| 962 | +struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V); |
970 | 963 | "#, |
971 | 964 | expect![[r#" |
972 | | - BivariantPartial[T: bivariant, U: covariant] |
973 | | - Wrapper[T: bivariant, U: bivariant] |
974 | | - BivariantPartialIndirect[T: bivariant, U: bivariant] |
| 965 | + FixedPoint[T: bivariant, U: bivariant, V: bivariant] |
975 | 966 | "#]], |
976 | 967 | ); |
977 | 968 | } |
|
0 commit comments