aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/body/lower.rs19
-rw-r--r--crates/ra_hir_def/src/db.rs12
-rw-r--r--crates/ra_hir_def/src/find_path.rs45
-rw-r--r--crates/ra_hir_ty/src/lib.rs14
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs10
-rw-r--r--crates/ra_hir_ty/src/tests/method_resolution.rs31
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs31
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs132
-rw-r--r--crates/ra_mbe/src/mbe_expander/transcriber.rs33
-rw-r--r--crates/ra_parser/src/lib.rs2
-rw-r--r--crates/ra_parser/src/parser.rs2
-rw-r--r--crates/ra_syntax/src/syntax_node.rs2
-rw-r--r--crates/ra_tt/src/buffer.rs4
-rw-r--r--crates/rust-analyzer/src/config.rs41
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs166
15 files changed, 409 insertions, 135 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 443b057ab..c69e0efea 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -60,13 +60,10 @@ pub(super) fn lower(
60 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
61 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
62) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
65 ExprCollector { 63 ExprCollector {
66 db, 64 db,
67 def, 65 def,
68 expander, 66 expander,
69 ctx,
70 source_map: BodySourceMap::default(), 67 source_map: BodySourceMap::default(),
71 body: Body { 68 body: Body {
72 exprs: Arena::default(), 69 exprs: Arena::default(),
@@ -83,7 +80,6 @@ struct ExprCollector<'a> {
83 db: &'a dyn DefDatabase, 80 db: &'a dyn DefDatabase,
84 def: DefWithBodyId, 81 def: DefWithBodyId,
85 expander: Expander, 82 expander: Expander,
86 ctx: LowerCtx,
87 body: Body, 83 body: Body,
88 source_map: BodySourceMap, 84 source_map: BodySourceMap,
89} 85}
@@ -122,6 +118,10 @@ impl ExprCollector<'_> {
122 (self.body, self.source_map) 118 (self.body, self.source_map)
123 } 119 }
124 120
121 fn ctx(&self) -> LowerCtx {
122 LowerCtx::new(self.db, self.expander.current_file_id)
123 }
124
125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId { 125 fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr<ast::Expr>) -> ExprId {
126 let src = self.expander.to_source(ptr); 126 let src = self.expander.to_source(ptr);
127 let id = self.make_expr(expr, Ok(src.clone())); 127 let id = self.make_expr(expr, Ok(src.clone()));
@@ -268,7 +268,7 @@ impl ExprCollector<'_> {
268 }; 268 };
269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 269 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
270 let generic_args = 270 let generic_args =
271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it)); 271 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it));
272 self.alloc_expr( 272 self.alloc_expr(
273 Expr::MethodCall { receiver, method_name, args, generic_args }, 273 Expr::MethodCall { receiver, method_name, args, generic_args },
274 syntax_ptr, 274 syntax_ptr,
@@ -373,7 +373,7 @@ impl ExprCollector<'_> {
373 } 373 }
374 ast::Expr::CastExpr(e) => { 374 ast::Expr::CastExpr(e) => {
375 let expr = self.collect_expr_opt(e.expr()); 375 let expr = self.collect_expr_opt(e.expr());
376 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref()); 376 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.type_ref());
377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 377 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
378 } 378 }
379 ast::Expr::RefExpr(e) => { 379 ast::Expr::RefExpr(e) => {
@@ -396,7 +396,7 @@ impl ExprCollector<'_> {
396 for param in pl.params() { 396 for param in pl.params() {
397 let pat = self.collect_pat_opt(param.pat()); 397 let pat = self.collect_pat_opt(param.pat());
398 let type_ref = 398 let type_ref =
399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 399 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
400 args.push(pat); 400 args.push(pat);
401 arg_types.push(type_ref); 401 arg_types.push(type_ref);
402 } 402 }
@@ -404,7 +404,7 @@ impl ExprCollector<'_> {
404 let ret_type = e 404 let ret_type = e
405 .ret_type() 405 .ret_type()
406 .and_then(|r| r.type_ref()) 406 .and_then(|r| r.type_ref())
407 .map(|it| TypeRef::from_ast(&self.ctx, it)); 407 .map(|it| TypeRef::from_ast(&self.ctx(), it));
408 let body = self.collect_expr_opt(e.body()); 408 let body = self.collect_expr_opt(e.body());
409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 409 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
410 } 410 }
@@ -507,7 +507,8 @@ impl ExprCollector<'_> {
507 .map(|s| match s { 507 .map(|s| match s {
508 ast::Stmt::LetStmt(stmt) => { 508 ast::Stmt::LetStmt(stmt) => {
509 let pat = self.collect_pat_opt(stmt.pat()); 509 let pat = self.collect_pat_opt(stmt.pat());
510 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it)); 510 let type_ref =
511 stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx(), it));
511 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 512 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
512 Statement::Let { pat, type_ref, initializer } 513 Statement::Let { pat, type_ref, initializer }
513 } 514 }
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index e665ab45d..2f71511ba 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -1,7 +1,7 @@
1//! Defines database & queries for name resolution. 1//! Defines database & queries for name resolution.
2use std::sync::Arc; 2use std::sync::Arc;
3 3
4use hir_expand::{db::AstDatabase, HirFileId}; 4use hir_expand::{db::AstDatabase, name::Name, HirFileId};
5use ra_db::{salsa, CrateId, SourceDatabase, Upcast}; 5use ra_db::{salsa, CrateId, SourceDatabase, Upcast};
6use ra_prof::profile; 6use ra_prof::profile;
7use ra_syntax::SmolStr; 7use ra_syntax::SmolStr;
@@ -12,9 +12,12 @@ use crate::{
12 body::{scope::ExprScopes, Body, BodySourceMap}, 12 body::{scope::ExprScopes, Body, BodySourceMap},
13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, 13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 docs::Documentation, 14 docs::Documentation,
15 find_path,
15 generics::GenericParams, 16 generics::GenericParams,
17 item_scope::ItemInNs,
16 lang_item::{LangItemTarget, LangItems}, 18 lang_item::{LangItemTarget, LangItems},
17 nameres::{raw::RawItems, CrateDefMap}, 19 nameres::{raw::RawItems, CrateDefMap},
20 visibility::Visibility,
18 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, 21 AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc,
19 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, 22 GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId,
20 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, 23 TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc,
@@ -108,6 +111,13 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
108 // Remove this query completely, in favor of `Attrs::docs` method 111 // Remove this query completely, in favor of `Attrs::docs` method
109 #[salsa::invoke(Documentation::documentation_query)] 112 #[salsa::invoke(Documentation::documentation_query)]
110 fn documentation(&self, def: AttrDefId) -> Option<Documentation>; 113 fn documentation(&self, def: AttrDefId) -> Option<Documentation>;
114
115 #[salsa::invoke(find_path::importable_locations_of_query)]
116 fn importable_locations_of(
117 &self,
118 item: ItemInNs,
119 krate: CrateId,
120 ) -> Arc<[(ModuleId, Name, Visibility)]>;
111} 121}
112 122
113fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> { 123fn crate_def_map_wait(db: &impl DefDatabase, krate: CrateId) -> Arc<CrateDefMap> {
diff --git a/crates/ra_hir_def/src/find_path.rs b/crates/ra_hir_def/src/find_path.rs
index 70dcb03e6..2eb12ec8f 100644
--- a/crates/ra_hir_def/src/find_path.rs
+++ b/crates/ra_hir_def/src/find_path.rs
@@ -1,5 +1,11 @@
1//! An algorithm to find a path to refer to a certain item. 1//! An algorithm to find a path to refer to a certain item.
2 2
3use std::sync::Arc;
4
5use hir_expand::name::{known, AsName, Name};
6use ra_prof::profile;
7use test_utils::tested_by;
8
3use crate::{ 9use crate::{
4 db::DefDatabase, 10 db::DefDatabase,
5 item_scope::ItemInNs, 11 item_scope::ItemInNs,
@@ -7,25 +13,28 @@ use crate::{
7 visibility::Visibility, 13 visibility::Visibility,
8 CrateId, ModuleDefId, ModuleId, 14 CrateId, ModuleDefId, ModuleId,
9}; 15};
10use hir_expand::name::{known, AsName, Name}; 16
11use test_utils::tested_by; 17// FIXME: handle local items
18
19/// Find a path that can be used to refer to a certain item. This can depend on
20/// *from where* you're referring to the item, hence the `from` parameter.
21pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
22 let _p = profile("find_path");
23 find_path_inner(db, item, from, MAX_PATH_LEN)
24}
12 25
13const MAX_PATH_LEN: usize = 15; 26const MAX_PATH_LEN: usize = 15;
14 27
15impl ModPath { 28impl ModPath {
16 fn starts_with_std(&self) -> bool { 29 fn starts_with_std(&self) -> bool {
17 self.segments.first().filter(|&first_segment| first_segment == &known::std).is_some() 30 self.segments.first() == Some(&known::std)
18 } 31 }
19 32
20 // When std library is present, paths starting with `std::` 33 // When std library is present, paths starting with `std::`
21 // should be preferred over paths starting with `core::` and `alloc::` 34 // should be preferred over paths starting with `core::` and `alloc::`
22 fn can_start_with_std(&self) -> bool { 35 fn can_start_with_std(&self) -> bool {
23 self.segments 36 let first_segment = self.segments.first();
24 .first() 37 first_segment == Some(&known::alloc) || first_segment == Some(&known::core)
25 .filter(|&first_segment| {
26 first_segment == &known::alloc || first_segment == &known::core
27 })
28 .is_some()
29 } 38 }
30 39
31 fn len(&self) -> usize { 40 fn len(&self) -> usize {
@@ -40,14 +49,6 @@ impl ModPath {
40 } 49 }
41} 50}
42 51
43// FIXME: handle local items
44
45/// Find a path that can be used to refer to a certain item. This can depend on
46/// *from where* you're referring to the item, hence the `from` parameter.
47pub fn find_path(db: &dyn DefDatabase, item: ItemInNs, from: ModuleId) -> Option<ModPath> {
48 find_path_inner(db, item, from, MAX_PATH_LEN)
49}
50
51fn find_path_inner( 52fn find_path_inner(
52 db: &dyn DefDatabase, 53 db: &dyn DefDatabase,
53 item: ItemInNs, 54 item: ItemInNs,
@@ -198,7 +199,7 @@ fn find_importable_locations(
198 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id)) 199 .chain(crate_graph[from.krate].dependencies.iter().map(|dep| dep.crate_id))
199 { 200 {
200 result.extend( 201 result.extend(
201 importable_locations_in_crate(db, item, krate) 202 db.importable_locations_of(item, krate)
202 .iter() 203 .iter()
203 .filter(|(_, _, vis)| vis.is_visible_from(db, from)) 204 .filter(|(_, _, vis)| vis.is_visible_from(db, from))
204 .map(|(m, n, _)| (*m, n.clone())), 205 .map(|(m, n, _)| (*m, n.clone())),
@@ -213,11 +214,12 @@ fn find_importable_locations(
213/// 214///
214/// Note that the crate doesn't need to be the one in which the item is defined; 215/// Note that the crate doesn't need to be the one in which the item is defined;
215/// it might be re-exported in other crates. 216/// it might be re-exported in other crates.
216fn importable_locations_in_crate( 217pub(crate) fn importable_locations_of_query(
217 db: &dyn DefDatabase, 218 db: &dyn DefDatabase,
218 item: ItemInNs, 219 item: ItemInNs,
219 krate: CrateId, 220 krate: CrateId,
220) -> Vec<(ModuleId, Name, Visibility)> { 221) -> Arc<[(ModuleId, Name, Visibility)]> {
222 let _p = profile("importable_locations_of_query");
221 let def_map = db.crate_def_map(krate); 223 let def_map = db.crate_def_map(krate);
222 let mut result = Vec::new(); 224 let mut result = Vec::new();
223 for (local_id, data) in def_map.modules.iter() { 225 for (local_id, data) in def_map.modules.iter() {
@@ -243,7 +245,8 @@ fn importable_locations_in_crate(
243 result.push((ModuleId { krate, local_id }, name.clone(), vis)); 245 result.push((ModuleId { krate, local_id }, name.clone(), vis));
244 } 246 }
245 } 247 }
246 result 248
249 Arc::from(result)
247} 250}
248 251
249#[cfg(test)] 252#[cfg(test)]
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index ccc4348f4..daea02f88 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -808,15 +808,13 @@ impl Ty {
808 } 808 }
809 } 809 }
810 810
811 /// If this is an `impl Trait` or `dyn Trait`, returns that trait. 811 /// If this is a `dyn Trait`, returns that trait.
812 pub fn inherent_trait(&self) -> Option<TraitId> { 812 pub fn dyn_trait(&self) -> Option<TraitId> {
813 match self { 813 match self {
814 Ty::Dyn(predicates) | Ty::Opaque(predicates) => { 814 Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
815 predicates.iter().find_map(|pred| match pred { 815 GenericPredicate::Implemented(tr) => Some(tr.trait_),
816 GenericPredicate::Implemented(tr) => Some(tr.trait_), 816 _ => None,
817 _ => None, 817 }),
818 })
819 }
820 _ => None, 818 _ => None,
821 } 819 }
822 } 820 }
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 657284fd0..0851e16a8 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -408,8 +408,9 @@ fn iterate_trait_method_candidates<T>(
408 receiver_ty: Option<&Canonical<Ty>>, 408 receiver_ty: Option<&Canonical<Ty>>,
409 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 409 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
410) -> Option<T> { 410) -> Option<T> {
411 // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope 411 // if ty is `dyn Trait`, the trait doesn't need to be in scope
412 let inherent_trait = self_ty.value.inherent_trait().into_iter(); 412 let inherent_trait =
413 self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
413 let env_traits = if let Ty::Placeholder(_) = self_ty.value { 414 let env_traits = if let Ty::Placeholder(_) = self_ty.value {
414 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope 415 // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
415 env.trait_predicates_for_self_ty(&self_ty.value) 416 env.trait_predicates_for_self_ty(&self_ty.value)
@@ -601,11 +602,6 @@ pub fn implements_trait(
601 krate: CrateId, 602 krate: CrateId,
602 trait_: TraitId, 603 trait_: TraitId,
603) -> bool { 604) -> bool {
604 if ty.value.inherent_trait() == Some(trait_) {
605 // FIXME this is a bit of a hack, since Chalk should say the same thing
606 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
607 return true;
608 }
609 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 605 let goal = generic_implements_goal(db, env, trait_, ty.clone());
610 let solution = db.trait_solve(krate, goal); 606 let solution = db.trait_solve(krate, goal);
611 607
diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs
index 67f964ab5..9c2c9e1d2 100644
--- a/crates/ra_hir_ty/src/tests/method_resolution.rs
+++ b/crates/ra_hir_ty/src/tests/method_resolution.rs
@@ -1096,3 +1096,34 @@ fn test() { (S {}).method()<|>; }
1096 ); 1096 );
1097 assert_eq!(t, "()"); 1097 assert_eq!(t, "()");
1098} 1098}
1099
1100#[test]
1101fn dyn_trait_super_trait_not_in_scope() {
1102 assert_snapshot!(
1103 infer(r#"
1104mod m {
1105 pub trait SuperTrait {
1106 fn foo(&self) -> u32 { 0 }
1107 }
1108}
1109trait Trait: m::SuperTrait {}
1110
1111struct S;
1112impl m::SuperTrait for S {}
1113impl Trait for S {}
1114
1115fn test(d: &dyn Trait) {
1116 d.foo();
1117}
1118"#),
1119 @r###"
1120 52..56 'self': &Self
1121 65..70 '{ 0 }': u32
1122 67..68 '0': u32
1123 177..178 'd': &dyn Trait
1124 192..208 '{ ...o(); }': ()
1125 198..199 'd': &dyn Trait
1126 198..205 'd.foo()': u32
1127 "###
1128 );
1129}
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs
index 115ad8328..c2168222e 100644
--- a/crates/ra_hir_ty/src/tests/regression.rs
+++ b/crates/ra_hir_ty/src/tests/regression.rs
@@ -564,6 +564,37 @@ fn main() {
564} 564}
565 565
566#[test] 566#[test]
567fn issue_4465_dollar_crate_at_type() {
568 assert_snapshot!(
569 infer(r#"
570pub struct Foo {}
571pub fn anything<T>() -> T {
572 loop {}
573}
574macro_rules! foo {
575 () => {{
576 let r: $crate::Foo = anything();
577 r
578 }};
579}
580fn main() {
581 let _a = foo!();
582}
583"#), @r###"
584 45..60 '{ loop {} }': T
585 51..58 'loop {}': !
586 56..58 '{}': ()
587 !0..31 '{letr:...g();r}': Foo
588 !4..5 'r': Foo
589 !18..26 'anything': fn anything<Foo>() -> Foo
590 !18..28 'anything()': Foo
591 !29..30 'r': Foo
592 164..188 '{ ...!(); }': ()
593 174..176 '_a': Foo
594"###);
595}
596
597#[test]
567fn issue_4053_diesel_where_clauses() { 598fn issue_4053_diesel_where_clauses() {
568 assert_snapshot!( 599 assert_snapshot!(
569 infer(r#" 600 infer(r#"
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index 9d32cbc7a..c49aacf98 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -1617,6 +1617,138 @@ fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1617} 1617}
1618 1618
1619#[test] 1619#[test]
1620fn fn_ptr_and_item() {
1621 assert_snapshot!(
1622 infer(r#"
1623#[lang="fn_once"]
1624trait FnOnce<Args> {
1625 type Output;
1626
1627 fn call_once(self, args: Args) -> Self::Output;
1628}
1629
1630trait Foo<T> {
1631 fn foo(&self) -> T;
1632}
1633
1634struct Bar<T>(T);
1635
1636impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1637 fn foo(&self) -> (A1, R) {}
1638}
1639
1640enum Opt<T> { None, Some(T) }
1641impl<T> Opt<T> {
1642 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> {}
1643}
1644
1645fn test() {
1646 let bar: Bar<fn(u8) -> u32>;
1647 bar.foo();
1648
1649 let opt: Opt<u8>;
1650 let f: fn(u8) -> u32;
1651 opt.map(f);
1652}
1653"#),
1654 @r###"
165575..79 'self': Self
165681..85 'args': Args
1657140..144 'self': &Self
1658244..248 'self': &Bar<F>
1659261..263 '{}': ()
1660347..351 'self': Opt<T>
1661353..354 'f': F
1662369..371 '{}': ()
1663385..501 '{ ...(f); }': ()
1664395..398 'bar': Bar<fn(u8) -> u32>
1665424..427 'bar': Bar<fn(u8) -> u32>
1666424..433 'bar.foo()': {unknown}
1667444..447 'opt': Opt<u8>
1668466..467 'f': fn(u8) -> u32
1669488..491 'opt': Opt<u8>
1670488..498 'opt.map(f)': Opt<FnOnce::Output<fn(u8) -> u32, (u8,)>>
1671496..497 'f': fn(u8) -> u32
1672"###
1673 );
1674}
1675
1676#[test]
1677fn fn_trait_deref_with_ty_default() {
1678 assert_snapshot!(
1679 infer(r#"
1680#[lang = "deref"]
1681trait Deref {
1682 type Target;
1683
1684 fn deref(&self) -> &Self::Target;
1685}
1686
1687#[lang="fn_once"]
1688trait FnOnce<Args> {
1689 type Output;
1690
1691 fn call_once(self, args: Args) -> Self::Output;
1692}
1693
1694struct Foo;
1695
1696impl Foo {
1697 fn foo(&self) -> usize {}
1698}
1699
1700struct Lazy<T, F = fn() -> T>(F);
1701
1702impl<T, F> Lazy<T, F> {
1703 pub fn new(f: F) -> Lazy<T, F> {}
1704}
1705
1706impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1707 type Target = T;
1708}
1709
1710fn test() {
1711 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
1712 let r1 = lazy1.foo();
1713
1714 fn make_foo_fn() -> Foo {}
1715 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
1716 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
1717 let r2 = lazy2.foo();
1718}
1719"#),
1720 @r###"
172165..69 'self': &Self
1722166..170 'self': Self
1723172..176 'args': Args
1724240..244 'self': &Foo
1725255..257 '{}': ()
1726335..336 'f': F
1727355..357 '{}': ()
1728444..690 '{ ...o(); }': ()
1729454..459 'lazy1': Lazy<Foo, fn() -> T>
1730476..485 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1731476..493 'Lazy::...| Foo)': Lazy<Foo, fn() -> T>
1732486..492 '|| Foo': || -> T
1733489..492 'Foo': Foo
1734503..505 'r1': {unknown}
1735508..513 'lazy1': Lazy<Foo, fn() -> T>
1736508..519 'lazy1.foo()': {unknown}
1737561..576 'make_foo_fn_ptr': fn() -> Foo
1738592..603 'make_foo_fn': fn make_foo_fn() -> Foo
1739613..618 'lazy2': Lazy<Foo, fn() -> T>
1740635..644 'Lazy::new': fn new<Foo, fn() -> T>(fn() -> T) -> Lazy<Foo, fn() -> T>
1741635..661 'Lazy::...n_ptr)': Lazy<Foo, fn() -> T>
1742645..660 'make_foo_fn_ptr': fn() -> Foo
1743671..673 'r2': {unknown}
1744676..681 'lazy2': Lazy<Foo, fn() -> T>
1745676..687 'lazy2.foo()': {unknown}
1746550..552 '{}': ()
1747"###
1748 );
1749}
1750
1751#[test]
1620fn closure_1() { 1752fn closure_1() {
1621 assert_snapshot!( 1753 assert_snapshot!(
1622 infer(r#" 1754 infer(r#"
diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs
index 4b173edd3..7c9bb4d00 100644
--- a/crates/ra_mbe/src/mbe_expander/transcriber.rs
+++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs
@@ -1,4 +1,4 @@
1//! Transcraber takes a template, like `fn $ident() {}`, a set of bindings like 1//! Transcriber takes a template, like `fn $ident() {}`, a set of bindings like
2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}` 2//! `$ident => foo`, interpolates variables in the template, to get `fn foo() {}`
3 3
4use ra_syntax::SmolStr; 4use ra_syntax::SmolStr;
@@ -53,7 +53,8 @@ impl Bindings {
53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> { 53pub(super) fn transcribe(template: &tt::Subtree, bindings: &Bindings) -> ExpandResult<tt::Subtree> {
54 assert!(template.delimiter == None); 54 assert!(template.delimiter == None);
55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() }; 55 let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new() };
56 expand_subtree(&mut ctx, template) 56 let mut arena: Vec<tt::TokenTree> = Vec::new();
57 expand_subtree(&mut ctx, template, &mut arena)
57} 58}
58 59
59#[derive(Debug)] 60#[derive(Debug)]
@@ -73,8 +74,13 @@ struct ExpandCtx<'a> {
73 nesting: Vec<NestingState>, 74 nesting: Vec<NestingState>,
74} 75}
75 76
76fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<tt::Subtree> { 77fn expand_subtree(
77 let mut buf: Vec<tt::TokenTree> = Vec::new(); 78 ctx: &mut ExpandCtx,
79 template: &tt::Subtree,
80 arena: &mut Vec<tt::TokenTree>,
81) -> ExpandResult<tt::Subtree> {
82 // remember how many elements are in the arena now - when returning, we want to drain exactly how many elements we added. This way, the recursive uses of the arena get their own "view" of the arena, but will reuse the allocation
83 let start_elements = arena.len();
78 let mut err = None; 84 let mut err = None;
79 for op in parse_template(template) { 85 for op in parse_template(template) {
80 let op = match op { 86 let op = match op {
@@ -85,25 +91,27 @@ fn expand_subtree(ctx: &mut ExpandCtx, template: &tt::Subtree) -> ExpandResult<t
85 } 91 }
86 }; 92 };
87 match op { 93 match op {
88 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => buf.push(tt.clone()), 94 Op::TokenTree(tt @ tt::TokenTree::Leaf(..)) => arena.push(tt.clone()),
89 Op::TokenTree(tt::TokenTree::Subtree(tt)) => { 95 Op::TokenTree(tt::TokenTree::Subtree(tt)) => {
90 let ExpandResult(tt, e) = expand_subtree(ctx, tt); 96 let ExpandResult(tt, e) = expand_subtree(ctx, tt, arena);
91 err = err.or(e); 97 err = err.or(e);
92 buf.push(tt.into()); 98 arena.push(tt.into());
93 } 99 }
94 Op::Var { name, kind: _ } => { 100 Op::Var { name, kind: _ } => {
95 let ExpandResult(fragment, e) = expand_var(ctx, name); 101 let ExpandResult(fragment, e) = expand_var(ctx, name);
96 err = err.or(e); 102 err = err.or(e);
97 push_fragment(&mut buf, fragment); 103 push_fragment(arena, fragment);
98 } 104 }
99 Op::Repeat { subtree, kind, separator } => { 105 Op::Repeat { subtree, kind, separator } => {
100 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator); 106 let ExpandResult(fragment, e) = expand_repeat(ctx, subtree, kind, separator, arena);
101 err = err.or(e); 107 err = err.or(e);
102 push_fragment(&mut buf, fragment) 108 push_fragment(arena, fragment)
103 } 109 }
104 } 110 }
105 } 111 }
106 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: buf }, err) 112 // drain the elements added in this instance of expand_subtree
113 let tts = arena.drain(start_elements..arena.len()).collect();
114 ExpandResult(tt::Subtree { delimiter: template.delimiter, token_trees: tts }, err)
107} 115}
108 116
109fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> { 117fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> ExpandResult<Fragment> {
@@ -155,6 +163,7 @@ fn expand_repeat(
155 template: &tt::Subtree, 163 template: &tt::Subtree,
156 kind: RepeatKind, 164 kind: RepeatKind,
157 separator: Option<Separator>, 165 separator: Option<Separator>,
166 arena: &mut Vec<tt::TokenTree>,
158) -> ExpandResult<Fragment> { 167) -> ExpandResult<Fragment> {
159 let mut buf: Vec<tt::TokenTree> = Vec::new(); 168 let mut buf: Vec<tt::TokenTree> = Vec::new();
160 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false }); 169 ctx.nesting.push(NestingState { idx: 0, at_end: false, hit: false });
@@ -165,7 +174,7 @@ fn expand_repeat(
165 let mut counter = 0; 174 let mut counter = 0;
166 175
167 loop { 176 loop {
168 let ExpandResult(mut t, e) = expand_subtree(ctx, template); 177 let ExpandResult(mut t, e) = expand_subtree(ctx, template, arena);
169 let nesting_state = ctx.nesting.last_mut().unwrap(); 178 let nesting_state = ctx.nesting.last_mut().unwrap();
170 if nesting_state.at_end || !nesting_state.hit { 179 if nesting_state.at_end || !nesting_state.hit {
171 break; 180 break;
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs
index e08ad4dae..eeb8ad66b 100644
--- a/crates/ra_parser/src/lib.rs
+++ b/crates/ra_parser/src/lib.rs
@@ -25,7 +25,7 @@ pub(crate) use token_set::TokenSet;
25pub use syntax_kind::SyntaxKind; 25pub use syntax_kind::SyntaxKind;
26 26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)] 27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
28pub struct ParseError(pub String); 28pub struct ParseError(pub Box<String>);
29 29
30/// `TokenSource` abstracts the source of the tokens parser operates on. 30/// `TokenSource` abstracts the source of the tokens parser operates on.
31/// 31///
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index faa63d53f..4f59b0a23 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -192,7 +192,7 @@ impl<'t> Parser<'t> {
192 /// structured errors with spans and notes, like rustc 192 /// structured errors with spans and notes, like rustc
193 /// does. 193 /// does.
194 pub(crate) fn error<T: Into<String>>(&mut self, message: T) { 194 pub(crate) fn error<T: Into<String>>(&mut self, message: T) {
195 let msg = ParseError(message.into()); 195 let msg = ParseError(Box::new(message.into()));
196 self.push_event(Event::Error { msg }) 196 self.push_event(Event::Error { msg })
197 } 197 }
198 198
diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs
index f9d379abf..e566af7e8 100644
--- a/crates/ra_syntax/src/syntax_node.rs
+++ b/crates/ra_syntax/src/syntax_node.rs
@@ -70,6 +70,6 @@ impl SyntaxTreeBuilder {
70 } 70 }
71 71
72 pub fn error(&mut self, error: ra_parser::ParseError, text_pos: TextSize) { 72 pub fn error(&mut self, error: ra_parser::ParseError, text_pos: TextSize) {
73 self.errors.push(SyntaxError::new_at_offset(error.0, text_pos)) 73 self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos))
74 } 74 }
75} 75}
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs
index 14b3f707d..5967f44cd 100644
--- a/crates/ra_tt/src/buffer.rs
+++ b/crates/ra_tt/src/buffer.rs
@@ -42,7 +42,9 @@ impl<'t> TokenBuffer<'t> {
42 buffers: &mut Vec<Box<[Entry<'t>]>>, 42 buffers: &mut Vec<Box<[Entry<'t>]>>,
43 next: Option<EntryPtr>, 43 next: Option<EntryPtr>,
44 ) -> usize { 44 ) -> usize {
45 let mut entries = vec![]; 45 // Must contain everything in tokens and then the Entry::End
46 let start_capacity = tokens.len() + 1;
47 let mut entries = Vec::with_capacity(start_capacity);
46 let mut children = vec![]; 48 let mut children = vec![];
47 49
48 for (idx, tt) in tokens.iter().enumerate() { 50 for (idx, tt) in tokens.iter().enumerate() {
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 53aee833d..b5dc6f0fa 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -33,6 +33,36 @@ pub struct Config {
33 pub inlay_hints: InlayHintsConfig, 33 pub inlay_hints: InlayHintsConfig,
34 pub completion: CompletionConfig, 34 pub completion: CompletionConfig,
35 pub call_info_full: bool, 35 pub call_info_full: bool,
36 pub lens: LensConfig,
37}
38
39#[derive(Clone, Debug, PartialEq, Eq)]
40pub struct LensConfig {
41 pub run: bool,
42 pub debug: bool,
43 pub impementations: bool,
44}
45
46impl Default for LensConfig {
47 fn default() -> Self {
48 Self { run: true, debug: true, impementations: true }
49 }
50}
51
52impl LensConfig {
53 pub const NO_LENS: LensConfig = Self { run: false, debug: false, impementations: false };
54
55 pub fn any(&self) -> bool {
56 self.impementations || self.runnable()
57 }
58
59 pub fn none(&self) -> bool {
60 !self.any()
61 }
62
63 pub fn runnable(&self) -> bool {
64 self.run || self.debug
65 }
36} 66}
37 67
38#[derive(Debug, Clone)] 68#[derive(Debug, Clone)]
@@ -107,6 +137,7 @@ impl Default for Config {
107 ..CompletionConfig::default() 137 ..CompletionConfig::default()
108 }, 138 },
109 call_info_full: true, 139 call_info_full: true,
140 lens: LensConfig::default(),
110 } 141 }
111 } 142 }
112} 143}
@@ -196,6 +227,16 @@ impl Config {
196 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets); 227 set(value, "/completion/addCallArgumentSnippets", &mut self.completion.add_call_argument_snippets);
197 set(value, "/callInfo/full", &mut self.call_info_full); 228 set(value, "/callInfo/full", &mut self.call_info_full);
198 229
230 let mut lens_enabled = true;
231 set(value, "/lens/enable", &mut lens_enabled);
232 if lens_enabled {
233 set(value, "/lens/run", &mut self.lens.run);
234 set(value, "/lens/debug", &mut self.lens.debug);
235 set(value, "/lens/implementations", &mut self.lens.impementations);
236 } else {
237 self.lens = LensConfig::NO_LENS;
238 }
239
199 log::info!("Config::update() = {:#?}", self); 240 log::info!("Config::update() = {:#?}", self);
200 241
201 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> { 242 fn get<'a, T: Deserialize<'a>>(value: &'a serde_json::Value, pointer: &str) -> Option<T> {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 6b14830b6..e67556752 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -812,88 +812,108 @@ pub fn handle_code_lens(
812 params: lsp_types::CodeLensParams, 812 params: lsp_types::CodeLensParams,
813) -> Result<Option<Vec<CodeLens>>> { 813) -> Result<Option<Vec<CodeLens>>> {
814 let _p = profile("handle_code_lens"); 814 let _p = profile("handle_code_lens");
815 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
816 let line_index = world.analysis().file_line_index(file_id)?;
817
818 let mut lenses: Vec<CodeLens> = Default::default(); 815 let mut lenses: Vec<CodeLens> = Default::default();
819 816
817 if world.config.lens.none() {
818 // early return before any db query!
819 return Ok(Some(lenses));
820 }
821
822 let file_id = from_proto::file_id(&world, &params.text_document.uri)?;
823 let line_index = world.analysis().file_line_index(file_id)?;
820 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?; 824 let cargo_spec = CargoTargetSpec::for_file(&world, file_id)?;
821 // Gather runnables 825
822 for runnable in world.analysis().runnables(file_id)? { 826 if world.config.lens.runnable() {
823 let title = match &runnable.kind { 827 // Gather runnables
824 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶\u{fe0e} Run Test", 828 for runnable in world.analysis().runnables(file_id)? {
825 RunnableKind::DocTest { .. } => "▶\u{fe0e} Run Doctest", 829 let (run_title, debugee) = match &runnable.kind {
826 RunnableKind::Bench { .. } => "Run Bench", 830 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => {
827 RunnableKind::Bin => { 831 ("▶️\u{fe0e}Run Test", true)
828 // Do not suggest binary run on other target than binary
829 match &cargo_spec {
830 Some(spec) => match spec.target_kind {
831 TargetKind::Bin => "Run",
832 _ => continue,
833 },
834 None => continue,
835 } 832 }
833 RunnableKind::DocTest { .. } => {
834 // cargo does not support -no-run for doctests
835 ("▶️\u{fe0e}Run Doctest", false)
836 }
837 RunnableKind::Bench { .. } => {
838 // Nothing wrong with bench debugging
839 ("Run Bench", true)
840 }
841 RunnableKind::Bin => {
842 // Do not suggest binary run on other target than binary
843 match &cargo_spec {
844 Some(spec) => match spec.target_kind {
845 TargetKind::Bin => ("Run", true),
846 _ => continue,
847 },
848 None => continue,
849 }
850 }
851 };
852
853 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
854 if world.config.lens.run {
855 let lens = CodeLens {
856 range: r.range,
857 command: Some(Command {
858 title: run_title.to_string(),
859 command: "rust-analyzer.runSingle".into(),
860 arguments: Some(vec![to_value(&r).unwrap()]),
861 }),
862 data: None,
863 };
864 lenses.push(lens);
836 } 865 }
837 }
838 .to_string();
839 let mut r = to_lsp_runnable(&world, file_id, runnable)?;
840 let lens = CodeLens {
841 range: r.range,
842 command: Some(Command {
843 title,
844 command: "rust-analyzer.runSingle".into(),
845 arguments: Some(vec![to_value(&r).unwrap()]),
846 }),
847 data: None,
848 };
849 lenses.push(lens);
850 866
851 if r.args[0] == "run" { 867 if debugee && world.config.lens.debug {
852 r.args[0] = "build".into(); 868 if r.args[0] == "run" {
853 } else { 869 r.args[0] = "build".into();
854 r.args.push("--no-run".into()); 870 } else {
871 r.args.push("--no-run".into());
872 }
873 let debug_lens = CodeLens {
874 range: r.range,
875 command: Some(Command {
876 title: "Debug".into(),
877 command: "rust-analyzer.debugSingle".into(),
878 arguments: Some(vec![to_value(r).unwrap()]),
879 }),
880 data: None,
881 };
882 lenses.push(debug_lens);
883 }
855 } 884 }
856 let debug_lens = CodeLens {
857 range: r.range,
858 command: Some(Command {
859 title: "Debug".into(),
860 command: "rust-analyzer.debugSingle".into(),
861 arguments: Some(vec![to_value(r).unwrap()]),
862 }),
863 data: None,
864 };
865 lenses.push(debug_lens);
866 } 885 }
867 886
868 // Handle impls 887 if world.config.lens.impementations {
869 lenses.extend( 888 // Handle impls
870 world 889 lenses.extend(
871 .analysis() 890 world
872 .file_structure(file_id)? 891 .analysis()
873 .into_iter() 892 .file_structure(file_id)?
874 .filter(|it| match it.kind { 893 .into_iter()
875 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, 894 .filter(|it| match it.kind {
876 _ => false, 895 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
877 }) 896 _ => false,
878 .map(|it| { 897 })
879 let range = to_proto::range(&line_index, it.node_range); 898 .map(|it| {
880 let pos = range.start; 899 let range = to_proto::range(&line_index, it.node_range);
881 let lens_params = lsp_types::request::GotoImplementationParams { 900 let pos = range.start;
882 text_document_position_params: lsp_types::TextDocumentPositionParams::new( 901 let lens_params = lsp_types::request::GotoImplementationParams {
883 params.text_document.clone(), 902 text_document_position_params: lsp_types::TextDocumentPositionParams::new(
884 pos, 903 params.text_document.clone(),
885 ), 904 pos,
886 work_done_progress_params: Default::default(), 905 ),
887 partial_result_params: Default::default(), 906 work_done_progress_params: Default::default(),
888 }; 907 partial_result_params: Default::default(),
889 CodeLens { 908 };
890 range, 909 CodeLens {
891 command: None, 910 range,
892 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()), 911 command: None,
893 } 912 data: Some(to_value(CodeLensResolveData::Impls(lens_params)).unwrap()),
894 }), 913 }
895 ); 914 }),
896 915 );
916 }
897 Ok(Some(lenses)) 917 Ok(Some(lenses))
898} 918}
899 919