aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorBenjamin Coenen <[email protected]>2020-05-02 19:27:02 +0100
committerBenjamin Coenen <[email protected]>2020-05-02 19:27:02 +0100
commit4613497a7714c6cd87166e6525d764d75f8acefd (patch)
tree2527ae2c0ef2ef100efee3fcb8899f8e34d0d573 /crates/ra_hir_ty
parent19e28888aa41b2845b47adb7314aed99d3c48679 (diff)
parent89e1f97515c36ab97bd378d972cabec0feb6d77e (diff)
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer into fix_4202
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/Cargo.toml2
-rw-r--r--crates/ra_hir_ty/src/lib.rs3
-rw-r--r--crates/ra_hir_ty/src/lower.rs143
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs66
-rw-r--r--crates/ra_hir_ty/src/tests/simple.rs32
5 files changed, 189 insertions, 57 deletions
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml
index 04d3cd6a2..65db6d1b0 100644
--- a/crates/ra_hir_ty/Cargo.toml
+++ b/crates/ra_hir_ty/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
11itertools = "0.9.0" 11itertools = "0.9.0"
12arrayvec = "0.5.1" 12arrayvec = "0.5.1"
13smallvec = "1.2.0" 13smallvec = "1.2.0"
14ena = "0.13.1" 14ena = "0.14.0"
15log = "0.4.8" 15log = "0.4.8"
16rustc-hash = "1.1.0" 16rustc-hash = "1.1.0"
17 17
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index a8ef32ec5..a6f56c661 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -66,7 +66,8 @@ pub use autoderef::autoderef;
66pub use infer::{InferTy, InferenceResult}; 66pub use infer::{InferTy, InferenceResult};
67pub use lower::CallableDef; 67pub use lower::CallableDef;
68pub use lower::{ 68pub use lower::{
69 callable_item_sig, ImplTraitLoweringMode, TyDefId, TyLoweringContext, ValueTyDefId, 69 associated_type_shorthand_candidates, callable_item_sig, ImplTraitLoweringMode, TyDefId,
70 TyLoweringContext, ValueTyDefId,
70}; 71};
71pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 72pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
72 73
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs
index a6f893037..9ad6dbe07 100644
--- a/crates/ra_hir_ty/src/lower.rs
+++ b/crates/ra_hir_ty/src/lower.rs
@@ -17,9 +17,9 @@ use hir_def::{
17 path::{GenericArg, Path, PathSegment, PathSegments}, 17 path::{GenericArg, Path, PathSegment, PathSegments},
18 resolver::{HasResolver, Resolver, TypeNs}, 18 resolver::{HasResolver, Resolver, TypeNs},
19 type_ref::{TypeBound, TypeRef}, 19 type_ref::{TypeBound, TypeRef},
20 AdtId, AssocContainerId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, 20 AdtId, AssocContainerId, AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId,
21 ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, 21 HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, TypeParamId,
22 VariantId, 22 UnionId, VariantId,
23}; 23};
24use ra_arena::map::ArenaMap; 24use ra_arena::map::ArenaMap;
25use ra_db::CrateId; 25use ra_db::CrateId;
@@ -34,6 +34,7 @@ use crate::{
34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, 34 Binders, BoundVar, DebruijnIndex, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate,
35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, 35 ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
36}; 36};
37use hir_expand::name::Name;
37 38
38#[derive(Debug)] 39#[derive(Debug)]
39pub struct TyLoweringContext<'a> { 40pub struct TyLoweringContext<'a> {
@@ -383,61 +384,38 @@ impl Ty {
383 res: Option<TypeNs>, 384 res: Option<TypeNs>,
384 segment: PathSegment<'_>, 385 segment: PathSegment<'_>,
385 ) -> Ty { 386 ) -> Ty {
386 let traits_from_env: Vec<_> = match res { 387 if let Some(res) = res {
387 Some(TypeNs::SelfType(impl_id)) => match ctx.db.impl_trait(impl_id) { 388 let ty =
388 None => return Ty::Unknown, 389 associated_type_shorthand_candidates(ctx.db, res, move |name, t, associated_ty| {
389 Some(trait_ref) => vec![trait_ref.value], 390 if name == segment.name {
390 }, 391 let substs = match ctx.type_param_mode {
391 Some(TypeNs::GenericParam(param_id)) => { 392 TypeParamLoweringMode::Placeholder => {
392 let predicates = ctx.db.generic_predicates_for_param(param_id); 393 // if we're lowering to placeholders, we have to put
393 let mut traits_: Vec<_> = predicates 394 // them in now
394 .iter() 395 let s = Substs::type_params(
395 .filter_map(|pred| match &pred.value { 396 ctx.db,
396 GenericPredicate::Implemented(tr) => Some(tr.clone()), 397 ctx.resolver.generic_def().expect(
397 _ => None, 398 "there should be generics if there's a generic param",
398 }) 399 ),
399 .collect(); 400 );
400 // Handle `Self::Type` referring to own associated type in trait definitions 401 t.substs.clone().subst_bound_vars(&s)
401 if let GenericDefId::TraitId(trait_id) = param_id.parent { 402 }
402 let generics = generics(ctx.db.upcast(), trait_id.into()); 403 TypeParamLoweringMode::Variable => t.substs.clone(),
403 if generics.params.types[param_id.local_id].provenance
404 == TypeParamProvenance::TraitSelf
405 {
406 let trait_ref = TraitRef {
407 trait_: trait_id,
408 substs: Substs::bound_vars(&generics, DebruijnIndex::INNERMOST),
409 }; 404 };
410 traits_.push(trait_ref); 405 // FIXME handle type parameters on the segment
406 return Some(Ty::Projection(ProjectionTy {
407 associated_ty,
408 parameters: substs,
409 }));
411 } 410 }
412 } 411
413 traits_ 412 None
414 } 413 });
415 _ => return Ty::Unknown, 414
416 }; 415 ty.unwrap_or(Ty::Unknown)
417 let traits = traits_from_env.into_iter().flat_map(|t| all_super_trait_refs(ctx.db, t)); 416 } else {
418 for t in traits { 417 Ty::Unknown
419 if let Some(associated_ty) =
420 ctx.db.trait_data(t.trait_).associated_type_by_name(&segment.name)
421 {
422 let substs = match ctx.type_param_mode {
423 TypeParamLoweringMode::Placeholder => {
424 // if we're lowering to placeholders, we have to put
425 // them in now
426 let s = Substs::type_params(
427 ctx.db,
428 ctx.resolver
429 .generic_def()
430 .expect("there should be generics if there's a generic param"),
431 );
432 t.substs.subst_bound_vars(&s)
433 }
434 TypeParamLoweringMode::Variable => t.substs,
435 };
436 // FIXME handle (forbid) type parameters on the segment
437 return Ty::Projection(ProjectionTy { associated_ty, parameters: substs });
438 }
439 } 418 }
440 Ty::Unknown
441 } 419 }
442 420
443 fn from_hir_path_inner( 421 fn from_hir_path_inner(
@@ -694,6 +672,61 @@ pub fn callable_item_sig(db: &dyn HirDatabase, def: CallableDef) -> PolyFnSig {
694 } 672 }
695} 673}
696 674
675pub fn associated_type_shorthand_candidates<R>(
676 db: &dyn HirDatabase,
677 res: TypeNs,
678 mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
679) -> Option<R> {
680 let traits_from_env: Vec<_> = match res {
681 TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) {
682 None => vec![],
683 Some(trait_ref) => vec![trait_ref.value],
684 },
685 TypeNs::GenericParam(param_id) => {
686 let predicates = db.generic_predicates_for_param(param_id);
687 let mut traits_: Vec<_> = predicates
688 .iter()
689 .filter_map(|pred| match &pred.value {
690 GenericPredicate::Implemented(tr) => Some(tr.clone()),
691 _ => None,
692 })
693 .collect();
694 // Handle `Self::Type` referring to own associated type in trait definitions
695 if let GenericDefId::TraitId(trait_id) = param_id.parent {
696 let generics = generics(db.upcast(), trait_id.into());
697 if generics.params.types[param_id.local_id].provenance
698 == TypeParamProvenance::TraitSelf
699 {
700 let trait_ref = TraitRef {
701 trait_: trait_id,
702 substs: Substs::bound_vars(&generics, DebruijnIndex::INNERMOST),
703 };
704 traits_.push(trait_ref);
705 }
706 }
707 traits_
708 }
709 _ => vec![],
710 };
711
712 for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) {
713 let data = db.trait_data(t.trait_);
714
715 for (name, assoc_id) in &data.items {
716 match assoc_id {
717 AssocItemId::TypeAliasId(alias) => {
718 if let Some(result) = cb(name, &t, *alias) {
719 return Some(result);
720 }
721 }
722 AssocItemId::FunctionId(_) | AssocItemId::ConstId(_) => {}
723 }
724 }
725 }
726
727 None
728}
729
697/// Build the type of all specific fields of a struct or enum variant. 730/// Build the type of all specific fields of a struct or enum variant.
698pub(crate) fn field_types_query( 731pub(crate) fn field_types_query(
699 db: &dyn HirDatabase, 732 db: &dyn HirDatabase,
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 5ddecbdc6..29e38a06c 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -339,6 +339,46 @@ pub fn baz() -> usize { 31usize }
339} 339}
340 340
341#[test] 341#[test]
342fn infer_macro_with_dollar_crate_is_correct_in_trait_associate_type() {
343 let (db, pos) = TestDB::with_position(
344 r#"
345//- /main.rs crate:main deps:foo
346use foo::Trait;
347
348fn test() {
349 let msg = foo::Message(foo::MessageRef);
350 let r = msg.deref();
351 r<|>;
352}
353
354//- /lib.rs crate:foo
355pub struct MessageRef;
356pub struct Message(MessageRef);
357
358pub trait Trait {
359 type Target;
360 fn deref(&self) -> &Self::Target;
361}
362
363#[macro_export]
364macro_rules! expand {
365 () => {
366 impl Trait for Message {
367 type Target = $crate::MessageRef;
368 fn deref(&self) -> &Self::Target {
369 &self.0
370 }
371 }
372 }
373}
374
375expand!();
376"#,
377 );
378 assert_eq!("&MessageRef", type_at_pos(&db, pos));
379}
380
381#[test]
342fn infer_type_value_non_legacy_macro_use_as() { 382fn infer_type_value_non_legacy_macro_use_as() {
343 assert_snapshot!( 383 assert_snapshot!(
344 infer(r#" 384 infer(r#"
@@ -388,6 +428,32 @@ fn main() {
388} 428}
389 429
390#[test] 430#[test]
431fn infer_local_inner_macros() {
432 let (db, pos) = TestDB::with_position(
433 r#"
434//- /main.rs crate:main deps:foo
435fn test() {
436 let x = foo::foo!(1);
437 x<|>;
438}
439
440//- /lib.rs crate:foo
441#[macro_export(local_inner_macros)]
442macro_rules! foo {
443 (1) => { bar!() };
444}
445
446#[macro_export]
447macro_rules! bar {
448 () => { 42 }
449}
450
451"#,
452 );
453 assert_eq!("i32", type_at_pos(&db, pos));
454}
455
456#[test]
391fn infer_builtin_macros_line() { 457fn infer_builtin_macros_line() {
392 assert_snapshot!( 458 assert_snapshot!(
393 infer(r#" 459 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs
index 56abc65b8..3d3088965 100644
--- a/crates/ra_hir_ty/src/tests/simple.rs
+++ b/crates/ra_hir_ty/src/tests/simple.rs
@@ -1755,3 +1755,35 @@ fn main() {
1755 "### 1755 "###
1756 ); 1756 );
1757} 1757}
1758
1759#[test]
1760fn effects_smoke_test() {
1761 assert_snapshot!(
1762 infer(r#"
1763fn main() {
1764 let x = unsafe { 92 };
1765 let y = async { async { () }.await };
1766 let z = try { () };
1767 let t = 'a: { 92 };
1768}
1769"#),
1770 @r###"
1771 11..131 '{ ...2 }; }': ()
1772 21..22 'x': i32
1773 32..38 '{ 92 }': i32
1774 34..36 '92': i32
1775 48..49 'y': {unknown}
1776 58..80 '{ asyn...wait }': {unknown}
1777 60..78 'async ....await': {unknown}
1778 66..72 '{ () }': ()
1779 68..70 '()': ()
1780 90..91 'z': {unknown}
1781 94..104 'try { () }': {unknown}
1782 98..104 '{ () }': ()
1783 100..102 '()': ()
1784 114..115 't': i32
1785 122..128 '{ 92 }': i32
1786 124..126 '92': i32
1787 "###
1788 )
1789}