Skip to content

Commit a102ea1

Browse files
committed
Describe variance resolution approach differences to rustc
1 parent bf27d88 commit a102ea1

File tree

1 file changed

+27
-36
lines changed

1 file changed

+27
-36
lines changed

src/tools/rust-analyzer/crates/hir-ty/src/variance.rs

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
//! chapter for more info.
33
//!
44
//! [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.
515
616
use crate::db::HirDatabase;
717
use crate::generics::{generics, Generics};
@@ -371,33 +381,19 @@ impl Context<'_> {
371381
if args.is_empty() {
372382
return;
373383
}
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+
};
390387

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]))
400395
}
396+
GenericArgData::Const(val) => self.add_constraints_from_const(val, variance),
401397
}
402398
}
403399
}
@@ -956,22 +952,17 @@ struct S3<T>(S<T, T>);
956952
}
957953

958954
#[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]`
961957
// 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.
965960
check(
966961
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);
970963
"#,
971964
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]
975966
"#]],
976967
);
977968
}

0 commit comments

Comments
 (0)