diff options
author | Florian Diebold <[email protected]> | 2020-11-20 17:00:34 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-12-07 10:48:58 +0000 |
commit | 78dd5482438b1ba13b4aa2eaa9a7c443a3342ce4 (patch) | |
tree | 29c3c7ffa25d23582972d58afea77da75e6a2b50 /crates/hir_ty | |
parent | a0fa522fdaf25daff6a2a9794214f0e0bedc5c24 (diff) |
Upgrade Chalk
Also make overflow depth and max type size configurable through env variables.
This can be helpful at least for debugging.
Fixes #6628.
Diffstat (limited to 'crates/hir_ty')
-rw-r--r-- | crates/hir_ty/Cargo.toml | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/regression.rs | 43 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 49 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/interner.rs | 16 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 13 |
7 files changed, 129 insertions, 17 deletions
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml index cf5c38a23..289e812fe 100644 --- a/crates/hir_ty/Cargo.toml +++ b/crates/hir_ty/Cargo.toml | |||
@@ -17,9 +17,9 @@ ena = "0.14.0" | |||
17 | log = "0.4.8" | 17 | log = "0.4.8" |
18 | rustc-hash = "1.1.0" | 18 | rustc-hash = "1.1.0" |
19 | scoped-tls = "1" | 19 | scoped-tls = "1" |
20 | chalk-solve = { version = "0.37", default-features = false } | 20 | chalk-solve = { version = "0.43", default-features = false } |
21 | chalk-ir = "0.37" | 21 | chalk-ir = "0.43" |
22 | chalk-recursive = "0.37" | 22 | chalk-recursive = "0.43" |
23 | 23 | ||
24 | stdx = { path = "../stdx", version = "0.0.0" } | 24 | stdx = { path = "../stdx", version = "0.0.0" } |
25 | hir_def = { path = "../hir_def", version = "0.0.0" } | 25 | hir_def = { path = "../hir_def", version = "0.0.0" } |
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 25cf9eb7f..66bdb8e88 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -99,6 +99,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
99 | #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] | 99 | #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] |
100 | fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>; | 100 | fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>; |
101 | 101 | ||
102 | #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] | ||
103 | fn fn_def_variance(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> chalk::Variances; | ||
104 | |||
105 | #[salsa::invoke(crate::traits::chalk::adt_variance_query)] | ||
106 | fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; | ||
107 | |||
102 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] | 108 | #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] |
103 | fn associated_ty_value( | 109 | fn associated_ty_value( |
104 | &self, | 110 | &self, |
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs index 94d86b0d1..8cf4e7012 100644 --- a/crates/hir_ty/src/tests/regression.rs +++ b/crates/hir_ty/src/tests/regression.rs | |||
@@ -840,3 +840,46 @@ fn issue_4966() { | |||
840 | "#]], | 840 | "#]], |
841 | ); | 841 | ); |
842 | } | 842 | } |
843 | |||
844 | #[test] | ||
845 | fn issue_6628() { | ||
846 | check_infer( | ||
847 | r#" | ||
848 | #[lang = "fn_once"] | ||
849 | pub trait FnOnce<Args> { | ||
850 | type Output; | ||
851 | } | ||
852 | |||
853 | struct S<T>(); | ||
854 | impl<T> S<T> { | ||
855 | fn f(&self, _t: T) {} | ||
856 | fn g<F: FnOnce(&T)>(&self, _f: F) {} | ||
857 | } | ||
858 | fn main() { | ||
859 | let s = S(); | ||
860 | s.g(|_x| {}); | ||
861 | s.f(10); | ||
862 | } | ||
863 | "#, | ||
864 | expect![[r#" | ||
865 | 105..109 'self': &S<T> | ||
866 | 111..113 '_t': T | ||
867 | 118..120 '{}': () | ||
868 | 146..150 'self': &S<T> | ||
869 | 152..154 '_f': F | ||
870 | 159..161 '{}': () | ||
871 | 174..225 '{ ...10); }': () | ||
872 | 184..185 's': S<i32> | ||
873 | 188..189 'S': S<i32>() -> S<i32> | ||
874 | 188..191 'S()': S<i32> | ||
875 | 197..198 's': S<i32> | ||
876 | 197..209 's.g(|_x| {})': () | ||
877 | 201..208 '|_x| {}': |&i32| -> () | ||
878 | 202..204 '_x': &i32 | ||
879 | 206..208 '{}': () | ||
880 | 215..216 's': S<i32> | ||
881 | 215..222 's.f(10)': () | ||
882 | 219..221 '10': i32 | ||
883 | "#]], | ||
884 | ); | ||
885 | } | ||
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index ce1174cbe..dfa51896b 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -1,4 +1,5 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::env::var; | ||
2 | use std::sync::Arc; | 3 | use std::sync::Arc; |
3 | 4 | ||
4 | use base_db::CrateId; | 5 | use base_db::CrateId; |
@@ -15,12 +16,6 @@ use self::chalk::{from_chalk, Interner, ToChalk}; | |||
15 | 16 | ||
16 | pub(crate) mod chalk; | 17 | pub(crate) mod chalk; |
17 | 18 | ||
18 | // This controls the maximum size of types Chalk considers. If we set this too | ||
19 | // high, we can run into slow edge cases; if we set it too low, Chalk won't | ||
20 | // find some solutions. | ||
21 | // FIXME this is currently hardcoded in the recursive solver | ||
22 | // const CHALK_SOLVER_MAX_SIZE: usize = 10; | ||
23 | |||
24 | /// This controls how much 'time' we give the Chalk solver before giving up. | 19 | /// This controls how much 'time' we give the Chalk solver before giving up. |
25 | const CHALK_SOLVER_FUEL: i32 = 100; | 20 | const CHALK_SOLVER_FUEL: i32 = 100; |
26 | 21 | ||
@@ -31,9 +26,11 @@ struct ChalkContext<'a> { | |||
31 | } | 26 | } |
32 | 27 | ||
33 | fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { | 28 | fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { |
34 | let overflow_depth = 100; | 29 | let overflow_depth = |
30 | var("CHALK_OVERFLOW_DEPTH").ok().and_then(|s| s.parse().ok()).unwrap_or(100); | ||
35 | let caching_enabled = true; | 31 | let caching_enabled = true; |
36 | chalk_recursive::RecursiveSolver::new(overflow_depth, caching_enabled) | 32 | let max_size = var("CHALK_SOLVER_MAX_SIZE").ok().and_then(|s| s.parse().ok()).unwrap_or(30); |
33 | chalk_recursive::RecursiveSolver::new(overflow_depth, max_size, caching_enabled) | ||
37 | } | 34 | } |
38 | 35 | ||
39 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: | 36 | /// A set of clauses that we assume to be true. E.g. if we are inside this function: |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 55e2c3a3e..69eae6f79 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -104,7 +104,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
104 | }; | 104 | }; |
105 | 105 | ||
106 | // Note: Since we're using impls_for_trait, only impls where the trait | 106 | // Note: Since we're using impls_for_trait, only impls where the trait |
107 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 107 | // can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that |
108 | // and will panic if the trait can't be resolved. | 108 | // and will panic if the trait can't be resolved. |
109 | let in_deps = self.db.trait_impls_in_deps(self.krate); | 109 | let in_deps = self.db.trait_impls_in_deps(self.krate); |
110 | let in_self = self.db.trait_impls_in_crate(self.krate); | 110 | let in_self = self.db.trait_impls_in_crate(self.krate); |
@@ -206,7 +206,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
206 | Some((trait_, alias)) | 206 | Some((trait_, alias)) |
207 | }) | 207 | }) |
208 | { | 208 | { |
209 | // Making up `AsyncBlock<T>: Future<Output = T>` | 209 | // Making up Symbol’s value as variable is void: AsyncBlock<T>: |
210 | // | 210 | // |
211 | // |--------------------OpaqueTyDatum-------------------| | 211 | // |--------------------OpaqueTyDatum-------------------| |
212 | // |-------------OpaqueTyDatumBound--------------| | 212 | // |-------------OpaqueTyDatumBound--------------| |
@@ -242,7 +242,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
242 | // The opaque type has 1 parameter. | 242 | // The opaque type has 1 parameter. |
243 | make_binders(bound, 1) | 243 | make_binders(bound, 1) |
244 | } else { | 244 | } else { |
245 | // If failed to find `Future::Output`, return empty bounds as fallback. | 245 | // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. |
246 | let bound = OpaqueTyDatumBound { | 246 | let bound = OpaqueTyDatumBound { |
247 | bounds: make_binders(vec![], 0), | 247 | bounds: make_binders(vec![], 0), |
248 | where_clauses: make_binders(vec![], 0), | 248 | where_clauses: make_binders(vec![], 0), |
@@ -343,6 +343,23 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
343 | // FIXME | 343 | // FIXME |
344 | unimplemented!() | 344 | unimplemented!() |
345 | } | 345 | } |
346 | |||
347 | fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> { | ||
348 | self | ||
349 | } | ||
350 | } | ||
351 | |||
352 | impl<'a> chalk_ir::UnificationDatabase<Interner> for ChalkContext<'a> { | ||
353 | fn fn_def_variance( | ||
354 | &self, | ||
355 | fn_def_id: chalk_ir::FnDefId<Interner>, | ||
356 | ) -> chalk_ir::Variances<Interner> { | ||
357 | self.db.fn_def_variance(self.krate, fn_def_id) | ||
358 | } | ||
359 | |||
360 | fn adt_variance(&self, adt_id: chalk_ir::AdtId<Interner>) -> chalk_ir::Variances<Interner> { | ||
361 | self.db.adt_variance(self.krate, adt_id) | ||
362 | } | ||
346 | } | 363 | } |
347 | 364 | ||
348 | pub(crate) fn program_clauses_for_chalk_env_query( | 365 | pub(crate) fn program_clauses_for_chalk_env_query( |
@@ -644,6 +661,32 @@ pub(crate) fn fn_def_datum_query( | |||
644 | Arc::new(datum) | 661 | Arc::new(datum) |
645 | } | 662 | } |
646 | 663 | ||
664 | pub(crate) fn fn_def_variance_query( | ||
665 | db: &dyn HirDatabase, | ||
666 | _krate: CrateId, | ||
667 | fn_def_id: FnDefId, | ||
668 | ) -> Variances { | ||
669 | let callable_def: CallableDefId = from_chalk(db, fn_def_id); | ||
670 | let generic_params = generics(db.upcast(), callable_def.into()); | ||
671 | Variances::from( | ||
672 | &Interner, | ||
673 | std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), | ||
674 | ) | ||
675 | } | ||
676 | |||
677 | pub(crate) fn adt_variance_query( | ||
678 | db: &dyn HirDatabase, | ||
679 | _krate: CrateId, | ||
680 | adt_id: AdtId, | ||
681 | ) -> Variances { | ||
682 | let adt: crate::AdtId = from_chalk(db, adt_id); | ||
683 | let generic_params = generics(db.upcast(), adt.into()); | ||
684 | Variances::from( | ||
685 | &Interner, | ||
686 | std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()), | ||
687 | ) | ||
688 | } | ||
689 | |||
647 | impl From<FnDefId> for crate::db::InternedCallableDefId { | 690 | impl From<FnDefId> for crate::db::InternedCallableDefId { |
648 | fn from(fn_def_id: FnDefId) -> Self { | 691 | fn from(fn_def_id: FnDefId) -> Self { |
649 | InternKey::from_intern_id(fn_def_id.0) | 692 | InternKey::from_intern_id(fn_def_id.0) |
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/traits/chalk/interner.rs index 39569e690..6a4aa8333 100644 --- a/crates/hir_ty/src/traits/chalk/interner.rs +++ b/crates/hir_ty/src/traits/chalk/interner.rs | |||
@@ -25,6 +25,7 @@ pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>; | |||
25 | pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; | 25 | pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; |
26 | pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 26 | pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
27 | pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; | 27 | pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; |
28 | pub(crate) type Variances = chalk_ir::Variances<Interner>; | ||
28 | 29 | ||
29 | impl chalk_ir::interner::Interner for Interner { | 30 | impl chalk_ir::interner::Interner for Interner { |
30 | type InternedType = Arc<chalk_ir::TyData<Self>>; | 31 | type InternedType = Arc<chalk_ir::TyData<Self>>; |
@@ -41,6 +42,7 @@ impl chalk_ir::interner::Interner for Interner { | |||
41 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; | 42 | type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; |
42 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; | 43 | type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; |
43 | type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; | 44 | type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; |
45 | type InternedVariances = Arc<[chalk_ir::Variance]>; | ||
44 | type DefId = InternId; | 46 | type DefId = InternId; |
45 | type InternedAdtId = hir_def::AdtId; | 47 | type InternedAdtId = hir_def::AdtId; |
46 | type Identifier = TypeAliasId; | 48 | type Identifier = TypeAliasId; |
@@ -370,6 +372,20 @@ impl chalk_ir::interner::Interner for Interner { | |||
370 | ) -> Option<fmt::Result> { | 372 | ) -> Option<fmt::Result> { |
371 | None | 373 | None |
372 | } | 374 | } |
375 | |||
376 | fn intern_variances<E>( | ||
377 | &self, | ||
378 | data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>, | ||
379 | ) -> Result<Self::InternedVariances, E> { | ||
380 | data.into_iter().collect() | ||
381 | } | ||
382 | |||
383 | fn variances_data<'a>( | ||
384 | &self, | ||
385 | variances: &'a Self::InternedVariances, | ||
386 | ) -> &'a [chalk_ir::Variance] { | ||
387 | &variances | ||
388 | } | ||
373 | } | 389 | } |
374 | 390 | ||
375 | impl chalk_ir::interner::HasInterner for Interner { | 391 | impl chalk_ir::interner::HasInterner for Interner { |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 86cbc4c7e..8700d664e 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -31,7 +31,8 @@ impl ToChalk for Ty { | |||
31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), | 31 | TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters), |
32 | TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), | 32 | TypeCtor::Array => array_to_chalk(db, apply_ty.parameters), |
33 | TypeCtor::FnPtr { num_args: _, is_varargs } => { | 33 | TypeCtor::FnPtr { num_args: _, is_varargs } => { |
34 | let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner); | 34 | let substitution = |
35 | chalk_ir::FnSubst(apply_ty.parameters.to_chalk(db).shifted_in(&Interner)); | ||
35 | chalk_ir::TyKind::Function(chalk_ir::FnPointer { | 36 | chalk_ir::TyKind::Function(chalk_ir::FnPointer { |
36 | num_binders: 0, | 37 | num_binders: 0, |
37 | sig: chalk_ir::FnSig { | 38 | sig: chalk_ir::FnSig { |
@@ -183,7 +184,7 @@ impl ToChalk for Ty { | |||
183 | assert_eq!(num_binders, 0); | 184 | assert_eq!(num_binders, 0); |
184 | let parameters: Substs = from_chalk( | 185 | let parameters: Substs = from_chalk( |
185 | db, | 186 | db, |
186 | substitution.shifted_out(&Interner).expect("fn ptr should have no binders"), | 187 | substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"), |
187 | ); | 188 | ); |
188 | Ty::Apply(ApplicationTy { | 189 | Ty::Apply(ApplicationTy { |
189 | ctor: TypeCtor::FnPtr { | 190 | ctor: TypeCtor::FnPtr { |
@@ -536,6 +537,7 @@ impl ToChalk for GenericPredicate { | |||
536 | // we don't produce any where clauses with binders and can't currently deal with them | 537 | // we don't produce any where clauses with binders and can't currently deal with them |
537 | match where_clause | 538 | match where_clause |
538 | .skip_binders() | 539 | .skip_binders() |
540 | .clone() | ||
539 | .shifted_out(&Interner) | 541 | .shifted_out(&Interner) |
540 | .expect("unexpected bound vars in where clause") | 542 | .expect("unexpected bound vars in where clause") |
541 | { | 543 | { |
@@ -661,7 +663,12 @@ where | |||
661 | chalk_ir::TyVariableKind::Integer => TyKind::Integer, | 663 | chalk_ir::TyVariableKind::Integer => TyKind::Integer, |
662 | chalk_ir::TyVariableKind::Float => TyKind::Float, | 664 | chalk_ir::TyVariableKind::Float => TyKind::Float, |
663 | }, | 665 | }, |
664 | chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"), | 666 | // HACK: Chalk can sometimes return new lifetime variables. We |
667 | // want to just skip them, but to not mess up the indices of | ||
668 | // other variables, we'll just create a new type variable in | ||
669 | // their place instead. This should not matter (we never see the | ||
670 | // actual *uses* of the lifetime variable). | ||
671 | chalk_ir::VariableKind::Lifetime => TyKind::General, | ||
665 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), | 672 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), |
666 | }) | 673 | }) |
667 | .collect(); | 674 | .collect(); |