Skip to content

Commit 403ed48

Browse files
Merge #6597
6597: Upgrade Chalk r=flodiebold a=flodiebold Also make overflow depth and max type size configurable through env variables. This can be helpful at least for debugging. Tests currently fail because of rust-lang/chalk#656, so we'll need to wait for the next update to merge this. Co-authored-by: Florian Diebold <[email protected]>
2 parents a0fa522 + 78dd548 commit 403ed48

File tree

8 files changed

+137
-25
lines changed

8 files changed

+137
-25
lines changed

Cargo.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir_ty/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ ena = "0.14.0"
1717
log = "0.4.8"
1818
rustc-hash = "1.1.0"
1919
scoped-tls = "1"
20-
chalk-solve = { version = "0.37", default-features = false }
21-
chalk-ir = "0.37"
22-
chalk-recursive = "0.37"
20+
chalk-solve = { version = "0.43", default-features = false }
21+
chalk-ir = "0.43"
22+
chalk-recursive = "0.43"
2323

2424
stdx = { path = "../stdx", version = "0.0.0" }
2525
hir_def = { path = "../hir_def", version = "0.0.0" }

crates/hir_ty/src/db.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
9999
#[salsa::invoke(crate::traits::chalk::fn_def_datum_query)]
100100
fn fn_def_datum(&self, krate: CrateId, fn_def_id: chalk::FnDefId) -> Arc<chalk::FnDefDatum>;
101101

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+
102108
#[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
103109
fn associated_ty_value(
104110
&self,

crates/hir_ty/src/tests/regression.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,3 +840,46 @@ fn issue_4966() {
840840
"#]],
841841
);
842842
}
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+
}

crates/hir_ty/src/traits.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Trait solving using Chalk.
2+
use std::env::var;
23
use std::sync::Arc;
34

45
use base_db::CrateId;
@@ -15,12 +16,6 @@ use self::chalk::{from_chalk, Interner, ToChalk};
1516

1617
pub(crate) mod chalk;
1718

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-
2419
/// This controls how much 'time' we give the Chalk solver before giving up.
2520
const CHALK_SOLVER_FUEL: i32 = 100;
2621

@@ -31,9 +26,11 @@ struct ChalkContext<'a> {
3126
}
3227

3328
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);
3531
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)
3734
}
3835

3936
/// A set of clauses that we assume to be true. E.g. if we are inside this function:

crates/hir_ty/src/traits/chalk.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
104104
};
105105

106106
// 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
108108
// and will panic if the trait can't be resolved.
109109
let in_deps = self.db.trait_impls_in_deps(self.krate);
110110
let in_self = self.db.trait_impls_in_crate(self.krate);
@@ -206,7 +206,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
206206
Some((trait_, alias))
207207
})
208208
{
209-
// Making up `AsyncBlock<T>: Future<Output = T>`
209+
// Making up Symbol’s value as variable is void: AsyncBlock<T>:
210210
//
211211
// |--------------------OpaqueTyDatum-------------------|
212212
// |-------------OpaqueTyDatumBound--------------|
@@ -242,7 +242,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
242242
// The opaque type has 1 parameter.
243243
make_binders(bound, 1)
244244
} 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.
246246
let bound = OpaqueTyDatumBound {
247247
bounds: make_binders(vec![], 0),
248248
where_clauses: make_binders(vec![], 0),
@@ -343,6 +343,23 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
343343
// FIXME
344344
unimplemented!()
345345
}
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+
}
346363
}
347364

348365
pub(crate) fn program_clauses_for_chalk_env_query(
@@ -644,6 +661,32 @@ pub(crate) fn fn_def_datum_query(
644661
Arc::new(datum)
645662
}
646663

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+
647690
impl From<FnDefId> for crate::db::InternedCallableDefId {
648691
fn from(fn_def_id: FnDefId) -> Self {
649692
InternKey::from_intern_id(fn_def_id.0)

crates/hir_ty/src/traits/chalk/interner.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub(crate) type FnDefId = chalk_ir::FnDefId<Interner>;
2525
pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
2626
pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
2727
pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
28+
pub(crate) type Variances = chalk_ir::Variances<Interner>;
2829

2930
impl chalk_ir::interner::Interner for Interner {
3031
type InternedType = Arc<chalk_ir::TyData<Self>>;
@@ -41,6 +42,7 @@ impl chalk_ir::interner::Interner for Interner {
4142
type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>;
4243
type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>;
4344
type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
45+
type InternedVariances = Arc<[chalk_ir::Variance]>;
4446
type DefId = InternId;
4547
type InternedAdtId = hir_def::AdtId;
4648
type Identifier = TypeAliasId;
@@ -370,6 +372,20 @@ impl chalk_ir::interner::Interner for Interner {
370372
) -> Option<fmt::Result> {
371373
None
372374
}
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+
}
373389
}
374390

375391
impl chalk_ir::interner::HasInterner for Interner {

crates/hir_ty/src/traits/chalk/mapping.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ impl ToChalk for Ty {
3131
TypeCtor::Ref(m) => ref_to_chalk(db, m, apply_ty.parameters),
3232
TypeCtor::Array => array_to_chalk(db, apply_ty.parameters),
3333
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));
3536
chalk_ir::TyKind::Function(chalk_ir::FnPointer {
3637
num_binders: 0,
3738
sig: chalk_ir::FnSig {
@@ -183,7 +184,7 @@ impl ToChalk for Ty {
183184
assert_eq!(num_binders, 0);
184185
let parameters: Substs = from_chalk(
185186
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"),
187188
);
188189
Ty::Apply(ApplicationTy {
189190
ctor: TypeCtor::FnPtr {
@@ -536,6 +537,7 @@ impl ToChalk for GenericPredicate {
536537
// we don't produce any where clauses with binders and can't currently deal with them
537538
match where_clause
538539
.skip_binders()
540+
.clone()
539541
.shifted_out(&Interner)
540542
.expect("unexpected bound vars in where clause")
541543
{
@@ -661,7 +663,12 @@ where
661663
chalk_ir::TyVariableKind::Integer => TyKind::Integer,
662664
chalk_ir::TyVariableKind::Float => TyKind::Float,
663665
},
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,
665672
chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"),
666673
})
667674
.collect();

0 commit comments

Comments
 (0)