Skip to content

Commit 4053fcf

Browse files
committed
Introduce our own Chalk TypeFamily, instead of using ChalkIr
It's not very different, except we can directly use Salsa IDs instead of casting them. This means we need to refactor the handling of errors to get rid of UNKNOWN_TRAIT though.
1 parent 6b5efe5 commit 4053fcf

File tree

4 files changed

+126
-87
lines changed

4 files changed

+126
-87
lines changed

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/traits.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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)