|
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