mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 21:13:37 +00:00
Upgrade Chalk
Also make overflow depth and max type size configurable through env variables. This can be helpful at least for debugging. Fixes #6628.
This commit is contained in:
parent
a0fa522fda
commit
78dd548243
8 changed files with 137 additions and 25 deletions
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -168,9 +168,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-derive"
|
name = "chalk-derive"
|
||||||
version = "0.37.0"
|
version = "0.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "564b529b0d620da43dc7ea46fa95b5c602e783e1870aeb07e8cbb6d7ff71bee6"
|
checksum = "e2d9e0c8adcced1ab0fea5cb8a38647922893d5b495e363e1814299fd380469b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -180,9 +180,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-ir"
|
name = "chalk-ir"
|
||||||
version = "0.37.0"
|
version = "0.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e67d29482387f4cbed6d8f1b1f7d24f00ff10612c700c65fe4af220df11e4d24"
|
checksum = "c5218266a5709bc4943de997e64d3fab41c9e9f68efd54a898de53135e987bd3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
@ -190,9 +190,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-recursive"
|
name = "chalk-recursive"
|
||||||
version = "0.37.0"
|
version = "0.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c52032be6fbdf91b6a7df3cafba3a6683fdabeff88e7ab73eea96e28657d973"
|
checksum = "ed8f34f13fd4f30251f9f6f1dc56f80363201390ecbcac2fdfc8e33036cd9c4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"chalk-ir",
|
"chalk-ir",
|
||||||
|
@ -203,9 +203,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chalk-solve"
|
name = "chalk-solve"
|
||||||
version = "0.37.0"
|
version = "0.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e0378bdfe1547b6fd545f518373b08c1e0c14920f7555a62d049021250a2b89b"
|
checksum = "379c9f584488346044709d4c638c38d61a06fe593d4de2ac5f15fd2b0ba4cd9d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chalk-derive",
|
"chalk-derive",
|
||||||
"chalk-ir",
|
"chalk-ir",
|
||||||
|
|
|
@ -17,9 +17,9 @@ ena = "0.14.0"
|
||||||
log = "0.4.8"
|
log = "0.4.8"
|
||||||
rustc-hash = "1.1.0"
|
rustc-hash = "1.1.0"
|
||||||
scoped-tls = "1"
|
scoped-tls = "1"
|
||||||
chalk-solve = { version = "0.37", default-features = false }
|
chalk-solve = { version = "0.43", default-features = false }
|
||||||
chalk-ir = "0.37"
|
chalk-ir = "0.43"
|
||||||
chalk-recursive = "0.37"
|
chalk-recursive = "0.43"
|
||||||
|
|
||||||
stdx = { path = "../stdx", version = "0.0.0" }
|
stdx = { path = "../stdx", version = "0.0.0" }
|
||||||
hir_def = { path = "../hir_def", version = "0.0.0" }
|
hir_def = { path = "../hir_def", version = "0.0.0" }
|
||||||
|
|
|
@ -99,6 +99,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||||
#[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
|
#[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
|
||||||
fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>;
|
fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>;
|
||||||
|
|
||||||
|
#[salsa::invoke(crate::traits::chalk::fn_def_variance_query)]
|
||||||
|
fn fn_def_variance(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> chalk::Variances;
|
||||||
|
|
||||||
|
#[salsa::invoke(crate::traits::chalk::adt_variance_query)]
|
||||||
|
fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances;
|
||||||
|
|
||||||
#[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
|
#[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
|
||||||
fn associated_ty_value(
|
fn associated_ty_value(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
@ -840,3 +840,46 @@ fn issue_4966() {
|
||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_6628() {
|
||||||
|
check_infer(
|
||||||
|
r#"
|
||||||
|
#[lang = "fn_once"]
|
||||||
|
pub trait FnOnce<Args> {
|
||||||
|
type Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S<T>();
|
||||||
|
impl<T> S<T> {
|
||||||
|
fn f(&self, _t: T) {}
|
||||||
|
fn g<F: FnOnce(&T)>(&self, _f: F) {}
|
||||||
|
}
|
||||||
|
fn main() {
|
||||||
|
let s = S();
|
||||||
|
s.g(|_x| {});
|
||||||
|
s.f(10);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
expect![[r#"
|
||||||
|
105..109 'self': &S<T>
|
||||||
|
111..113 '_t': T
|
||||||
|
118..120 '{}': ()
|
||||||
|
146..150 'self': &S<T>
|
||||||
|
152..154 '_f': F
|
||||||
|
159..161 '{}': ()
|
||||||
|
174..225 '{ ...10); }': ()
|
||||||
|
184..185 's': S<i32>
|
||||||
|
188..189 'S': S<i32>() -> S<i32>
|
||||||
|
188..191 'S()': S<i32>
|
||||||
|
197..198 's': S<i32>
|
||||||
|
197..209 's.g(|_x| {})': ()
|
||||||
|
201..208 '|_x| {}': |&i32| -> ()
|
||||||
|
202..204 '_x': &i32
|
||||||
|
206..208 '{}': ()
|
||||||
|
215..216 's': S<i32>
|
||||||
|
215..222 's.f(10)': ()
|
||||||
|
219..221 '10': i32
|
||||||
|
"#]],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//! Trait solving using Chalk.
|
//! Trait solving using Chalk.
|
||||||
|
use std::env::var;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use base_db::CrateId;
|
use base_db::CrateId;
|
||||||
|
@ -15,12 +16,6 @@ use self::chalk::{from_chalk, Interner, ToChalk};
|
||||||
|
|
||||||
pub(crate) mod chalk;
|
pub(crate) mod chalk;
|
||||||
|
|
||||||
// This controls the maximum size of types Chalk considers. If we set this too
|
|
||||||
// high, we can run into slow edge cases; if we set it too low, Chalk won't
|
|
||||||
// find some solutions.
|
|
||||||
// FIXME this is currently hardcoded in the recursive solver
|
|
||||||
// const CHALK_SOLVER_MAX_SIZE: usize = 10;
|
|
||||||
|
|
||||||
/// This controls how much 'time' we give the Chalk solver before giving up.
|
/// This controls how much 'time' we give the Chalk solver before giving up.
|
||||||
const CHALK_SOLVER_FUEL: i32 = 100;
|
const CHALK_SOLVER_FUEL: i32 = 100;
|
||||||
|
|
||||||
|
@ -31,9 +26,11 @@ struct ChalkContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
|
fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
|
||||||
let overflow_depth = 100;
|
let overflow_depth =
|
||||||
|
var("CHALK_OVERFLOW_DEPTH").ok().and_then(|s| s.parse().ok()).unwrap_or(100);
|
||||||
let caching_enabled = true;
|
let caching_enabled = true;
|
||||||
chalk_recursive::RecursiveSolver::new(overflow_depth, caching_enabled)
|
let max_size = var("CHALK_SOLVER_MAX_SIZE").ok().and_then(|s| s.parse().ok()).unwrap_or(30);
|
||||||
|
chalk_recursive::RecursiveSolver::new(overflow_depth, max_size, caching_enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
|
/// A set of clauses that we assume to be true. E.g. if we are inside this function:
|
||||||
|
|
|
@ -104,7 +104,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Note: Since we're using impls_for_trait, only impls where the trait
|
// Note: Since we're using impls_for_trait, only impls where the trait
|
||||||
// can be resolved should ever reach Chalk. `impl_datum` relies on that
|
// can be resolved should ever reach Chalk. Symbol’s value as variable is void: impl_datum relies on that
|
||||||
// and will panic if the trait can't be resolved.
|
// and will panic if the trait can't be resolved.
|
||||||
let in_deps = self.db.trait_impls_in_deps(self.krate);
|
let in_deps = self.db.trait_impls_in_deps(self.krate);
|
||||||
let in_self = self.db.trait_impls_in_crate(self.krate);
|
let in_self = self.db.trait_impls_in_crate(self.krate);
|
||||||
|
@ -206,7 +206,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||||
Some((trait_, alias))
|
Some((trait_, alias))
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
// Making up `AsyncBlock<T>: Future<Output = T>`
|
// Making up Symbol’s value as variable is void: AsyncBlock<T>:
|
||||||
//
|
//
|
||||||
// |--------------------OpaqueTyDatum-------------------|
|
// |--------------------OpaqueTyDatum-------------------|
|
||||||
// |-------------OpaqueTyDatumBound--------------|
|
// |-------------OpaqueTyDatumBound--------------|
|
||||||
|
@ -242,7 +242,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||||
// The opaque type has 1 parameter.
|
// The opaque type has 1 parameter.
|
||||||
make_binders(bound, 1)
|
make_binders(bound, 1)
|
||||||
} else {
|
} else {
|
||||||
// If failed to find `Future::Output`, return empty bounds as fallback.
|
// If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
|
||||||
let bound = OpaqueTyDatumBound {
|
let bound = OpaqueTyDatumBound {
|
||||||
bounds: make_binders(vec![], 0),
|
bounds: make_binders(vec![], 0),
|
||||||
where_clauses: make_binders(vec![], 0),
|
where_clauses: make_binders(vec![], 0),
|
||||||
|
@ -343,6 +343,23 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
|
||||||
// FIXME
|
// FIXME
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> chalk_ir::UnificationDatabase<Interner> for ChalkContext<'a> {
|
||||||
|
fn fn_def_variance(
|
||||||
|
&self,
|
||||||
|
fn_def_id: chalk_ir::FnDefId<Interner>,
|
||||||
|
) -> chalk_ir::Variances<Interner> {
|
||||||
|
self.db.fn_def_variance(self.krate, fn_def_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adt_variance(&self, adt_id: chalk_ir::AdtId<Interner>) -> chalk_ir::Variances<Interner> {
|
||||||
|
self.db.adt_variance(self.krate, adt_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn program_clauses_for_chalk_env_query(
|
pub(crate) fn program_clauses_for_chalk_env_query(
|
||||||
|
@ -644,6 +661,32 @@ pub(crate) fn fn_def_datum_query(
|
||||||
Arc::new(datum)
|
Arc::new(datum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn fn_def_variance_query(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
_krate: CrateId,
|
||||||
|
fn_def_id: FnDefId,
|
||||||
|
) -> Variances {
|
||||||
|
let callable_def: CallableDefId = from_chalk(db, fn_def_id);
|
||||||
|
let generic_params = generics(db.upcast(), callable_def.into());
|
||||||
|
Variances::from(
|
||||||
|
&Interner,
|
||||||
|
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn adt_variance_query(
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
_krate: CrateId,
|
||||||
|
adt_id: AdtId,
|
||||||
|
) -> Variances {
|
||||||
|
let adt: crate::AdtId = from_chalk(db, adt_id);
|
||||||
|
let generic_params = generics(db.upcast(), adt.into());
|
||||||
|
Variances::from(
|
||||||
|
&Interner,
|
||||||
|
std::iter::repeat(chalk_ir::Variance::Invariant).take(generic_params.len()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
impl From<FnDefId> for crate::db::InternedCallableDefId {
|
impl From<FnDefId> for crate::db::InternedCallableDefId {
|
||||||
fn from(fn_def_id: FnDefId) -> Self {
|
fn from(fn_def_id: FnDefId) -> Self {
|
||||||
InternKey::from_intern_id(fn_def_id.0)
|
InternKey::from_intern_id(fn_def_id.0)
|
||||||
|
|
|
@ -25,6 +25,7 @@ pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
|
||||||
pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
|
pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
|
||||||
pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
|
pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
|
||||||
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
|
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
|
||||||
|
pub(crate) type Variances = chalk_ir::Variances<Interner>;
|
||||||
|
|
||||||
impl chalk_ir::interner::Interner for Interner {
|
impl chalk_ir::interner::Interner for Interner {
|
||||||
type InternedType = Arc<chalk_ir::TyData<Self>>;
|
type InternedType = Arc<chalk_ir::TyData<Self>>;
|
||||||
|
@ -41,6 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
|
||||||
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
|
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
|
||||||
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
|
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
|
||||||
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
|
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
|
||||||
|
type InternedVariances = Arc<[chalk_ir::Variance]>;
|
||||||
type DefId = InternId;
|
type DefId = InternId;
|
||||||
type InternedAdtId = hir_def::AdtId;
|
type InternedAdtId = hir_def::AdtId;
|
||||||
type Identifier = TypeAliasId;
|
type Identifier = TypeAliasId;
|
||||||
|
@ -370,6 +372,20 @@ impl chalk_ir::interner::Interner for Interner {
|
||||||
) -> Option<fmt::Result> {
|
) -> Option<fmt::Result> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn intern_variances<E>(
|
||||||
|
&self,
|
||||||
|
data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
|
||||||
|
) -> Result<Self::InternedVariances, E> {
|
||||||
|
data.into_iter().collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variances_data<'a>(
|
||||||
|
&self,
|
||||||
|
variances: &'a Self::InternedVariances,
|
||||||
|
) -> &'a [chalk_ir::Variance] {
|
||||||
|
&variances
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl chalk_ir::interner::HasInterner for Interner {
|
impl chalk_ir::interner::HasInterner for Interner {
|
||||||
|
|
|
@ -31,7 +31,8 @@ impl ToChalk for Ty {
|
||||||
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
|
||||||
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
|
||||||
TypeCtor::FnPtr { num_args: _, is_varargs } => {
|
TypeCtor::FnPtr { num_args: _, is_varargs } => {
|
||||||
let substitution = apply_ty.parameters.to_chalk(db).shifted_in(&Interner);
|
let substitution =
|
||||||
|
chalk_ir::FnSubst(apply_ty.parameters.to_chalk(db).shifted_in(&Interner));
|
||||||
chalk_ir::TyKind::Function(chalk_ir::FnPointer {
|
chalk_ir::TyKind::Function(chalk_ir::FnPointer {
|
||||||
num_binders: 0,
|
num_binders: 0,
|
||||||
sig: chalk_ir::FnSig {
|
sig: chalk_ir::FnSig {
|
||||||
|
@ -183,7 +184,7 @@ impl ToChalk for Ty {
|
||||||
assert_eq!(num_binders, 0);
|
assert_eq!(num_binders, 0);
|
||||||
let parameters: Substs = from_chalk(
|
let parameters: Substs = from_chalk(
|
||||||
db,
|
db,
|
||||||
substitution.shifted_out(&Interner).expect("fn ptr should have no binders"),
|
substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
|
||||||
);
|
);
|
||||||
Ty::Apply(ApplicationTy {
|
Ty::Apply(ApplicationTy {
|
||||||
ctor: TypeCtor::FnPtr {
|
ctor: TypeCtor::FnPtr {
|
||||||
|
@ -536,6 +537,7 @@ impl ToChalk for GenericPredicate {
|
||||||
// we don't produce any where clauses with binders and can't currently deal with them
|
// we don't produce any where clauses with binders and can't currently deal with them
|
||||||
match where_clause
|
match where_clause
|
||||||
.skip_binders()
|
.skip_binders()
|
||||||
|
.clone()
|
||||||
.shifted_out(&Interner)
|
.shifted_out(&Interner)
|
||||||
.expect("unexpected bound vars in where clause")
|
.expect("unexpected bound vars in where clause")
|
||||||
{
|
{
|
||||||
|
@ -661,7 +663,12 @@ where
|
||||||
chalk_ir::TyVariableKind::Integer => TyKind::Integer,
|
chalk_ir::TyVariableKind::Integer => TyKind::Integer,
|
||||||
chalk_ir::TyVariableKind::Float => TyKind::Float,
|
chalk_ir::TyVariableKind::Float => TyKind::Float,
|
||||||
},
|
},
|
||||||
chalk_ir::VariableKind::Lifetime => panic!("unexpected lifetime from Chalk"),
|
// HACK: Chalk can sometimes return new lifetime variables. We
|
||||||
|
// want to just skip them, but to not mess up the indices of
|
||||||
|
// other variables, we'll just create a new type variable in
|
||||||
|
// their place instead. This should not matter (we never see the
|
||||||
|
// actual *uses* of the lifetime variable).
|
||||||
|
chalk_ir::VariableKind::Lifetime => TyKind::General,
|
||||||
chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
|
chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
Loading…
Reference in a new issue