Skip to content

Commit ce07a2d

Browse files
Merge #2636
2636: Chalk update and refactoring r=flodiebold a=flodiebold This updates the Chalk integration to rust-lang/chalk#311, which will presumably get merged soon, and refactors it some more, most notably introducing our own `TypeFamily` instead of reusing `ChalkIr`. It's still mostly the same as `ChalkIr` though, except for using Salsa `InternId`s directly. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents 31c5888 + 1f7f457 commit ce07a2d

File tree

8 files changed

+354
-306
lines changed

8 files changed

+354
-306
lines changed

Cargo.lock

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

crates/ra_hir_ty/Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ ra_prof = { path = "../ra_prof" }
2121
ra_syntax = { path = "../ra_syntax" }
2222
test_utils = { path = "../test_utils" }
2323

24-
# https://github.com/rust-lang/chalk/pull/294
25-
chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" }
26-
chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" }
27-
chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" }
24+
chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
25+
chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
26+
chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" }
2827

2928
lalrpop-intern = "0.15.1"
3029

crates/ra_hir_ty/src/db.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use ra_db::{salsa, CrateId};
1010

1111
use crate::{
1212
method_resolution::CrateImplBlocks,
13-
traits::{AssocTyValue, Impl},
13+
traits::{chalk, AssocTyValue, Impl},
1414
CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor,
1515
ValueTyDefId,
1616
};
@@ -77,39 +77,24 @@ pub trait HirDatabase: DefDatabase {
7777
#[salsa::interned]
7878
fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId;
7979

80-
#[salsa::invoke(crate::traits::chalk::associated_ty_data_query)]
81-
fn associated_ty_data(
82-
&self,
83-
id: chalk_ir::TypeId,
84-
) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>;
80+
#[salsa::invoke(chalk::associated_ty_data_query)]
81+
fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>;
8582

86-
#[salsa::invoke(crate::traits::chalk::trait_datum_query)]
87-
fn trait_datum(
88-
&self,
89-
krate: CrateId,
90-
trait_id: chalk_ir::TraitId,
91-
) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>;
83+
#[salsa::invoke(chalk::trait_datum_query)]
84+
fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>;
9285

93-
#[salsa::invoke(crate::traits::chalk::struct_datum_query)]
94-
fn struct_datum(
95-
&self,
96-
krate: CrateId,
97-
struct_id: chalk_ir::StructId,
98-
) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>;
86+
#[salsa::invoke(chalk::struct_datum_query)]
87+
fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc<chalk::StructDatum>;
9988

10089
#[salsa::invoke(crate::traits::chalk::impl_datum_query)]
101-
fn impl_datum(
102-
&self,
103-
krate: CrateId,
104-
impl_id: chalk_ir::ImplId,
105-
) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>;
90+
fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>;
10691

10792
#[salsa::invoke(crate::traits::chalk::associated_ty_value_query)]
10893
fn associated_ty_value(
10994
&self,
11095
krate: CrateId,
111-
id: chalk_rust_ir::AssociatedTyValueId,
112-
) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>;
96+
id: chalk::AssociatedTyValueId,
97+
) -> Arc<chalk::AssociatedTyValue>;
11398

