diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-04 19:07:09 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-05-04 19:07:09 +0100 |
commit | 9c49f6c36e1e097f938946811d1e2f5eb70edca9 (patch) | |
tree | 544bfd290a08475b1d5250bcc5e0717779b53758 /crates/ra_hir/src/ty/lower.rs | |
parent | b6ffb1d2a3bcc94e41c95c7a086117e11ce487e5 (diff) | |
parent | a4eb1a546c7623f65823c5e249cd3c6d8c90fd8c (diff) |
Merge #1216
1216: Basic Chalk integration r=matklad a=flodiebold
This replaces the ad-hoc `implements` check by Chalk. It doesn't yet any new functionality (e.g. where clauses aren't passed to Chalk yet). The tests that exist actually work, but it needs some refactoring, currently crashes when running analysis on the RA repo, and depends on rust-lang/chalk#216 which isn't merged yet :smile:
The main work here is converting stuff back and forth and providing Chalk with the information it needs, and the canonicalization logic. Since canonicalization depends a lot on the inference table, I don't think we can currently reuse the logic from Chalk, so we need to implement it ourselves; it's not actually that complicated anyway ;) I realized that we need a `Ty::Bound` variant separate from `Ty::Param` -- these are two different things, and I think type parameters inside a function actually need to be represented in Chalk as `Placeholder` types.
~~Currently this crashes in the 'real' world because we don't yet do canonicalization when filtering method candidates. Proper canonicalization needs the inference table (to collapse different inference variables that have already been unified), but we need to be able to call the method candidate selection from the completion code... So I'm currently thinking how to best handle that :smile:~~
Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 37 |
1 files changed, 17 insertions, 20 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 7fac084ce..8bab7e54b 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -29,7 +29,10 @@ impl Ty { | |||
29 | TypeRef::Tuple(inner) => { | 29 | TypeRef::Tuple(inner) => { |
30 | let inner_tys = | 30 | let inner_tys = |
31 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 31 | inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
32 | Ty::apply(TypeCtor::Tuple, Substs(inner_tys.into())) | 32 | Ty::apply( |
33 | TypeCtor::Tuple { cardinality: inner_tys.len() as u16 }, | ||
34 | Substs(inner_tys.into()), | ||
35 | ) | ||
33 | } | 36 | } |
34 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), | 37 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), |
35 | TypeRef::RawPtr(inner, mutability) => { | 38 | TypeRef::RawPtr(inner, mutability) => { |
@@ -53,7 +56,7 @@ impl Ty { | |||
53 | let inner_tys = | 56 | let inner_tys = |
54 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); | 57 | params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); |
55 | let sig = Substs(inner_tys.into()); | 58 | let sig = Substs(inner_tys.into()); |
56 | Ty::apply(TypeCtor::FnPtr, sig) | 59 | Ty::apply(TypeCtor::FnPtr { num_args: sig.len() as u16 - 1 }, sig) |
57 | } | 60 | } |
58 | TypeRef::Error => Ty::Unknown, | 61 | TypeRef::Error => Ty::Unknown, |
59 | } | 62 | } |
@@ -238,6 +241,11 @@ impl TraitRef { | |||
238 | let segment = path.segments.last().expect("path should have at least one segment"); | 241 | let segment = path.segments.last().expect("path should have at least one segment"); |
239 | substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true) | 242 | substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true) |
240 | } | 243 | } |
244 | |||
245 | pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { | ||
246 | let substs = Substs::identity(&trait_.generic_params(db)); | ||
247 | TraitRef { trait_, substs } | ||
248 | } | ||
241 | } | 249 | } |
242 | 250 | ||
243 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 251 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
@@ -299,7 +307,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | |||
299 | /// function body. | 307 | /// function body. |
300 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 308 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
301 | let generics = def.generic_params(db); | 309 | let generics = def.generic_params(db); |
302 | let substs = make_substs(&generics); | 310 | let substs = Substs::identity(&generics); |
303 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 311 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
304 | } | 312 | } |
305 | 313 | ||
@@ -341,7 +349,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | |||
341 | return type_for_struct(db, def); // Unit struct | 349 | return type_for_struct(db, def); // Unit struct |
342 | } | 350 | } |
343 | let generics = def.generic_params(db); | 351 | let generics = def.generic_params(db); |
344 | let substs = make_substs(&generics); | 352 | let substs = Substs::identity(&generics); |
345 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 353 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
346 | } | 354 | } |
347 | 355 | ||
@@ -357,7 +365,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) | |||
357 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 365 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
358 | .collect::<Vec<_>>(); | 366 | .collect::<Vec<_>>(); |
359 | let generics = def.parent_enum(db).generic_params(db); | 367 | let generics = def.parent_enum(db).generic_params(db); |
360 | let substs = make_substs(&generics); | 368 | let substs = Substs::identity(&generics); |
361 | let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs); | 369 | let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs); |
362 | FnSig::from_params_and_return(params, ret) | 370 | FnSig::from_params_and_return(params, ret) |
363 | } | 371 | } |
@@ -369,36 +377,25 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> | |||
369 | return type_for_enum(db, def.parent_enum(db)); // Unit variant | 377 | return type_for_enum(db, def.parent_enum(db)); // Unit variant |
370 | } | 378 | } |
371 | let generics = def.parent_enum(db).generic_params(db); | 379 | let generics = def.parent_enum(db).generic_params(db); |
372 | let substs = make_substs(&generics); | 380 | let substs = Substs::identity(&generics); |
373 | Ty::apply(TypeCtor::FnDef(def.into()), substs) | 381 | Ty::apply(TypeCtor::FnDef(def.into()), substs) |
374 | } | 382 | } |
375 | 383 | ||
376 | fn make_substs(generics: &GenericParams) -> Substs { | ||
377 | Substs( | ||
378 | generics | ||
379 | .params_including_parent() | ||
380 | .into_iter() | ||
381 | .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() }) | ||
382 | .collect::<Vec<_>>() | ||
383 | .into(), | ||
384 | ) | ||
385 | } | ||
386 | |||
387 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 384 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
388 | let generics = s.generic_params(db); | 385 | let generics = s.generic_params(db); |
389 | Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) | 386 | Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics)) |
390 | } | 387 | } |
391 | 388 | ||
392 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 389 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
393 | let generics = s.generic_params(db); | 390 | let generics = s.generic_params(db); |
394 | Ty::apply(TypeCtor::Adt(s.into()), make_substs(&generics)) | 391 | Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics)) |
395 | } | 392 | } |
396 | 393 | ||
397 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 394 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { |
398 | let generics = t.generic_params(db); | 395 | let generics = t.generic_params(db); |
399 | let resolver = t.resolver(db); | 396 | let resolver = t.resolver(db); |
400 | let type_ref = t.type_ref(db); | 397 | let type_ref = t.type_ref(db); |
401 | let substs = make_substs(&generics); | 398 | let substs = Substs::identity(&generics); |
402 | let inner = Ty::from_hir(db, &resolver, &type_ref); | 399 | let inner = Ty::from_hir(db, &resolver, &type_ref); |
403 | inner.subst(&substs) | 400 | inner.subst(&substs) |
404 | } | 401 | } |