Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/variance.rs')
-rw-r--r--crates/hir-ty/src/variance.rs90
1 files changed, 37 insertions, 53 deletions
diff --git a/crates/hir-ty/src/variance.rs b/crates/hir-ty/src/variance.rs
index 5b8122a0a5..6f415a5289 100644
--- a/crates/hir-ty/src/variance.rs
+++ b/crates/hir-ty/src/variance.rs
@@ -36,13 +36,11 @@ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> Variances
#[salsa::tracked(
returns(ref),
- // cycle_fn = crate::variance::variances_of_cycle_fn,
- // cycle_initial = crate::variance::variances_of_cycle_initial,
- cycle_result = crate::variance::variances_of_cycle_initial,
+ cycle_fn = crate::variance::variances_of_cycle_fn,
+ cycle_initial = crate::variance::variances_of_cycle_initial,
)]
fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariancesOf {
tracing::debug!("variances_of(def={:?})", def);
- let interner = DbInterner::new_no_crate(db);
match def {
GenericDefId::FunctionId(_) => (),
GenericDefId::AdtId(adt) => {
@@ -56,43 +54,30 @@ fn variances_of_query(db: &dyn HirDatabase, def: GenericDefId) -> StoredVariance
}
}
}
- _ => return VariancesOf::empty(interner).store(),
+ _ => return VariancesOf::empty(DbInterner::new_no_crate(db)).store(),
}
let generics = generics(db, def);
let count = generics.len();
if count == 0 {
- return VariancesOf::empty(interner).store();
- }
- let mut variances =
- Context { generics, variances: vec![Variance::Bivariant; count], db }.solve();
-
- // FIXME(next-solver): This is *not* the correct behavior. I don't know if it has an actual effect,
- // since bivariance is prohibited in Rust, but rustc definitely does not fallback bivariance.
- // So why do we do this? Because, with the new solver, the effects of bivariance are catastrophic:
- // it leads to not relating types properly, and to very, very hard to debug bugs (speaking from experience).
- // Furthermore, our variance infra is known to not handle cycles properly. Therefore, at least until we fix
- // cycles, and perhaps forever at least for out tests, not allowing bivariance makes sense.
- // Why specifically invariance? I don't have a strong reason, mainly that invariance is a stronger relationship
- // (therefore, less room for mistakes) and that IMO incorrect covariance can be more problematic that incorrect
- // bivariance, at least while we don't handle lifetimes anyway.
- for variance in &mut variances {
- if *variance == Variance::Bivariant {
- *variance = Variance::Invariant;
- }
+ return VariancesOf::empty(DbInterner::new_no_crate(db)).store();
}
+ let variances =
+ Context { generics, variances: vec![Variance::Bivariant; count].into_boxed_slice(), db }
+ .solve();
VariancesOf::new_from_slice(&variances).store()
}
-// pub(crate) fn variances_of_cycle_fn(
-// _db: &dyn HirDatabase,
-// _result: &Option<Arc<[Variance]>>,
-// _count: u32,
-// _def: GenericDefId,
-// ) -> salsa::CycleRecoveryAction<Option<Arc<[Variance]>>> {
-// salsa::CycleRecoveryAction::Iterate
-// }
+pub(crate) fn variances_of_cycle_fn(
+ _db: &dyn HirDatabase,
+ _: &salsa::Cycle<'_>,
+ _last_provisional_value: &StoredVariancesOf,
+ value: StoredVariancesOf,
+ _def: GenericDefId,
+) -> StoredVariancesOf {
+ value
+}
fn glb(v1: Variance, v2: Variance) -> Variance {
// Greatest lower bound of the variance lattice as defined in The Paper:
@@ -123,18 +108,17 @@ pub(crate) fn variances_of_cycle_initial(
let generics = generics(db, def);
let count = generics.len();
- // FIXME(next-solver): Returns `Invariance` and not `Bivariance` here, see the comment in the main query.
- VariancesOf::new_from_iter(interner, std::iter::repeat_n(Variance::Invariant, count)).store()
+ VariancesOf::new_from_iter(interner, std::iter::repeat_n(Variance::Bivariant, count)).store()
}
struct Context<'db> {
db: &'db dyn HirDatabase,
generics: Generics,
- variances: Vec<Variance>,
+ variances: Box<[Variance]>,
}
impl<'db> Context<'db> {
- fn solve(mut self) -> Vec<Variance> {
+ fn solve(mut self) -> Box<[Variance]> {
tracing::debug!("solve(generics={:?})", self.generics);
match self.generics.def() {
GenericDefId::AdtId(adt) => {
@@ -484,8 +468,8 @@ struct Other<'a> {
}
"#,
expect![[r#"
- Hello['a: invariant]
- Other['a: invariant]
+ Hello['a: bivariant]
+ Other['a: bivariant]
"#]],
);
}
@@ -504,7 +488,7 @@ struct Foo<T: Trait> { //~ ERROR [T: o]
}
"#,
expect![[r#"
- Foo[T: invariant]
+ Foo[T: bivariant]
"#]],
);
}
@@ -586,9 +570,9 @@ struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR [U: *, T: +]
get[Self: contravariant, T: covariant]
get[Self: contravariant, T: contravariant]
TestStruct[U: covariant, T: covariant]
- TestEnum[U: invariant, T: covariant]
- TestContraStruct[U: invariant, T: covariant]
- TestBox[U: invariant, T: covariant]
+ TestEnum[U: bivariant, T: covariant]
+ TestContraStruct[U: bivariant, T: covariant]
+ TestBox[U: bivariant, T: covariant]
"#]],
);
}
@@ -708,8 +692,8 @@ enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
trait SomeTrait<'a> { fn foo(&self); } // OK on traits.
"#,
expect![[r#"
- SomeStruct['a: invariant]
- SomeEnum['a: invariant]
+ SomeStruct['a: bivariant]
+ SomeEnum['a: bivariant]
foo[Self: contravariant, 'a: invariant]
"#]],
);
@@ -737,14 +721,14 @@ struct DoubleNothing<T> {
"#,
expect![[r#"
- SomeStruct[A: invariant]
- SomeEnum[A: invariant]
- ListCell[T: invariant]
- SelfTyAlias[T: invariant]
- WithBounds[T: invariant]
- WithWhereBounds[T: invariant]
- WithOutlivesBounds[T: invariant]
- DoubleNothing[T: invariant]
+ SomeStruct[A: bivariant]
+ SomeEnum[A: bivariant]
+ ListCell[T: bivariant]
+ SelfTyAlias[T: bivariant]
+ WithBounds[T: bivariant]
+ WithWhereBounds[T: bivariant]
+ WithOutlivesBounds[T: bivariant]
+ DoubleNothing[T: bivariant]
"#]],
);
}
@@ -855,7 +839,7 @@ struct S3<T>(S<T, T>);
"#,
expect![[r#"
S[T: covariant]
- S2[T: invariant]
+ S2[T: bivariant]
S3[T: covariant]
"#]],
);
@@ -868,7 +852,7 @@ struct S3<T>(S<T, T>);
struct FixedPoint<T, U, V>(&'static FixedPoint<(), T, U>, V);
"#,
expect![[r#"
- FixedPoint[T: invariant, U: invariant, V: invariant]
+ FixedPoint[T: covariant, U: covariant, V: covariant]
"#]],
);
}