aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_assists/src/ast_transform.rs2
-rw-r--r--crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs2
-rw-r--r--crates/ra_hir/src/lib.rs3
-rw-r--r--crates/ra_hir/src/semantics.rs7
-rw-r--r--crates/ra_hir/src/source_analyzer.rs3
-rw-r--r--crates/ra_hir_def/src/adt.rs18
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/body/lower.rs42
-rw-r--r--crates/ra_hir_def/src/data.rs21
-rw-r--r--crates/ra_hir_def/src/generics.rs68
-rw-r--r--crates/ra_hir_def/src/path.rs5
-rw-r--r--crates/ra_hir_def/src/path/lower.rs23
-rw-r--r--crates/ra_hir_def/src/type_ref.rs52
-rw-r--r--crates/ra_hir_expand/src/hygiene.rs2
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs40
-rw-r--r--crates/ra_ide/src/display/short_label.rs6
-rw-r--r--crates/ra_ide/src/hover.rs11
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs2
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs2
-rw-r--r--crates/ra_syntax/src/validation.rs119
-rw-r--r--crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast70
-rw-r--r--crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs4
-rw-r--r--crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast27
-rw-r--r--crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs2
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast26
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rs1
-rw-r--r--crates/rust-analyzer/src/caps.rs29
-rw-r--r--crates/rust-analyzer/src/config.rs6
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs28
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/support.rs6
-rw-r--r--docs/dev/architecture.md4
-rw-r--r--docs/dev/guide.md8
-rw-r--r--docs/user/readme.adoc11
-rw-r--r--xtask/src/ast_src.rs2
34 files changed, 474 insertions, 180 deletions
diff --git a/crates/ra_assists/src/ast_transform.rs b/crates/ra_assists/src/ast_transform.rs
index 52b4c82db..9ac65ab39 100644
--- a/crates/ra_assists/src/ast_transform.rs
+++ b/crates/ra_assists/src/ast_transform.rs
@@ -85,6 +85,7 @@ impl<'a> SubstituteTypeParams<'a> {
85 ast::TypeRef::PathType(path_type) => path_type.path()?, 85 ast::TypeRef::PathType(path_type) => path_type.path()?,
86 _ => return None, 86 _ => return None,
87 }; 87 };
88 // FIXME: use `hir::Path::from_src` instead.
88 let path = hir::Path::from_ast(path)?; 89 let path = hir::Path::from_ast(path)?;
89 let resolution = self.source_scope.resolve_hir_path(&path)?; 90 let resolution = self.source_scope.resolve_hir_path(&path)?;
90 match resolution { 91 match resolution {
@@ -128,6 +129,7 @@ impl<'a> QualifyPaths<'a> {
128 // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway 129 // don't try to qualify `Fn(Foo) -> Bar` paths, they are in prelude anyway
129 return None; 130 return None;
130 } 131 }
132 // FIXME: use `hir::Path::from_src` instead.
131 let hir_path = hir::Path::from_ast(p.clone()); 133 let hir_path = hir::Path::from_ast(p.clone());
132 let resolution = self.source_scope.resolve_hir_path(&hir_path?)?; 134 let resolution = self.source_scope.resolve_hir_path(&hir_path?)?;
133 match resolution { 135 match resolution {
diff --git a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
index 2f02df303..918e8dd8d 100644
--- a/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
+++ b/crates/ra_assists/src/handlers/replace_qualified_name_with_use.rs
@@ -27,7 +27,7 @@ pub(crate) fn replace_qualified_name_with_use(ctx: AssistCtx) -> Option<Assist>
27 return None; 27 return None;
28 } 28 }
29 29
30 let hir_path = hir::Path::from_ast(path.clone())?; 30 let hir_path = ctx.sema.lower_path(&path)?;
31 let segments = collect_hir_path_segments(&hir_path)?; 31 let segments = collect_hir_path_segments(&hir_path)?;
32 if segments.len() < 2 { 32 if segments.len() < 2 {
33 return None; 33 return None;
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 312ef3814..c5df4ac24 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -70,6 +70,7 @@ pub use hir_def::{
70 type_ref::Mutability, 70 type_ref::Mutability,
71}; 71};
72pub use hir_expand::{ 72pub use hir_expand::{
73 name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, 73 hygiene::Hygiene, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId,
74 MacroFile, Origin,
74}; 75};
75pub use hir_ty::{display::HirDisplay, CallableDef}; 76pub use hir_ty::{display::HirDisplay, CallableDef};
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index a0a0f234b..515e5eb17 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 resolver::{self, HasResolver, Resolver}, 8 resolver::{self, HasResolver, Resolver},
9 AsMacroCall, TraitId, 9 AsMacroCall, TraitId,
10}; 10};
11use hir_expand::ExpansionInfo; 11use hir_expand::{hygiene::Hygiene, ExpansionInfo};
12use hir_ty::associated_type_shorthand_candidates; 12use hir_ty::associated_type_shorthand_candidates;
13use itertools::Itertools; 13use itertools::Itertools;
14use ra_db::{FileId, FileRange}; 14use ra_db::{FileId, FileRange};
@@ -246,6 +246,11 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
246 self.analyze(path.syntax()).resolve_path(self.db, path) 246 self.analyze(path.syntax()).resolve_path(self.db, path)
247 } 247 }
248 248
249 pub fn lower_path(&self, path: &ast::Path) -> Option<Path> {
250 let src = self.find_file(path.syntax().clone());
251 Path::from_src(path.clone(), &Hygiene::new(self.db.upcast(), src.file_id.into()))
252 }
253
249 pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> { 254 pub fn resolve_bind_pat_to_const(&self, pat: &ast::BindPat) -> Option<ModuleDef> {
250 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat) 255 self.analyze(pat.syntax()).resolve_bind_pat_to_const(self.db, pat)
251 } 256 }
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 74d64c97d..c63d1b847 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -224,7 +224,8 @@ impl SourceAnalyzer {
224 } 224 }
225 } 225 }
226 // This must be a normal source file rather than macro file. 226 // This must be a normal source file rather than macro file.
227 let hir_path = crate::Path::from_ast(path.clone())?; 227 let hir_path =
228 crate::Path::from_src(path.clone(), &Hygiene::new(db.upcast(), self.file_id))?;
228 resolve_hir_path(db, &self.resolver, &hir_path) 229 resolve_hir_path(db, &self.resolver, &hir_path)
229 } 230 }
230 231
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index 753becc3d..8eef51828 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -12,9 +12,15 @@ use ra_prof::profile;
12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner}; 12use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner, VisibilityOwner};
13 13
14use crate::{ 14use crate::{
15 body::CfgExpander, db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, 15 body::{CfgExpander, LowerCtx},
16 type_ref::TypeRef, visibility::RawVisibility, EnumId, HasModule, LocalEnumVariantId, 16 db::DefDatabase,
17 LocalFieldId, Lookup, ModuleId, StructId, UnionId, VariantId, 17 src::HasChildSource,
18 src::HasSource,
19 trace::Trace,
20 type_ref::TypeRef,
21 visibility::RawVisibility,
22 EnumId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StructId, UnionId,
23 VariantId,
18}; 24};
19 25
20/// Note that we use `StructData` for unions as well! 26/// Note that we use `StructData` for unions as well!
@@ -198,6 +204,8 @@ fn lower_struct(
198 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>, 204 trace: &mut Trace<FieldData, Either<ast::TupleFieldDef, ast::RecordFieldDef>>,
199 ast: &InFile<ast::StructKind>, 205 ast: &InFile<ast::StructKind>,
200) -> StructKind { 206) -> StructKind {
207 let ctx = LowerCtx::new(db, ast.file_id);
208
201 match &ast.value { 209 match &ast.value {
202 ast::StructKind::Tuple(fl) => { 210 ast::StructKind::Tuple(fl) => {
203 for (i, fd) in fl.fields().enumerate() { 211 for (i, fd) in fl.fields().enumerate() {
@@ -210,7 +218,7 @@ fn lower_struct(
210 || Either::Left(fd.clone()), 218 || Either::Left(fd.clone()),
211 || FieldData { 219 || FieldData {
212 name: Name::new_tuple_field(i), 220 name: Name::new_tuple_field(i),
213 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 221 type_ref: TypeRef::from_ast_opt(&ctx, fd.type_ref()),
214 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 222 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
215 }, 223 },
216 ); 224 );
@@ -228,7 +236,7 @@ fn lower_struct(
228 || Either::Right(fd.clone()), 236 || Either::Right(fd.clone()),
229 || FieldData { 237 || FieldData {
230 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 238 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
231 type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), 239 type_ref: TypeRef::from_ast_opt(&ctx, fd.ascribed_type()),
232 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 240 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
233 }, 241 },
234 ); 242 );
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 890cefcaf..4edaad960 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -15,6 +15,8 @@ use ra_prof::profile;
15use ra_syntax::{ast, AstNode, AstPtr}; 15use ra_syntax::{ast, AstNode, AstPtr};
16use rustc_hash::FxHashMap; 16use rustc_hash::FxHashMap;
17 17
18pub(crate) use lower::LowerCtx;
19
18use crate::{ 20use crate::{
19 attr::Attrs, 21 attr::Attrs,
20 db::DefDatabase, 22 db::DefDatabase,
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index f467ed3fe..e9dd65b0a 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -3,8 +3,9 @@
3 3
4use either::Either; 4use either::Either;
5use hir_expand::{ 5use hir_expand::{
6 hygiene::Hygiene,
6 name::{name, AsName, Name}, 7 name::{name, AsName, Name},
7 MacroDefId, MacroDefKind, 8 HirFileId, MacroDefId, MacroDefKind,
8}; 9};
9use ra_arena::Arena; 10use ra_arena::Arena;
10use ra_syntax::{ 11use ra_syntax::{
@@ -26,7 +27,7 @@ use crate::{
26 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement, 27 LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, Statement,
27 }, 28 },
28 item_scope::BuiltinShadowMode, 29 item_scope::BuiltinShadowMode,
29 path::GenericArgs, 30 path::{GenericArgs, Path},
30 type_ref::{Mutability, TypeRef}, 31 type_ref::{Mutability, TypeRef},
31 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, 32 AdtId, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId,
32 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, 33 StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc,
@@ -35,6 +36,23 @@ use crate::{
35use super::{ExprSource, PatSource}; 36use super::{ExprSource, PatSource};
36use ast::AstChildren; 37use ast::AstChildren;
37 38
39pub(crate) struct LowerCtx {
40 hygiene: Hygiene,
41}
42
43impl LowerCtx {
44 pub fn new(db: &dyn DefDatabase, file_id: HirFileId) -> Self {
45 LowerCtx { hygiene: Hygiene::new(db.upcast(), file_id) }
46 }
47 pub fn with_hygiene(hygiene: &Hygiene) -> Self {
48 LowerCtx { hygiene: hygiene.clone() }
49 }
50
51 pub fn lower_path(&self, ast: ast::Path) -> Option<Path> {
52 Path::from_src(ast, &self.hygiene)
53 }
54}
55
38pub(super) fn lower( 56pub(super) fn lower(
39 db: &dyn DefDatabase, 57 db: &dyn DefDatabase,
40 def: DefWithBodyId, 58 def: DefWithBodyId,
@@ -42,10 +60,13 @@ pub(super) fn lower(
42 params: Option<ast::ParamList>, 60 params: Option<ast::ParamList>,
43 body: Option<ast::Expr>, 61 body: Option<ast::Expr>,
44) -> (Body, BodySourceMap) { 62) -> (Body, BodySourceMap) {
63 let ctx = LowerCtx::new(db, expander.current_file_id.clone());
64
45 ExprCollector { 65 ExprCollector {
46 db, 66 db,
47 def, 67 def,
48 expander, 68 expander,
69 ctx,
49 source_map: BodySourceMap::default(), 70 source_map: BodySourceMap::default(),
50 body: Body { 71 body: Body {
51 exprs: Arena::default(), 72 exprs: Arena::default(),
@@ -62,7 +83,7 @@ struct ExprCollector<'a> {
62 db: &'a dyn DefDatabase, 83 db: &'a dyn DefDatabase,
63 def: DefWithBodyId, 84 def: DefWithBodyId,
64 expander: Expander, 85 expander: Expander,
65 86 ctx: LowerCtx,
66 body: Body, 87 body: Body,
67 source_map: BodySourceMap, 88 source_map: BodySourceMap,
68} 89}
@@ -237,7 +258,8 @@ impl ExprCollector<'_> {
237 Vec::new() 258 Vec::new()
238 }; 259 };
239 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 260 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
240 let generic_args = e.type_arg_list().and_then(GenericArgs::from_ast); 261 let generic_args =
262 e.type_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx, it));
241 self.alloc_expr( 263 self.alloc_expr(
242 Expr::MethodCall { receiver, method_name, args, generic_args }, 264 Expr::MethodCall { receiver, method_name, args, generic_args },
243 syntax_ptr, 265 syntax_ptr,
@@ -343,7 +365,7 @@ impl ExprCollector<'_> {
343 } 365 }
344 ast::Expr::CastExpr(e) => { 366 ast::Expr::CastExpr(e) => {
345 let expr = self.collect_expr_opt(e.expr()); 367 let expr = self.collect_expr_opt(e.expr());
346 let type_ref = TypeRef::from_ast_opt(e.type_ref()); 368 let type_ref = TypeRef::from_ast_opt(&self.ctx, e.type_ref());
347 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 369 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
348 } 370 }
349 ast::Expr::RefExpr(e) => { 371 ast::Expr::RefExpr(e) => {
@@ -365,12 +387,16 @@ impl ExprCollector<'_> {
365 if let Some(pl) = e.param_list() { 387 if let Some(pl) = e.param_list() {
366 for param in pl.params() { 388 for param in pl.params() {
367 let pat = self.collect_pat_opt(param.pat()); 389 let pat = self.collect_pat_opt(param.pat());
368 let type_ref = param.ascribed_type().map(TypeRef::from_ast); 390 let type_ref =
391 param.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
369 args.push(pat); 392 args.push(pat);
370 arg_types.push(type_ref); 393 arg_types.push(type_ref);
371 } 394 }
372 } 395 }
373 let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); 396 let ret_type = e
397 .ret_type()
398 .and_then(|r| r.type_ref())
399 .map(|it| TypeRef::from_ast(&self.ctx, it));
374 let body = self.collect_expr_opt(e.body()); 400 let body = self.collect_expr_opt(e.body());
375 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 401 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
376 } 402 }
@@ -476,7 +502,7 @@ impl ExprCollector<'_> {
476 .map(|s| match s { 502 .map(|s| match s {
477 ast::Stmt::LetStmt(stmt) => { 503 ast::Stmt::LetStmt(stmt) => {
478 let pat = self.collect_pat_opt(stmt.pat()); 504 let pat = self.collect_pat_opt(stmt.pat());
479 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 505 let type_ref = stmt.ascribed_type().map(|it| TypeRef::from_ast(&self.ctx, it));
480 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 506 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
481 Statement::Let { pat, type_ref, initializer } 507 Statement::Let { pat, type_ref, initializer }
482 } 508 }
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index ccb682f9a..7a2067e49 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -15,6 +15,7 @@ use ra_syntax::ast::{
15 15
16use crate::{ 16use crate::{
17 attr::Attrs, 17 attr::Attrs,
18 body::LowerCtx,
18 db::DefDatabase, 19 db::DefDatabase,
19 path::{path, AssociatedTypeBinding, GenericArgs, Path}, 20 path::{path, AssociatedTypeBinding, GenericArgs, Path},
20 src::HasSource, 21 src::HasSource,
@@ -40,13 +41,14 @@ impl FunctionData {
40 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> { 41 pub(crate) fn fn_data_query(db: &impl DefDatabase, func: FunctionId) -> Arc<FunctionData> {
41 let loc = func.lookup(db); 42 let loc = func.lookup(db);
42 let src = loc.source(db); 43 let src = loc.source(db);
44 let ctx = LowerCtx::new(db, src.file_id);
43 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 45 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
44 let mut params = Vec::new(); 46 let mut params = Vec::new();
45 let mut has_self_param = false; 47 let mut has_self_param = false;
46 if let Some(param_list) = src.value.param_list() { 48 if let Some(param_list) = src.value.param_list() {
47 if let Some(self_param) = param_list.self_param() { 49 if let Some(self_param) = param_list.self_param() {
48 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 50 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
49 TypeRef::from_ast(type_ref) 51 TypeRef::from_ast(&ctx, type_ref)
50 } else { 52 } else {
51 let self_type = TypeRef::Path(name![Self].into()); 53 let self_type = TypeRef::Path(name![Self].into());
52 match self_param.kind() { 54 match self_param.kind() {
@@ -63,14 +65,14 @@ impl FunctionData {
63 has_self_param = true; 65 has_self_param = true;
64 } 66 }
65 for param in param_list.params() { 67 for param in param_list.params() {
66 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 68 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
67 params.push(type_ref); 69 params.push(type_ref);
68 } 70 }
69 } 71 }
70 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id)); 72 let attrs = Attrs::new(&src.value, &Hygiene::new(db.upcast(), src.file_id));
71 73
72 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) { 74 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
73 TypeRef::from_ast(type_ref) 75 TypeRef::from_ast(&ctx, type_ref)
74 } else { 76 } else {
75 TypeRef::unit() 77 TypeRef::unit()
76 }; 78 };
@@ -122,7 +124,8 @@ impl TypeAliasData {
122 let loc = typ.lookup(db); 124 let loc = typ.lookup(db);
123 let node = loc.source(db); 125 let node = loc.source(db);
124 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name()); 126 let name = node.value.name().map_or_else(Name::missing, |n| n.as_name());
125 let type_ref = node.value.type_ref().map(TypeRef::from_ast); 127 let lower_ctx = LowerCtx::new(db, node.file_id);
128 let type_ref = node.value.type_ref().map(|it| TypeRef::from_ast(&lower_ctx, it));
126 let vis_default = RawVisibility::default_for_container(loc.container); 129 let vis_default = RawVisibility::default_for_container(loc.container);
127 let visibility = RawVisibility::from_ast_with_default( 130 let visibility = RawVisibility::from_ast_with_default(
128 db, 131 db,
@@ -130,7 +133,7 @@ impl TypeAliasData {
130 node.as_ref().map(|n| n.visibility()), 133 node.as_ref().map(|n| n.visibility()),
131 ); 134 );
132 let bounds = if let Some(bound_list) = node.value.type_bound_list() { 135 let bounds = if let Some(bound_list) = node.value.type_bound_list() {
133 bound_list.bounds().map(TypeBound::from_ast).collect() 136 bound_list.bounds().map(|it| TypeBound::from_ast(&lower_ctx, it)).collect()
134 } else { 137 } else {
135 Vec::new() 138 Vec::new()
136 }; 139 };
@@ -223,9 +226,10 @@ impl ImplData {
223 let _p = profile("impl_data_query"); 226 let _p = profile("impl_data_query");
224 let impl_loc = id.lookup(db); 227 let impl_loc = id.lookup(db);
225 let src = impl_loc.source(db); 228 let src = impl_loc.source(db);
229 let lower_ctx = LowerCtx::new(db, src.file_id);
226 230
227 let target_trait = src.value.target_trait().map(TypeRef::from_ast); 231 let target_trait = src.value.target_trait().map(|it| TypeRef::from_ast(&lower_ctx, it));
228 let target_type = TypeRef::from_ast_opt(src.value.target_type()); 232 let target_type = TypeRef::from_ast_opt(&lower_ctx, src.value.target_type());
229 let is_negative = src.value.excl_token().is_some(); 233 let is_negative = src.value.excl_token().is_some();
230 let module_id = impl_loc.container.module(db); 234 let module_id = impl_loc.container.module(db);
231 235
@@ -279,8 +283,9 @@ impl ConstData {
279 vis_default: RawVisibility, 283 vis_default: RawVisibility,
280 node: InFile<N>, 284 node: InFile<N>,
281 ) -> ConstData { 285 ) -> ConstData {
286 let ctx = LowerCtx::new(db, node.file_id);
282 let name = node.value.name().map(|n| n.as_name()); 287 let name = node.value.name().map(|n| n.as_name());
283 let type_ref = TypeRef::from_ast_opt(node.value.ascribed_type()); 288 let type_ref = TypeRef::from_ast_opt(&ctx, node.value.ascribed_type());
284 let visibility = 289 let visibility =
285 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility())); 290 RawVisibility::from_ast_with_default(db, vis_default, node.map(|n| n.visibility()));
286 ConstData { name, type_ref, visibility } 291 ConstData { name, type_ref, visibility }
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
index d850244c4..09a5241f7 100644
--- a/crates/ra_hir_def/src/generics.rs
+++ b/crates/ra_hir_def/src/generics.rs
@@ -15,6 +15,7 @@ use ra_prof::profile;
15use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; 15use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
16 16
17use crate::{ 17use crate::{
18 body::LowerCtx,
18 child_by_source::ChildBySource, 19 child_by_source::ChildBySource,
19 db::DefDatabase, 20 db::DefDatabase,
20 dyn_map::DynMap, 21 dyn_map::DynMap,
@@ -80,11 +81,13 @@ impl GenericParams {
80 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 81 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
81 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; 82 let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() };
82 let mut sm = ArenaMap::default(); 83 let mut sm = ArenaMap::default();
84
83 // FIXME: add `: Sized` bound for everything except for `Self` in traits 85 // FIXME: add `: Sized` bound for everything except for `Self` in traits
84 let file_id = match def { 86 let file_id = match def {
85 GenericDefId::FunctionId(it) => { 87 GenericDefId::FunctionId(it) => {
86 let src = it.lookup(db).source(db); 88 let src = it.lookup(db).source(db);
87 generics.fill(&mut sm, &src.value); 89 let lower_ctx = LowerCtx::new(db, src.file_id);
90 generics.fill(&lower_ctx, &mut sm, &src.value);
88 // lower `impl Trait` in arguments 91 // lower `impl Trait` in arguments
89 let data = db.function_data(it); 92 let data = db.function_data(it);
90 for param in &data.params { 93 for param in &data.params {
@@ -94,21 +97,25 @@ impl GenericParams {
94 } 97 }
95 GenericDefId::AdtId(AdtId::StructId(it)) => { 98 GenericDefId::AdtId(AdtId::StructId(it)) => {
96 let src = it.lookup(db).source(db); 99 let src = it.lookup(db).source(db);
97 generics.fill(&mut sm, &src.value); 100 let lower_ctx = LowerCtx::new(db, src.file_id);
101 generics.fill(&lower_ctx, &mut sm, &src.value);
98 src.file_id 102 src.file_id
99 } 103 }
100 GenericDefId::AdtId(AdtId::UnionId(it)) => { 104 GenericDefId::AdtId(AdtId::UnionId(it)) => {
101 let src = it.lookup(db).source(db); 105 let src = it.lookup(db).source(db);
102 generics.fill(&mut sm, &src.value); 106 let lower_ctx = LowerCtx::new(db, src.file_id);
107 generics.fill(&lower_ctx, &mut sm, &src.value);
103 src.file_id 108 src.file_id
104 } 109 }
105 GenericDefId::AdtId(AdtId::EnumId(it)) => { 110 GenericDefId::AdtId(AdtId::EnumId(it)) => {
106 let src = it.lookup(db).source(db); 111 let src = it.lookup(db).source(db);
107 generics.fill(&mut sm, &src.value); 112 let lower_ctx = LowerCtx::new(db, src.file_id);
113 generics.fill(&lower_ctx, &mut sm, &src.value);
108 src.file_id 114 src.file_id
109 } 115 }
110 GenericDefId::TraitId(it) => { 116 GenericDefId::TraitId(it) => {
111 let src = it.lookup(db).source(db); 117 let src = it.lookup(db).source(db);
118 let lower_ctx = LowerCtx::new(db, src.file_id);
112 119
113 // traits get the Self type as an implicit first type parameter 120 // traits get the Self type as an implicit first type parameter
114 let self_param_id = generics.types.alloc(TypeParamData { 121 let self_param_id = generics.types.alloc(TypeParamData {
@@ -120,14 +127,16 @@ impl GenericParams {
120 // add super traits as bounds on Self 127 // add super traits as bounds on Self
121 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar 128 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
122 let self_param = TypeRef::Path(name![Self].into()); 129 let self_param = TypeRef::Path(name![Self].into());
123 generics.fill_bounds(&src.value, self_param); 130 generics.fill_bounds(&lower_ctx, &src.value, self_param);
124 131
125 generics.fill(&mut sm, &src.value); 132 generics.fill(&lower_ctx, &mut sm, &src.value);
126 src.file_id 133 src.file_id
127 } 134 }
128 GenericDefId::TypeAliasId(it) => { 135 GenericDefId::TypeAliasId(it) => {
129 let src = it.lookup(db).source(db); 136 let src = it.lookup(db).source(db);
130 generics.fill(&mut sm, &src.value); 137 let lower_ctx = LowerCtx::new(db, src.file_id);
138
139 generics.fill(&lower_ctx, &mut sm, &src.value);
131 src.file_id 140 src.file_id
132 } 141 }
133 // Note that we don't add `Self` here: in `impl`s, `Self` is not a 142 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
@@ -135,7 +144,9 @@ impl GenericParams {
135 // type, so this is handled by the resolver. 144 // type, so this is handled by the resolver.
136 GenericDefId::ImplId(it) => { 145 GenericDefId::ImplId(it) => {
137 let src = it.lookup(db).source(db); 146 let src = it.lookup(db).source(db);
138 generics.fill(&mut sm, &src.value); 147 let lower_ctx = LowerCtx::new(db, src.file_id);
148
149 generics.fill(&lower_ctx, &mut sm, &src.value);
139 src.file_id 150 src.file_id
140 } 151 }
141 // We won't be using this ID anyway 152 // We won't be using this ID anyway
@@ -145,28 +156,38 @@ impl GenericParams {
145 (generics, InFile::new(file_id, sm)) 156 (generics, InFile::new(file_id, sm))
146 } 157 }
147 158
148 fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { 159 fn fill(&mut self, lower_ctx: &LowerCtx, sm: &mut SourceMap, node: &dyn TypeParamsOwner) {
149 if let Some(params) = node.type_param_list() { 160 if let Some(params) = node.type_param_list() {
150 self.fill_params(sm, params) 161 self.fill_params(lower_ctx, sm, params)
151 } 162 }
152 if let Some(where_clause) = node.where_clause() { 163 if let Some(where_clause) = node.where_clause() {
153 self.fill_where_predicates(where_clause); 164 self.fill_where_predicates(lower_ctx, where_clause);
154 } 165 }
155 } 166 }
156 167
157 fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { 168 fn fill_bounds(
169 &mut self,
170 lower_ctx: &LowerCtx,
171 node: &dyn ast::TypeBoundsOwner,
172 type_ref: TypeRef,
173 ) {
158 for bound in 174 for bound in
159 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 175 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
160 { 176 {
161 self.add_where_predicate_from_bound(bound, type_ref.clone()); 177 self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
162 } 178 }
163 } 179 }
164 180
165 fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { 181 fn fill_params(
182 &mut self,
183 lower_ctx: &LowerCtx,
184 sm: &mut SourceMap,
185 params: ast::TypeParamList,
186 ) {
166 for type_param in params.type_params() { 187 for type_param in params.type_params() {
167 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 188 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
168 // FIXME: Use `Path::from_src` 189 // FIXME: Use `Path::from_src`
169 let default = type_param.default_type().map(TypeRef::from_ast); 190 let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it));
170 let param = TypeParamData { 191 let param = TypeParamData {
171 name: Some(name.clone()), 192 name: Some(name.clone()),
172 default, 193 default,
@@ -176,29 +197,34 @@ impl GenericParams {
176 sm.insert(param_id, Either::Right(type_param.clone())); 197 sm.insert(param_id, Either::Right(type_param.clone()));
177 198
178 let type_ref = TypeRef::Path(name.into()); 199 let type_ref = TypeRef::Path(name.into());
179 self.fill_bounds(&type_param, type_ref); 200 self.fill_bounds(&lower_ctx, &type_param, type_ref);
180 } 201 }
181 } 202 }
182 203
183 fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) { 204 fn fill_where_predicates(&mut self, lower_ctx: &LowerCtx, where_clause: ast::WhereClause) {
184 for pred in where_clause.predicates() { 205 for pred in where_clause.predicates() {
185 let type_ref = match pred.type_ref() { 206 let type_ref = match pred.type_ref() {
186 Some(type_ref) => type_ref, 207 Some(type_ref) => type_ref,
187 None => continue, 208 None => continue,
188 }; 209 };
189 let type_ref = TypeRef::from_ast(type_ref); 210 let type_ref = TypeRef::from_ast(lower_ctx, type_ref);
190 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 211 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
191 self.add_where_predicate_from_bound(bound, type_ref.clone()); 212 self.add_where_predicate_from_bound(lower_ctx, bound, type_ref.clone());
192 } 213 }
193 } 214 }
194 } 215 }
195 216
196 fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) { 217 fn add_where_predicate_from_bound(
218 &mut self,
219 lower_ctx: &LowerCtx,
220 bound: ast::TypeBound,
221 type_ref: TypeRef,
222 ) {
197 if bound.question_token().is_some() { 223 if bound.question_token().is_some() {
198 // FIXME: remove this bound 224 // FIXME: remove this bound
199 return; 225 return;
200 } 226 }
201 let bound = TypeBound::from_ast(bound); 227 let bound = TypeBound::from_ast(lower_ctx, bound);
202 self.where_predicates 228 self.where_predicates
203 .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound }); 229 .push(WherePredicate { target: WherePredicateTarget::TypeRef(type_ref), bound });
204 } 230 }
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 162b3c8c7..e84efe2ab 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -7,6 +7,7 @@ use std::{
7 sync::Arc, 7 sync::Arc,
8}; 8};
9 9
10use crate::body::LowerCtx;
10use hir_expand::{ 11use hir_expand::{
11 hygiene::Hygiene, 12 hygiene::Hygiene,
12 name::{AsName, Name}, 13 name::{AsName, Name},
@@ -244,8 +245,8 @@ impl<'a> PathSegments<'a> {
244} 245}
245 246
246impl GenericArgs { 247impl GenericArgs {
247 pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> { 248 pub(crate) fn from_ast(lower_ctx: &LowerCtx, node: ast::TypeArgList) -> Option<GenericArgs> {
248 lower::lower_generic_args(node) 249 lower::lower_generic_args(lower_ctx, node)
249 } 250 }
250 251
251 pub(crate) fn empty() -> GenericArgs { 252 pub(crate) fn empty() -> GenericArgs {
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 9ec2e0dcd..e3d237a0a 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -13,6 +13,7 @@ use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner, TypeBoundsOwner};
13 13
14use super::AssociatedTypeBinding; 14use super::AssociatedTypeBinding;
15use crate::{ 15use crate::{
16 body::LowerCtx,
16 path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, 17 path::{GenericArg, GenericArgs, ModPath, Path, PathKind},
17 type_ref::{TypeBound, TypeRef}, 18 type_ref::{TypeBound, TypeRef},
18}; 19};
@@ -26,6 +27,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
26 let mut type_anchor = None; 27 let mut type_anchor = None;
27 let mut segments = Vec::new(); 28 let mut segments = Vec::new();
28 let mut generic_args = Vec::new(); 29 let mut generic_args = Vec::new();
30 let ctx = LowerCtx::with_hygiene(hygiene);
29 loop { 31 loop {
30 let segment = path.segment()?; 32 let segment = path.segment()?;
31 33
@@ -40,9 +42,10 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
40 Either::Left(name) => { 42 Either::Left(name) => {
41 let args = segment 43 let args = segment
42 .type_arg_list() 44 .type_arg_list()
43 .and_then(lower_generic_args) 45 .and_then(|it| lower_generic_args(&ctx, it))
44 .or_else(|| { 46 .or_else(|| {
45 lower_generic_args_from_fn_path( 47 lower_generic_args_from_fn_path(
48 &ctx,
46 segment.param_list(), 49 segment.param_list(),
47 segment.ret_type(), 50 segment.ret_type(),
48 ) 51 )
@@ -60,7 +63,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
60 ast::PathSegmentKind::Type { type_ref, trait_ref } => { 63 ast::PathSegmentKind::Type { type_ref, trait_ref } => {
61 assert!(path.qualifier().is_none()); // this can only occur at the first segment 64 assert!(path.qualifier().is_none()); // this can only occur at the first segment
62 65
63 let self_type = TypeRef::from_ast(type_ref?); 66 let self_type = TypeRef::from_ast(&ctx, type_ref?);
64 67
65 match trait_ref { 68 match trait_ref {
66 // <T>::foo 69 // <T>::foo
@@ -128,10 +131,13 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
128 } 131 }
129} 132}
130 133
131pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs> { 134pub(super) fn lower_generic_args(
135 lower_ctx: &LowerCtx,
136 node: ast::TypeArgList,
137) -> Option<GenericArgs> {
132 let mut args = Vec::new(); 138 let mut args = Vec::new();
133 for type_arg in node.type_args() { 139 for type_arg in node.type_args() {
134 let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); 140 let type_ref = TypeRef::from_ast_opt(lower_ctx, type_arg.type_ref());
135 args.push(GenericArg::Type(type_ref)); 141 args.push(GenericArg::Type(type_ref));
136 } 142 }
137 // lifetimes ignored for now 143 // lifetimes ignored for now
@@ -140,9 +146,9 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
140 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg; 146 let assoc_type_arg: ast::AssocTypeArg = assoc_type_arg;
141 if let Some(name_ref) = assoc_type_arg.name_ref() { 147 if let Some(name_ref) = assoc_type_arg.name_ref() {
142 let name = name_ref.as_name(); 148 let name = name_ref.as_name();
143 let type_ref = assoc_type_arg.type_ref().map(TypeRef::from_ast); 149 let type_ref = assoc_type_arg.type_ref().map(|it| TypeRef::from_ast(lower_ctx, it));
144 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() { 150 let bounds = if let Some(l) = assoc_type_arg.type_bound_list() {
145 l.bounds().map(TypeBound::from_ast).collect() 151 l.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
146 } else { 152 } else {
147 Vec::new() 153 Vec::new()
148 }; 154 };
@@ -159,6 +165,7 @@ pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option<GenericArgs>
159/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) 165/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
160/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). 166/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
161fn lower_generic_args_from_fn_path( 167fn lower_generic_args_from_fn_path(
168 ctx: &LowerCtx,
162 params: Option<ast::ParamList>, 169 params: Option<ast::ParamList>,
163 ret_type: Option<ast::RetType>, 170 ret_type: Option<ast::RetType>,
164) -> Option<GenericArgs> { 171) -> Option<GenericArgs> {
@@ -167,14 +174,14 @@ fn lower_generic_args_from_fn_path(
167 if let Some(params) = params { 174 if let Some(params) = params {
168 let mut param_types = Vec::new(); 175 let mut param_types = Vec::new();
169 for param in params.params() { 176 for param in params.params() {
170 let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); 177 let type_ref = TypeRef::from_ast_opt(&ctx, param.ascribed_type());
171 param_types.push(type_ref); 178 param_types.push(type_ref);
172 } 179 }
173 let arg = GenericArg::Type(TypeRef::Tuple(param_types)); 180 let arg = GenericArg::Type(TypeRef::Tuple(param_types));
174 args.push(arg); 181 args.push(arg);
175 } 182 }
176 if let Some(ret_type) = ret_type { 183 if let Some(ret_type) = ret_type {
177 let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); 184 let type_ref = TypeRef::from_ast_opt(&ctx, ret_type.type_ref());
178 bindings.push(AssociatedTypeBinding { 185 bindings.push(AssociatedTypeBinding {
179 name: name![Output], 186 name: name![Output],
180 type_ref: Some(type_ref), 187 type_ref: Some(type_ref),
diff --git a/crates/ra_hir_def/src/type_ref.rs b/crates/ra_hir_def/src/type_ref.rs
index f308c6bdf..5bdad9efd 100644
--- a/crates/ra_hir_def/src/type_ref.rs
+++ b/crates/ra_hir_def/src/type_ref.rs
@@ -3,7 +3,7 @@
3 3
4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner}; 4use ra_syntax::ast::{self, TypeAscriptionOwner, TypeBoundsOwner};
5 5
6use crate::path::Path; 6use crate::{body::LowerCtx, path::Path};
7 7
8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] 8#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
9pub enum Mutability { 9pub enum Mutability {
@@ -64,30 +64,34 @@ pub enum TypeBound {
64 64
65impl TypeRef { 65impl TypeRef {
66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`. 66 /// Converts an `ast::TypeRef` to a `hir::TypeRef`.
67 pub(crate) fn from_ast(node: ast::TypeRef) -> Self { 67 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeRef) -> Self {
68 match node { 68 match node {
69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 69 ast::TypeRef::ParenType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
70 ast::TypeRef::TupleType(inner) => { 70 ast::TypeRef::TupleType(inner) => {
71 TypeRef::Tuple(inner.fields().map(TypeRef::from_ast).collect()) 71 TypeRef::Tuple(inner.fields().map(|it| TypeRef::from_ast(ctx, it)).collect())
72 } 72 }
73 ast::TypeRef::NeverType(..) => TypeRef::Never, 73 ast::TypeRef::NeverType(..) => TypeRef::Never,
74 ast::TypeRef::PathType(inner) => { 74 ast::TypeRef::PathType(inner) => {
75 // FIXME: Use `Path::from_src` 75 // FIXME: Use `Path::from_src`
76 inner.path().and_then(Path::from_ast).map(TypeRef::Path).unwrap_or(TypeRef::Error) 76 inner
77 .path()
78 .and_then(|it| ctx.lower_path(it))
79 .map(TypeRef::Path)
80 .unwrap_or(TypeRef::Error)
77 } 81 }
78 ast::TypeRef::PointerType(inner) => { 82 ast::TypeRef::PointerType(inner) => {
79 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 83 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
80 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 84 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
81 TypeRef::RawPtr(Box::new(inner_ty), mutability) 85 TypeRef::RawPtr(Box::new(inner_ty), mutability)
82 } 86 }
83 ast::TypeRef::ArrayType(inner) => { 87 ast::TypeRef::ArrayType(inner) => {
84 TypeRef::Array(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 88 TypeRef::Array(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
85 } 89 }
86 ast::TypeRef::SliceType(inner) => { 90 ast::TypeRef::SliceType(inner) => {
87 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(inner.type_ref()))) 91 TypeRef::Slice(Box::new(TypeRef::from_ast_opt(&ctx, inner.type_ref())))
88 } 92 }
89 ast::TypeRef::ReferenceType(inner) => { 93 ast::TypeRef::ReferenceType(inner) => {
90 let inner_ty = TypeRef::from_ast_opt(inner.type_ref()); 94 let inner_ty = TypeRef::from_ast_opt(&ctx, inner.type_ref());
91 let mutability = Mutability::from_mutable(inner.mut_token().is_some()); 95 let mutability = Mutability::from_mutable(inner.mut_token().is_some());
92 TypeRef::Reference(Box::new(inner_ty), mutability) 96 TypeRef::Reference(Box::new(inner_ty), mutability)
93 } 97 }
@@ -96,10 +100,13 @@ impl TypeRef {
96 let ret_ty = inner 100 let ret_ty = inner
97 .ret_type() 101 .ret_type()
98 .and_then(|rt| rt.type_ref()) 102 .and_then(|rt| rt.type_ref())
99 .map(TypeRef::from_ast) 103 .map(|it| TypeRef::from_ast(ctx, it))
100 .unwrap_or_else(|| TypeRef::Tuple(Vec::new())); 104 .unwrap_or_else(|| TypeRef::Tuple(Vec::new()));
101 let mut params = if let Some(pl) = inner.param_list() { 105 let mut params = if let Some(pl) = inner.param_list() {
102 pl.params().map(|p| p.ascribed_type()).map(TypeRef::from_ast_opt).collect() 106 pl.params()
107 .map(|p| p.ascribed_type())
108 .map(|it| TypeRef::from_ast_opt(&ctx, it))
109 .collect()
103 } else { 110 } else {
104 Vec::new() 111 Vec::new()
105 }; 112 };
@@ -107,19 +114,19 @@ impl TypeRef {
107 TypeRef::Fn(params) 114 TypeRef::Fn(params)
108 } 115 }
109 // for types are close enough for our purposes to the inner type for now... 116 // for types are close enough for our purposes to the inner type for now...
110 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(inner.type_ref()), 117 ast::TypeRef::ForType(inner) => TypeRef::from_ast_opt(&ctx, inner.type_ref()),
111 ast::TypeRef::ImplTraitType(inner) => { 118 ast::TypeRef::ImplTraitType(inner) => {
112 TypeRef::ImplTrait(type_bounds_from_ast(inner.type_bound_list())) 119 TypeRef::ImplTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
113 } 120 }
114 ast::TypeRef::DynTraitType(inner) => { 121 ast::TypeRef::DynTraitType(inner) => {
115 TypeRef::DynTrait(type_bounds_from_ast(inner.type_bound_list())) 122 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
116 } 123 }
117 } 124 }
118 } 125 }
119 126
120 pub(crate) fn from_ast_opt(node: Option<ast::TypeRef>) -> Self { 127 pub(crate) fn from_ast_opt(ctx: &LowerCtx, node: Option<ast::TypeRef>) -> Self {
121 if let Some(node) = node { 128 if let Some(node) = node {
122 TypeRef::from_ast(node) 129 TypeRef::from_ast(ctx, node)
123 } else { 130 } else {
124 TypeRef::Error 131 TypeRef::Error
125 } 132 }
@@ -180,24 +187,27 @@ impl TypeRef {
180 } 187 }
181} 188}
182 189
183pub(crate) fn type_bounds_from_ast(type_bounds_opt: Option<ast::TypeBoundList>) -> Vec<TypeBound> { 190pub(crate) fn type_bounds_from_ast(
191 lower_ctx: &LowerCtx,
192 type_bounds_opt: Option<ast::TypeBoundList>,
193) -> Vec<TypeBound> {
184 if let Some(type_bounds) = type_bounds_opt { 194 if let Some(type_bounds) = type_bounds_opt {
185 type_bounds.bounds().map(TypeBound::from_ast).collect() 195 type_bounds.bounds().map(|it| TypeBound::from_ast(lower_ctx, it)).collect()
186 } else { 196 } else {
187 vec![] 197 vec![]
188 } 198 }
189} 199}
190 200
191impl TypeBound { 201impl TypeBound {
192 pub(crate) fn from_ast(node: ast::TypeBound) -> Self { 202 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::TypeBound) -> Self {
193 match node.kind() { 203 match node.kind() {
194 ast::TypeBoundKind::PathType(path_type) => { 204 ast::TypeBoundKind::PathType(path_type) => {
195 let path = match path_type.path() { 205 let path = match path_type.path() {
196 Some(p) => p, 206 Some(p) => p,
197 None => return TypeBound::Error, 207 None => return TypeBound::Error,
198 }; 208 };
199 // FIXME: Use `Path::from_src` 209
200 let path = match Path::from_ast(path) { 210 let path = match ctx.lower_path(path) {
201 Some(p) => p, 211 Some(p) => p,
202 None => return TypeBound::Error, 212 None => return TypeBound::Error,
203 }; 213 };
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs
index 0b41d0e95..53866bbcb 100644
--- a/crates/ra_hir_expand/src/hygiene.rs
+++ b/crates/ra_hir_expand/src/hygiene.rs
@@ -12,7 +12,7 @@ use crate::{
12 HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind, 12 HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind,
13}; 13};
14 14
15#[derive(Debug)] 15#[derive(Clone, Debug)]
16pub struct Hygiene { 16pub struct Hygiene {
17 // This is what `$crate` expands to 17 // This is what `$crate` expands to
18 def_crate: Option<CrateId>, 18 def_crate: Option<CrateId>,
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 5ddecbdc6..1f796876d 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#"
diff --git a/crates/ra_ide/src/display/short_label.rs b/crates/ra_ide/src/display/short_label.rs
index 4b081bf6c..d37260e96 100644
--- a/crates/ra_ide/src/display/short_label.rs
+++ b/crates/ra_ide/src/display/short_label.rs
@@ -33,7 +33,11 @@ impl ShortLabel for ast::EnumDef {
33 33
34impl ShortLabel for ast::TraitDef { 34impl ShortLabel for ast::TraitDef {
35 fn short_label(&self) -> Option<String> { 35 fn short_label(&self) -> Option<String> {
36 short_label_from_node(self, "trait ") 36 if self.unsafe_token().is_some() {
37 short_label_from_node(self, "unsafe trait ")
38 } else {
39 short_label_from_node(self, "trait ")
40 }
37 } 41 }
38} 42}
39 43
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index a62f598f0..54d318858 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -869,4 +869,15 @@ fn func(foo: i32) { if true { <|>foo; }; }
869 &[r#"pub(crate) async unsafe extern "C" fn foo()"#], 869 &[r#"pub(crate) async unsafe extern "C" fn foo()"#],
870 ); 870 );
871 } 871 }
872
873 #[test]
874 fn test_hover_trait_show_qualifiers() {
875 check_hover_result(
876 "
877 //- /lib.rs
878 unsafe trait foo<|>() {}
879 ",
880 &["unsafe trait foo"],
881 );
882 }
872} 883}
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index f2ea5088e..45e3dd2d3 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -407,7 +407,7 @@ impl ast::Visibility {
407 } else if self.super_token().is_some() { 407 } else if self.super_token().is_some() {
408 VisibilityKind::PubSuper 408 VisibilityKind::PubSuper
409 } else if self.self_token().is_some() { 409 } else if self.self_token().is_some() {
410 VisibilityKind::PubSuper 410 VisibilityKind::PubSelf
411 } else { 411 } else {
412 VisibilityKind::Pub 412 VisibilityKind::Pub
413 } 413 }
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs
index 81260680f..3f16592b6 100644
--- a/crates/ra_syntax/src/ast/generated/nodes.rs
+++ b/crates/ra_syntax/src/ast/generated/nodes.rs
@@ -1241,6 +1241,8 @@ pub struct PathSegment {
1241impl PathSegment { 1241impl PathSegment {
1242 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } 1242 pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
1243 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } 1243 pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
1244 pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
1245 pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
1244 pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } 1246 pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
1245 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } 1247 pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
1246 pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } 1248 pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) }
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index f0b3dec63..e075cd801 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -96,7 +96,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
96 ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors), 96 ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors),
97 ast::Visibility(it) => validate_visibility(it, &mut errors), 97 ast::Visibility(it) => validate_visibility(it, &mut errors),
98 ast::RangeExpr(it) => validate_range_expr(it, &mut errors), 98 ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
99 ast::PathSegment(it) => validate_crate_keyword_in_path_segment(it, &mut errors), 99 ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
100 _ => (), 100 _ => (),
101 } 101 }
102 } 102 }
@@ -224,59 +224,82 @@ fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
224 } 224 }
225} 225}
226 226
227fn validate_crate_keyword_in_path_segment( 227fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxError>) {
228 segment: ast::PathSegment, 228 use ast::PathSegmentKind;
229 errors: &mut Vec<SyntaxError>,
230) {
231 const ERR_MSG: &str = "The `crate` keyword is only allowed as the first segment of a path";
232 229
233 let crate_token = match segment.crate_token() { 230 let path = segment.parent_path();
234 None => return, 231 let is_path_start = segment.coloncolon_token().is_none() && path.qualifier().is_none();
235 Some(it) => it, 232
236 }; 233 if let Some(token) = segment.self_token() {
234 if !is_path_start {
235 errors.push(SyntaxError::new(
236 "The `self` keyword is only allowed as the first segment of a path",
237 token.text_range(),
238 ));
239 }
240 } else if let Some(token) = segment.crate_token() {
241 if !is_path_start || use_prefix(path).is_some() {
242 errors.push(SyntaxError::new(
243 "The `crate` keyword is only allowed as the first segment of a path",
244 token.text_range(),
245 ));
246 }
247 } else if let Some(token) = segment.super_token() {
248 if !all_supers(&path) {
249 errors.push(SyntaxError::new(
250 "The `super` keyword may only be preceded by other `super`s",
251 token.text_range(),
252 ));
253 return;
254 }
237 255
238 // Disallow both ::crate and foo::crate 256 let mut curr_path = path;
239 let mut path = segment.parent_path(); 257 while let Some(prefix) = use_prefix(curr_path) {
240 if segment.coloncolon_token().is_some() || path.qualifier().is_some() { 258 if !all_supers(&prefix) {
241 errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range())); 259 errors.push(SyntaxError::new(
242 return; 260 "The `super` keyword may only be preceded by other `super`s",
261 token.text_range(),
262 ));
263 return;
264 }
265 curr_path = prefix;
266 }
243 } 267 }
244 268
245 // For expressions and types, validation is complete, but we still have 269 fn use_prefix(mut path: ast::Path) -> Option<ast::Path> {
246 // to handle invalid UseItems like this: 270 for node in path.syntax().ancestors().skip(1) {
247 // 271 match_ast! {
248 // use foo:{crate::bar::baz}; 272 match node {
249 // 273 ast::UseTree(it) => if let Some(tree_path) = it.path() {
250 // To handle this we must inspect the parent `UseItem`s and `UseTree`s 274 // Even a top-level path exists within a `UseTree` so we must explicitly
251 // but right now we're looking deep inside the nested `Path` nodes because 275 // allow our path but disallow anything else
252 // `Path`s are left-associative: 276 if tree_path != path {
253 // 277 return Some(tree_path);
254 // ((crate)::bar)::baz) 278 }
255 // ^ current value of path 279 },
256 // 280 ast::UseTreeList(_it) => continue,
257 // So we need to climb to the top 281 ast::Path(parent) => path = parent,
258 while let Some(parent) = path.parent_path() { 282 _ => return None,
259 path = parent; 283 }
284 };
285 }
286 return None;
260 } 287 }
261 288
262 // Now that we've found the whole path we need to see if there's a prefix 289 fn all_supers(path: &ast::Path) -> bool {
263 // somewhere in the UseTree hierarchy. This check is arbitrarily deep 290 let segment = match path.segment() {
264 // because rust allows arbitrary nesting like so: 291 Some(it) => it,
265 // 292 None => return false,
266 // use {foo::{{{{crate::bar::baz}}}}};
267 for node in path.syntax().ancestors().skip(1) {
268 match_ast! {
269 match node {
270 ast::UseTree(it) => if let Some(tree_path) = it.path() {
271 // Even a top-level path exists within a `UseTree` so we must explicitly
272 // allow our path but disallow anything else
273 if tree_path != path {
274 errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range()));
275 }
276 },
277 ast::UseTreeList(_it) => continue,
278 _ => return,
279 }
280 }; 293 };
294
295 if segment.kind() != Some(PathSegmentKind::SuperKw) {
296 return false;
297 }
298
299 if let Some(ref subpath) = path.qualifier() {
300 return all_supers(subpath);
301 }
302
303 return true;
281 } 304 }
282} 305}
diff --git a/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast b/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast
new file mode 100644
index 000000000..d0360c467
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rast
@@ -0,0 +1,70 @@
1[email protected]
2 [email protected]
3 [email protected] "use"
4 [email protected] " "
5 [email protected]
6 [email protected]
7 [email protected]
8 [email protected] "::"
9 [email protected] "super"
10 [email protected] ";"
11 [email protected] "\n"
12 [email protected]
13 [email protected] "use"
14 [email protected] " "
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected]
20 [email protected] "a"
21 [email protected] "::"
22 [email protected]
23 [email protected] "super"
24 [email protected] ";"
25 [email protected] "\n"
26 [email protected]
27 [email protected] "use"
28 [email protected] " "
29 [email protected]
30 [email protected]
31 [email protected]
32 [email protected]
33 [email protected]
34 [email protected] "super"
35 [email protected] "::"
36 [email protected]
37 [email protected]
38 [email protected] "a"
39 [email protected] "::"
40 [email protected]
41 [email protected] "super"
42 [email protected] ";"
43 [email protected] "\n"
44 [email protected]
45 [email protected] "use"
46 [email protected] " "
47 [email protected]
48 [email protected]
49 [email protected]
50 [email protected]
51 [email protected] "a"
52 [email protected] "::"
53 [email protected]
54 [email protected] "{"
55 [email protected]
56 [email protected]
57 [email protected]
58 [email protected]
59 [email protected] "super"
60 [email protected] "::"
61 [email protected]
62 [email protected]
63 [email protected] "b"
64 [email protected] "}"
65 [email protected] ";"
66 [email protected] "\n"
67error 6..11: The `super` keyword may only be preceded by other `super`s
68error 20..25: The `super` keyword may only be preceded by other `super`s
69error 41..46: The `super` keyword may only be preceded by other `super`s
70error 56..61: The `super` keyword may only be preceded by other `super`s
diff --git a/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs b/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs
new file mode 100644
index 000000000..bd4d58042
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0041_illegal_super_keyword_location.rs
@@ -0,0 +1,4 @@
1use ::super;
2use a::super;
3use super::a::super;
4use a::{super::b};
diff --git a/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast b/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast
new file mode 100644
index 000000000..4f382b06c
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rast
@@ -0,0 +1,27 @@
1[email protected]
2 [email protected]
3 [email protected] "use"
4 [email protected] " "
5 [email protected]
6 [email protected]
7 [email protected]
8 [email protected] "::"
9 [email protected] "self"
10 [email protected] ";"
11 [email protected] "\n"
12 [email protected]
13 [email protected] "use"
14 [email protected] " "
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected]
20 [email protected] "a"
21 [email protected] "::"
22 [email protected]
23 [email protected] "self"
24 [email protected] ";"
25 [email protected] "\n"
26error 6..10: The `self` keyword is only allowed as the first segment of a path
27error 19..23: The `self` keyword is only allowed as the first segment of a path
diff --git a/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs b/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs
new file mode 100644
index 000000000..b9e1d7d8b
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0042_illegal_self_keyword_location.rs
@@ -0,0 +1,2 @@
1use ::self;
2use a::self;
diff --git a/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast b/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast
index a5a90df7b..05d9c05ad 100644
--- a/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast
+++ b/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rast
@@ -1,4 +1,4 @@
1SOURCE_FILE@0..65 1SOURCE_FILE@0..38
2 [email protected] 2 [email protected]
3 [email protected] "use" 3 [email protected] "use"
4 [email protected] " " 4 [email protected] " "
@@ -31,27 +31,3 @@ [email protected]
31 [email protected] "bar" 31 [email protected] "bar"
32 [email protected] ";" 32 [email protected] ";"
33 [email protected] "\n" 33 [email protected] "\n"
34 [email protected]
35 [email protected] "use"
36 [email protected] " "
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected]
42 [email protected]
43 [email protected] "::"
44 [email protected] "self"
45 [email protected] "::"
46 [email protected]
47 [email protected]
48 [email protected] "a"
49 [email protected] "::"
50 [email protected]
51 [email protected] "super"
52 [email protected] "::"
53 [email protected]
54 [email protected]
55 [email protected] "bar"
56 [email protected] ";"
57 [email protected] "\n"
diff --git a/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rs b/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rs
index faf6a42c7..9d9eb9917 100644
--- a/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rs
+++ b/crates/ra_syntax/test_data/parser/ok/0013_use_path_self_super.rs
@@ -1,3 +1,2 @@
1use self::foo; 1use self::foo;
2use super::super::bar; 2use super::super::bar;
3use ::self::a::super::bar;
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index e22ab8402..c0d320926 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -3,13 +3,13 @@
3use crate::semantic_tokens; 3use crate::semantic_tokens;
4 4
5use lsp_types::{ 5use lsp_types::{
6 CallHierarchyServerCapability, CodeActionProviderCapability, CodeLensOptions, 6 CallHierarchyServerCapability, CodeActionOptions, CodeActionProviderCapability,
7 CompletionOptions, DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, 7 CodeLensOptions, CompletionOptions, DocumentOnTypeFormattingOptions,
8 ImplementationProviderCapability, RenameOptions, RenameProviderCapability, SaveOptions, 8 FoldingRangeProviderCapability, ImplementationProviderCapability, RenameOptions,
9 SelectionRangeProviderCapability, SemanticTokensDocumentProvider, SemanticTokensLegend, 9 RenameProviderCapability, SaveOptions, SelectionRangeProviderCapability,
10 SemanticTokensOptions, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, 10 SemanticTokensDocumentProvider, SemanticTokensLegend, SemanticTokensOptions,
11 TextDocumentSyncKind, TextDocumentSyncOptions, TypeDefinitionProviderCapability, 11 ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind,
12 WorkDoneProgressOptions, 12 TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions,
13}; 13};
14 14
15pub fn server_capabilities() -> ServerCapabilities { 15pub fn server_capabilities() -> ServerCapabilities {
@@ -40,7 +40,20 @@ pub fn server_capabilities() -> ServerCapabilities {
40 document_highlight_provider: Some(true), 40 document_highlight_provider: Some(true),
41 document_symbol_provider: Some(true), 41 document_symbol_provider: Some(true),
42 workspace_symbol_provider: Some(true), 42 workspace_symbol_provider: Some(true),
43 code_action_provider: Some(CodeActionProviderCapability::Simple(true)), 43 code_action_provider: Some(CodeActionProviderCapability::Options(CodeActionOptions {
44 // Advertise support for all built-in CodeActionKinds
45 code_action_kinds: Some(vec![
46 String::new(),
47 lsp_types::code_action_kind::QUICKFIX.to_string(),
48 lsp_types::code_action_kind::REFACTOR.to_string(),
49 lsp_types::code_action_kind::REFACTOR_EXTRACT.to_string(),
50 lsp_types::code_action_kind::REFACTOR_INLINE.to_string(),
51 lsp_types::code_action_kind::REFACTOR_REWRITE.to_string(),
52 lsp_types::code_action_kind::SOURCE.to_string(),
53 lsp_types::code_action_kind::SOURCE_ORGANIZE_IMPORTS.to_string(),
54 ]),
55 work_done_progress_options: Default::default(),
56 })),
44 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }), 57 code_lens_provider: Some(CodeLensOptions { resolve_provider: Some(true) }),
45 document_formatting_provider: Some(true), 58 document_formatting_provider: Some(true),
46 document_range_formatting_provider: None, 59 document_range_formatting_provider: None,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 74a63e32a..177da94cc 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -70,6 +70,7 @@ pub struct ClientCapsConfig {
70 pub location_link: bool, 70 pub location_link: bool,
71 pub line_folding_only: bool, 71 pub line_folding_only: bool,
72 pub hierarchical_symbols: bool, 72 pub hierarchical_symbols: bool,
73 pub code_action_literals: bool,
73} 74}
74 75
75impl Default for Config { 76impl Default for Config {
@@ -221,6 +222,11 @@ impl Config {
221 { 222 {
222 self.client_caps.hierarchical_symbols = value 223 self.client_caps.hierarchical_symbols = value
223 } 224 }
225 if let Some(value) =
226 caps.code_action.as_ref().and_then(|it| Some(it.code_action_literal_support.is_some()))
227 {
228 self.client_caps.code_action_literals = value;
229 }
224 self.completion.allow_snippets(false); 230 self.completion.allow_snippets(false);
225 if let Some(completion) = &caps.completion { 231 if let Some(completion) = &caps.completion {
226 if let Some(completion_item) = &completion.completion_item { 232 if let Some(completion_item) = &completion.completion_item {
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs
index 8db2dfa0c..0f623949e 100644
--- a/crates/rust-analyzer/src/main_loop/handlers.rs
+++ b/crates/rust-analyzer/src/main_loop/handlers.rs
@@ -19,8 +19,7 @@ use lsp_types::{
19 TextEdit, Url, WorkspaceEdit, 19 TextEdit, Url, WorkspaceEdit,
20}; 20};
21use ra_ide::{ 21use ra_ide::{
22 Assist, AssistId, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, 22 Assist, FileId, FilePosition, FileRange, Query, RangeInfo, Runnable, RunnableKind, SearchScope,
23 SearchScope,
24}; 23};
25use ra_prof::profile; 24use ra_prof::profile;
26use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize}; 25use ra_syntax::{AstNode, SyntaxKind, TextRange, TextSize};
@@ -702,15 +701,9 @@ fn create_single_code_action(assist: Assist, world: &WorldSnapshot) -> Result<Co
702 arguments: Some(vec![arg]), 701 arguments: Some(vec![arg]),
703 }; 702 };
704 703
705 let kind = match assist.id {
706 AssistId("introduce_variable") => Some("refactor.extract.variable".to_string()),
707 AssistId("add_custom_impl") => Some("refactor.rewrite.add_custom_impl".to_string()),
708 _ => None,
709 };
710
711 Ok(CodeAction { 704 Ok(CodeAction {
712 title, 705 title,
713 kind, 706 kind: Some(String::new()),
714 diagnostics: None, 707 diagnostics: None,
715 edit: None, 708 edit: None,
716 command: Some(command), 709 command: Some(command),
@@ -812,6 +805,23 @@ pub fn handle_code_action(
812 } 805 }
813 } 806 }
814 807
808 // If the client only supports commands then filter the list
809 // and remove and actions that depend on edits.
810 if !world.config.client_caps.code_action_literals {
811 // FIXME: use drain_filter once it hits stable.
812 res = res
813 .into_iter()
814 .filter_map(|it| match it {
815 cmd @ lsp_types::CodeActionOrCommand::Command(_) => Some(cmd),
816 lsp_types::CodeActionOrCommand::CodeAction(action) => match action.command {
817 Some(cmd) if action.edit.is_none() => {
818 Some(lsp_types::CodeActionOrCommand::Command(cmd))
819 }
820 _ => None,
821 },
822 })
823 .collect();
824 }
815 Ok(Some(res)) 825 Ok(Some(res))
816} 826}
817 827
diff --git a/crates/rust-analyzer/tests/heavy_tests/support.rs b/crates/rust-analyzer/tests/heavy_tests/support.rs
index e4fe3411a..8d47ee4f6 100644
--- a/crates/rust-analyzer/tests/heavy_tests/support.rs
+++ b/crates/rust-analyzer/tests/heavy_tests/support.rs
@@ -77,7 +77,11 @@ impl<'a> Project<'a> {
77 let roots = self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect(); 77 let roots = self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect();
78 78
79 let mut config = Config { 79 let mut config = Config {
80 client_caps: ClientCapsConfig { location_link: true, ..Default::default() }, 80 client_caps: ClientCapsConfig {
81 location_link: true,
82 code_action_literals: true,
83 ..Default::default()
84 },
81 with_sysroot: self.with_sysroot, 85 with_sysroot: self.with_sysroot,
82 ..Config::default() 86 ..Config::default()
83 }; 87 };
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 3a337c574..cee916c09 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -46,7 +46,7 @@ can be quickly updated for small modifications.
46 46
47Some of the components of this repository are generated through automatic 47Some of the components of this repository are generated through automatic
48processes. `cargo xtask codegen` runs all generation tasks. Generated code is 48processes. `cargo xtask codegen` runs all generation tasks. Generated code is
49commited to the git repository. 49committed to the git repository.
50 50
51In particular, `cargo xtask codegen` generates: 51In particular, `cargo xtask codegen` generates:
52 52
@@ -114,7 +114,7 @@ is responsible for guessing a HIR for a particular source position.
114Underneath, HIR works on top of salsa, using a `HirDatabase` trait. 114Underneath, HIR works on top of salsa, using a `HirDatabase` trait.
115 115
116`ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and 116`ra_hir_xxx` crates have a strong ECS flavor, in that they work with raw ids and
117directly query the databse. 117directly query the database.
118 118
119The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API. 119The top-level `ra_hir` façade crate wraps ids into a more OO-flavored API.
120 120
diff --git a/docs/dev/guide.md b/docs/dev/guide.md
index abbe4c154..c3252f1f6 100644
--- a/docs/dev/guide.md
+++ b/docs/dev/guide.md
@@ -26,7 +26,7 @@ properties hold:
26 26
27## IDE API 27## IDE API
28 28
29To see the bigger picture of how the IDE features works, let's take a look at the [`AnalysisHost`] and 29To see the bigger picture of how the IDE features work, let's take a look at the [`AnalysisHost`] and
30[`Analysis`] pair of types. `AnalysisHost` has three methods: 30[`Analysis`] pair of types. `AnalysisHost` has three methods:
31 31
32* `default()` for creating an empty analysis instance 32* `default()` for creating an empty analysis instance
@@ -131,7 +131,7 @@ mapping between `SourceRoot` IDs (which are assigned by the client) and actual
131analyzer. 131analyzer.
132 132
133Note that `mod`, `#[path]` and `include!()` can only reference files from the 133Note that `mod`, `#[path]` and `include!()` can only reference files from the
134same source root. It is of course is possible to explicitly add extra files to 134same source root. It is of course possible to explicitly add extra files to
135the source root, even `/dev/random`. 135the source root, even `/dev/random`.
136 136
137## Language Server Protocol 137## Language Server Protocol
@@ -192,7 +192,7 @@ task will be canceled as soon as the main loop calls `apply_change` on the
192[`schedule`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455 192[`schedule`]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop.rs#L426-L455
193[The task]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223 193[The task]: https://github.com/rust-analyzer/rust-analyzer/blob/guide-2019-01/crates/ra_lsp_server/src/main_loop/handlers.rs#L205-L223
194 194
195This concludes the overview of the analyzer's programing *interface*. Next, lets 195This concludes the overview of the analyzer's programing *interface*. Next, let's
196dig into the implementation! 196dig into the implementation!
197 197
198## Salsa 198## Salsa
@@ -480,7 +480,7 @@ throughout the analyzer:
480## Source Map pattern 480## Source Map pattern
481 481
482Due to an obscure edge case in completion, IDE needs to know the syntax node of 482Due to an obscure edge case in completion, IDE needs to know the syntax node of
483an use statement which imported the given completion candidate. We can't just 483a use statement which imported the given completion candidate. We can't just
484store the syntax node as a part of name resolution: this will break 484store the syntax node as a part of name resolution: this will break
485incrementality, due to the fact that syntax changes after every file 485incrementality, due to the fact that syntax changes after every file
486modification. 486modification.
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index 4cb1e23e8..b1af72ce6 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -201,7 +201,7 @@ let g:LanguageClient_serverCommands = {
201 201
2022. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists): 2022. Configure by adding this to your vim/neovim config file (replacing the existing Rust-specific line if it exists):
203+ 203+
204[source,vim] 204[source,vim]
205---- 205----
206let g:ycm_language_server = 206let g:ycm_language_server =
207\ [ 207\ [
@@ -252,6 +252,15 @@ If it worked, you should see "rust-analyzer, Line X, Column Y" on the left side
252 252
253If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary. 253If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary.
254 254
255=== Gnome Builder
256
257Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
258
259Gnome Builder currently has support for RLS, and there's no way to configure the language server executable. A future version might support `rust-analyzer` out of the box.
260
2611. Rename, symlink or copy the `rust-analyzer` binary to `rls` and place it somewhere Builder can find (in `PATH`, or under `~/.cargo/bin`).
2622. Enable the Rust Builder plugin.
263
255== Usage 264== Usage
256 265
257See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md]. 266See https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/features.md[features.md].
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index bdd42cb76..703fb9be9 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -593,7 +593,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
593 qualifier: Path, 593 qualifier: Path,
594 } 594 }
595 struct PathSegment { 595 struct PathSegment {
596 T![::], T![crate], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] 596 T![::], T![crate], T![self], T![super], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
597 } 597 }
598 struct TypeArgList { 598 struct TypeArgList {
599 T![::], 599 T![::],