11499
#[salsa::invoke(crate::traits::trait_solve_query)]
115100
fn trait_solve(

crates/ra_hir_ty/src/tests/method_resolution.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -865,7 +865,7 @@ mod foo {
865865

866866
#[test]
867867
fn method_resolution_where_clause_for_unknown_trait() {
868-
// The blanket impl shouldn't apply because we can't even resolve UnknownTrait
868+
// The blanket impl currently applies because we ignore the unresolved where clause
869869
let t = type_at(
870870
r#"
871871
//- /main.rs
@@ -875,7 +875,7 @@ impl<T> Trait for T where T: UnknownTrait {}
875875
fn test() { (&S).foo()<|>; }
876876
"#,
877877
);
878-
assert_eq!(t, "{unknown}");
878+
assert_eq!(t, "u128");
879879
}
880880

881881
#[test]

crates/ra_hir_ty/src/tests/traits.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,23 @@ fn test() {
958958
);
959959
}
960960

961+
#[test]
962+
fn error_bound_chalk() {
963+
let t = type_at(
964+
r#"
965+
//- /main.rs
966+
trait Trait {
967+
fn foo(&self) -> u32 {}
968+
}
969+
970+
fn test(x: (impl Trait + UnknownTrait)) {
971+
x.foo()<|>;
972+
}
973+
"#,
974+
);
975+
assert_eq!(t, "u32");
976+
}
977+
961978
#[test]
962979
fn assoc_type_bindings() {
963980
assert_snapshot!(

crates/ra_hir_ty/src/traits.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Trait solving using Chalk.
22
use std::sync::{Arc, Mutex};
33

4-
use chalk_ir::{cast::Cast, family::ChalkIr};
4+
use chalk_ir::cast::Cast;
55
use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId};
66
use log::debug;
77
use ra_db::{impl_intern_key, salsa, CrateId};
@@ -12,15 +12,15 @@ use crate::db::HirDatabase;
1212

1313
use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
1414

15-
use self::chalk::{from_chalk, ToChalk};
15+
use self::chalk::{from_chalk, ToChalk, TypeFamily};
1616

1717
pub(crate) mod chalk;
1818
mod builtin;
1919

2020
#[derive(Debug, Clone)]
2121
pub struct TraitSolver {
2222
krate: CrateId,
23-
inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>,
23+
inner: Arc<Mutex<chalk_solve::Solver<TypeFamily>>>,
2424
}
2525

2626
/// We need eq for salsa
@@ -36,8 +36,8 @@ impl TraitSolver {
3636
fn solve(
3737
&self,
3838
db: &impl HirDatabase,
39-
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>,
40-
) -> Option<chalk_solve::Solution<ChalkIr>> {
39+
goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<TypeFamily>>>,
40+
) -> Option<chalk_solve::Solution<TypeFamily>> {
4141
let context = ChalkContext { db, krate: self.krate };
4242
debug!("solve goal: {:?}", goal);
4343
let mut solver = match self.inner.lock() {
@@ -201,17 +201,17 @@ pub(crate) fn trait_solve_query(
201201

202202
fn solution_from_chalk(
203203
db: &impl HirDatabase,
204-
solution: chalk_solve::Solution<ChalkIr>,
204+
solution: chalk_solve::Solution<TypeFamily>,
205205
) -> Solution {
206-
let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| {
206+
let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<TypeFamily>>| {
207207
let value = subst
208208
.value
209209
.parameters
210210
.into_iter()
211211
.map(|p| {
212-
let ty = match p {
213-
chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty),
214-
chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(),
212+
let ty = match p.ty() {
213+
Some(ty) => from_chalk(db, ty.clone()),
214+
None => unimplemented!(),
215215
};
216216
ty
217217
})
@@ -291,7 +291,7 @@ impl FnTrait {
291291
}
292292
}
293293

294-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
294+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
295295
pub struct ClosureFnTraitImplData {
296296
def: DefWithBodyId,
297297
expr: ExprId,
@@ -300,7 +300,7 @@ pub struct ClosureFnTraitImplData {
300300

301301
/// An impl. Usually this comes from an impl block, but some built-in types get
302302
/// synthetic impls.
303-
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
303+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
304304
pub enum Impl {
305305
/// A normal impl from an impl block.
306306
ImplBlock(ImplId),

crates/ra_hir_ty/src/traits/builtin.rs

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls(
2828
trait_: TraitId,
2929
mut callback: impl FnMut(Impl),
3030
) {
31+
// Note: since impl_datum needs to be infallible, we need to make sure here
32+
// that we have all prerequisites to build the respective impls.
3133
if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty {
3234
for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter()
3335
{
3436
if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) {
3537
if trait_ == actual_trait {
3638
let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait };
37-
callback(Impl::ClosureFnTraitImpl(impl_));
39+
if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) {
40+
callback(Impl::ClosureFnTraitImpl(impl_));
41+
}
3842
}
3943
}
4044
}
4145
}
4246
}
4347

44-
pub(super) fn impl_datum(
45-
db: &impl HirDatabase,
46-
krate: CrateId,
47-
impl_: Impl,
48-
) -> Option<BuiltinImplData> {
48+
pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData {
4949
match impl_ {
5050
Impl::ImplBlock(_) => unreachable!(),
5151
Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data),
@@ -65,21 +65,38 @@ pub(super) fn associated_ty_value(
6565
}
6666
}
6767

68+
fn check_closure_fn_trait_impl_prerequisites(
69+
db: &impl HirDatabase,
70+
krate: CrateId,
71+
data: super::ClosureFnTraitImplData,
72+
) -> bool {
73+
// the respective Fn/FnOnce/FnMut trait needs to exist
74+
if get_fn_trait(db, krate, data.fn_trait).is_none() {
75+
return false;
76+
}
77+
78+
// FIXME: there are more assumptions that we should probably check here:
79+
// the traits having no type params, FnOnce being a supertrait
80+
81+
// the FnOnce trait needs to exist and have an assoc type named Output
82+
let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) {
83+
Some(t) => t,
84+
None => return false,
85+
};
86+
db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some()
87+
}
88+
6889
fn closure_fn_trait_impl_datum(
6990
db: &impl HirDatabase,
7091
krate: CrateId,
7192
data: super::ClosureFnTraitImplData,
72-
) -> Option<BuiltinImplData> {
93+
) -> BuiltinImplData {
7394
// for some closure |X, Y| -> Z:
7495
// impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V }
7596

76-
let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait
77-
78-
// validate FnOnce trait, since we need it in the assoc ty value definition
79-
// and don't want to return a valid value only to find out later that FnOnce
80-
// is broken
81-
let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?;
82-
let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
97+
let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait
98+
// the existence of the Fn trait has been checked before
99+
.expect("fn trait for closure impl missing");
83100

84101
let num_args: u16 = match &db.body(data.def.into())[data.expr] {
85102
Expr::Lambda { args, .. } => args.len() as u16,
@@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum(
107124

108125
let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone());
109126

110-
Some(BuiltinImplData {
127+
BuiltinImplData {
111128
num_vars: num_args as usize + 1,
112129
trait_ref,
113130
where_clauses: Vec::new(),
114131
assoc_ty_values: vec![output_ty_id],
115-
})
132+
}
116133
}
117134

118135
fn closure_fn_trait_output_assoc_ty_value(

0 commit comments

Comments
 (0)