aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/gen_lsp_server/Cargo.toml2
-rw-r--r--crates/ra_assists/src/add_explicit_type.rs4
-rw-r--r--crates/ra_assists/src/ast_editor.rs14
-rw-r--r--crates/ra_assists/src/auto_import.rs7
-rw-r--r--crates/ra_assists/src/change_visibility.rs5
-rw-r--r--crates/ra_assists/src/flip_comma.rs4
-rw-r--r--crates/ra_assists/src/remove_dbg.rs8
-rw-r--r--crates/ra_assists/src/split_import.rs5
-rw-r--r--crates/ra_cli/src/analysis_stats.rs5
-rw-r--r--crates/ra_db/src/lib.rs7
-rw-r--r--crates/ra_fmt/src/lib.rs14
-rw-r--r--crates/ra_hir/Cargo.toml8
-rw-r--r--crates/ra_hir/src/db.rs13
-rw-r--r--crates/ra_hir/src/expr/validation.rs77
-rw-r--r--crates/ra_hir/src/generics.rs17
-rw-r--r--crates/ra_hir/src/mock.rs6
-rw-r--r--crates/ra_hir/src/name.rs2
-rw-r--r--crates/ra_hir/src/nameres/tests.rs286
-rw-r--r--crates/ra_hir/src/nameres/tests/globs.rs76
-rw-r--r--crates/ra_hir/src/nameres/tests/macros.rs54
-rw-r--r--crates/ra_hir/src/ty.rs4
-rw-r--r--crates/ra_hir/src/ty/infer.rs4
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs7
-rw-r--r--crates/ra_hir/src/ty/lower.rs86
-rw-r--r--crates/ra_hir/src/ty/tests.rs29
-rw-r--r--crates/ra_hir/src/ty/traits.rs10
-rw-r--r--crates/ra_ide_api/Cargo.toml2
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs6
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs2
-rw-r--r--crates/ra_ide_api/src/join_lines.rs9
-rw-r--r--crates/ra_ide_api/src/matching_brace.rs5
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs21
-rw-r--r--crates/ra_mbe/src/mbe_expander.rs6
-rw-r--r--crates/ra_mbe/src/subtree_source.rs22
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs45
-rw-r--r--crates/ra_mbe/src/tests.rs14
-rw-r--r--crates/ra_parser/src/event.rs2
-rw-r--r--crates/ra_parser/src/grammar.rs42
-rw-r--r--crates/ra_parser/src/grammar/attributes.rs10
-rw-r--r--crates/ra_parser/src/grammar/expressions.rs156
-rw-r--r--crates/ra_parser/src/grammar/expressions/atom.rs144
-rw-r--r--crates/ra_parser/src/grammar/items.rs114
-rw-r--r--crates/ra_parser/src/grammar/items/consts.rs10
-rw-r--r--crates/ra_parser/src/grammar/items/nominal.rs66
-rw-r--r--crates/ra_parser/src/grammar/items/traits.rs38
-rw-r--r--crates/ra_parser/src/grammar/items/use_item.rs30
-rw-r--r--crates/ra_parser/src/grammar/params.rs38
-rw-r--r--crates/ra_parser/src/grammar/paths.rs18
-rw-r--r--crates/ra_parser/src/grammar/patterns.rs78
-rw-r--r--crates/ra_parser/src/grammar/type_args.rs14
-rw-r--r--crates/ra_parser/src/grammar/type_params.rs46
-rw-r--r--crates/ra_parser/src/grammar/types.rs84
-rw-r--r--crates/ra_parser/src/parser.rs25
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs4
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs.tera2
-rw-r--r--crates/ra_prof/Cargo.toml1
-rw-r--r--crates/ra_prof/src/lib.rs36
-rw-r--r--crates/ra_syntax/Cargo.toml4
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs77
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs60
-rw-r--r--crates/ra_syntax/src/lib.rs9
-rw-r--r--crates/ra_syntax/src/parsing/lexer.rs25
-rw-r--r--crates/ra_syntax/src/parsing/reparsing.rs11
-rw-r--r--crates/ra_syntax/src/syntax_text.rs65
-rw-r--r--crates/ra_syntax/src/validation.rs7
65 files changed, 1114 insertions, 988 deletions
diff --git a/crates/gen_lsp_server/Cargo.toml b/crates/gen_lsp_server/Cargo.toml
index 34343e2f2..ba8bfdbd3 100644
--- a/crates/gen_lsp_server/Cargo.toml
+++ b/crates/gen_lsp_server/Cargo.toml
@@ -1,7 +1,7 @@
1[package] 1[package]
2edition = "2018" 2edition = "2018"
3name = "gen_lsp_server" 3name = "gen_lsp_server"
4version = "0.1.0" 4version = "0.2.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6repository = "https://github.com/rust-analyzer/rust-analyzer" 6repository = "https://github.com/rust-analyzer/rust-analyzer"
7license = "MIT OR Apache-2.0" 7license = "MIT OR Apache-2.0"
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs
index cb0ac9885..f3ed74b7f 100644
--- a/crates/ra_assists/src/add_explicit_type.rs
+++ b/crates/ra_assists/src/add_explicit_type.rs
@@ -3,7 +3,7 @@ use hir::{
3 db::HirDatabase, 3 db::HirDatabase,
4}; 4};
5use ra_syntax::{ 5use ra_syntax::{
6 SyntaxKind, 6 T,
7 ast::{LetStmt, PatKind, NameOwner, AstNode} 7 ast::{LetStmt, PatKind, NameOwner, AstNode}
8}; 8};
9 9
@@ -24,7 +24,7 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<
24 let name = pat.name()?; 24 let name = pat.name()?;
25 let name_range = name.syntax().range(); 25 let name_range = name.syntax().range();
26 // Assist not applicable if the type has already been specified 26 // Assist not applicable if the type has already been specified
27 if stmt.syntax().children_with_tokens().any(|child| child.kind() == SyntaxKind::COLON) { 27 if stmt.syntax().children_with_tokens().any(|child| child.kind() == T![:]) {
28 return None; 28 return None;
29 } 29 }
30 // Infer type 30 // Infer type
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index aa7aeaabb..9afcac01a 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -2,7 +2,7 @@ use std::{iter, ops::RangeInclusive};
2 2
3use arrayvec::ArrayVec; 3use arrayvec::ArrayVec;
4use ra_text_edit::TextEditBuilder; 4use ra_text_edit::TextEditBuilder;
5use ra_syntax::{AstNode, TreeArc, ast, SyntaxKind::*, SyntaxElement, SourceFile, InsertPosition, Direction}; 5use ra_syntax::{AstNode, TreeArc, ast, SyntaxKind::*, SyntaxElement, SourceFile, InsertPosition, Direction, T};
6use ra_fmt::leading_indent; 6use ra_fmt::leading_indent;
7use hir::Name; 7use hir::Name;
8 8
@@ -49,7 +49,7 @@ impl<N: AstNode> AstEditor<N> {
49 49
50 fn do_make_multiline(&mut self) { 50 fn do_make_multiline(&mut self) {
51 let l_curly = 51 let l_curly =
52 match self.ast().syntax().children_with_tokens().find(|it| it.kind() == L_CURLY) { 52 match self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{']) {
53 Some(it) => it, 53 Some(it) => it,
54 None => return, 54 None => return,
55 }; 55 };
@@ -124,7 +124,7 @@ impl AstEditor<ast::NamedFieldList> {
124 if let Some(comma) = $anchor 124 if let Some(comma) = $anchor
125 .syntax() 125 .syntax()
126 .siblings_with_tokens(Direction::Next) 126 .siblings_with_tokens(Direction::Next)
127 .find(|it| it.kind() == COMMA) 127 .find(|it| it.kind() == T![,])
128 { 128 {
129 InsertPosition::After(comma) 129 InsertPosition::After(comma)
130 } else { 130 } else {
@@ -154,7 +154,7 @@ impl AstEditor<ast::NamedFieldList> {
154 } 154 }
155 155
156 fn l_curly(&self) -> Option<SyntaxElement> { 156 fn l_curly(&self) -> Option<SyntaxElement> {
157 self.ast().syntax().children_with_tokens().find(|it| it.kind() == L_CURLY) 157 self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
158 } 158 }
159} 159}
160 160
@@ -188,7 +188,7 @@ impl AstEditor<ast::ItemList> {
188 } 188 }
189 189
190 fn l_curly(&self) -> Option<SyntaxElement> { 190 fn l_curly(&self) -> Option<SyntaxElement> {
191 self.ast().syntax().children_with_tokens().find(|it| it.kind() == L_CURLY) 191 self.ast().syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
192 } 192 }
193} 193}
194 194
@@ -290,7 +290,7 @@ fn ast_node_from_file_text<N: AstNode>(text: &str) -> TreeArc<N> {
290 290
291mod tokens { 291mod tokens {
292 use once_cell::sync::Lazy; 292 use once_cell::sync::Lazy;
293 use ra_syntax::{AstNode, SourceFile, TreeArc, SyntaxToken, SyntaxKind::*}; 293 use ra_syntax::{AstNode, SourceFile, TreeArc, SyntaxToken, SyntaxKind::*, T};
294 294
295 static SOURCE_FILE: Lazy<TreeArc<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); 295 static SOURCE_FILE: Lazy<TreeArc<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;"));
296 296
@@ -299,7 +299,7 @@ mod tokens {
299 .syntax() 299 .syntax()
300 .descendants_with_tokens() 300 .descendants_with_tokens()
301 .filter_map(|it| it.as_token()) 301 .filter_map(|it| it.as_token())
302 .find(|it| it.kind() == COMMA) 302 .find(|it| it.kind() == T![,])
303 .unwrap() 303 .unwrap()
304 } 304 }
305 305
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index 7c856c19b..1566cf179 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -2,8 +2,9 @@ use ra_text_edit::TextEditBuilder;
2use hir::{ self, db::HirDatabase}; 2use hir::{ self, db::HirDatabase};
3 3
4use ra_syntax::{ 4use ra_syntax::{
5 T,
5 ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange, SmolStr, 6 ast::{ self, NameOwner }, AstNode, SyntaxNode, Direction, TextRange, SmolStr,
6 SyntaxKind::{ PATH, PATH_SEGMENT, COLONCOLON, COMMA } 7 SyntaxKind::{ PATH, PATH_SEGMENT }
7}; 8};
8use crate::{ 9use crate::{
9 AssistId, 10 AssistId,
@@ -23,7 +24,7 @@ fn collect_path_segments_raw<'a>(
23 children.next().map(|n| (n, n.kind())), 24 children.next().map(|n| (n, n.kind())),
24 ); 25 );
25 match (first, second, third) { 26 match (first, second, third) {
26 (Some((subpath, PATH)), Some((_, COLONCOLON)), Some((segment, PATH_SEGMENT))) => { 27 (Some((subpath, PATH)), Some((_, T![::])), Some((segment, PATH_SEGMENT))) => {
27 path = ast::Path::cast(subpath.as_node()?)?; 28 path = ast::Path::cast(subpath.as_node()?)?;
28 segments.push(ast::PathSegment::cast(segment.as_node()?)?); 29 segments.push(ast::PathSegment::cast(segment.as_node()?)?);
29 } 30 }
@@ -421,7 +422,7 @@ fn make_assist_add_in_tree_list(
421 let last = tree_list.use_trees().last(); 422 let last = tree_list.use_trees().last();
422 if let Some(last) = last { 423 if let Some(last) = last {
423 let mut buf = String::new(); 424 let mut buf = String::new();
424 let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == COMMA); 425 let comma = last.syntax().siblings(Direction::Next).find(|n| n.kind() == T![,]);
425 let offset = if let Some(comma) = comma { 426 let offset = if let Some(comma) = comma {
426 comma.range().end() 427 comma.range().end()
427 } else { 428 } else {
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index c63470726..620f534b5 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -1,8 +1,9 @@
1use hir::db::HirDatabase; 1use hir::db::HirDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 T,
3 AstNode, SyntaxNode, TextUnit, 4 AstNode, SyntaxNode, TextUnit,
4 ast::{self, VisibilityOwner, NameOwner}, 5 ast::{self, VisibilityOwner, NameOwner},
5 SyntaxKind::{VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF, IDENT, WHITESPACE, COMMENT, ATTR}, 6 SyntaxKind::{VISIBILITY, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF, IDENT, WHITESPACE, COMMENT, ATTR},
6}; 7};
7 8
8use crate::{AssistCtx, Assist, AssistId}; 9use crate::{AssistCtx, Assist, AssistId};
@@ -16,7 +17,7 @@ pub(crate) fn change_visibility(ctx: AssistCtx<impl HirDatabase>) -> Option<Assi
16 17
17fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 18fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
18 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() { 19 let item_keyword = ctx.token_at_offset().find(|leaf| match leaf.kind() {
19 FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true, 20 T![fn] | T![mod] | T![struct] | T![enum] | T![trait] => true,
20 _ => false, 21 _ => false,
21 }); 22 });
22 23
diff --git a/crates/ra_assists/src/flip_comma.rs b/crates/ra_assists/src/flip_comma.rs
index a9b108111..7626ffad3 100644
--- a/crates/ra_assists/src/flip_comma.rs
+++ b/crates/ra_assists/src/flip_comma.rs
@@ -1,14 +1,14 @@
1use hir::db::HirDatabase; 1use hir::db::HirDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 T,
3 Direction, 4 Direction,
4 SyntaxKind::COMMA,
5 algo::non_trivia_sibling, 5 algo::non_trivia_sibling,
6}; 6};
7 7
8use crate::{AssistCtx, Assist, AssistId}; 8use crate::{AssistCtx, Assist, AssistId};
9 9
10pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 10pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
11 let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == COMMA)?; 11 let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?;
12 let prev = non_trivia_sibling(comma.into(), Direction::Prev)?; 12 let prev = non_trivia_sibling(comma.into(), Direction::Prev)?;
13 let next = non_trivia_sibling(comma.into(), Direction::Next)?; 13 let next = non_trivia_sibling(comma.into(), Direction::Next)?;
14 ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| { 14 ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| {
diff --git a/crates/ra_assists/src/remove_dbg.rs b/crates/ra_assists/src/remove_dbg.rs
index ae9958f11..6e900f8ef 100644
--- a/crates/ra_assists/src/remove_dbg.rs
+++ b/crates/ra_assists/src/remove_dbg.rs
@@ -2,9 +2,7 @@ use hir::db::HirDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, AstNode}, 3 ast::{self, AstNode},
4 TextUnit, 4 TextUnit,
5 SyntaxKind::{ 5 T
6 L_PAREN, R_PAREN, L_CURLY, R_CURLY, L_BRACK, R_BRACK, EXCL
7 },
8}; 6};
9use crate::{AssistCtx, Assist, AssistId}; 7use crate::{AssistCtx, Assist, AssistId};
10 8
@@ -64,7 +62,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
64 // Make sure it is actually a dbg-macro call, dbg followed by ! 62 // Make sure it is actually a dbg-macro call, dbg followed by !
65 let excl = path.syntax().next_sibling_or_token()?; 63 let excl = path.syntax().next_sibling_or_token()?;
66 64
67 if name_ref.text() != macro_name || excl.kind() != EXCL { 65 if name_ref.text() != macro_name || excl.kind() != T![!] {
68 return None; 66 return None;
69 } 67 }
70 68
@@ -73,7 +71,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
73 let last_child = node.last_child_or_token()?; 71 let last_child = node.last_child_or_token()?;
74 72
75 match (first_child.kind(), last_child.kind()) { 73 match (first_child.kind(), last_child.kind()) {
76 (L_PAREN, R_PAREN) | (L_BRACK, R_BRACK) | (L_CURLY, R_CURLY) => Some(true), 74 (T!['('], T![')']) | (T!['['], T![']']) | (T!['{'], T!['}']) => Some(true),
77 _ => Some(false), 75 _ => Some(false),
78 } 76 }
79} 77}
diff --git a/crates/ra_assists/src/split_import.rs b/crates/ra_assists/src/split_import.rs
index 57e0efaf2..881c5ecdc 100644
--- a/crates/ra_assists/src/split_import.rs
+++ b/crates/ra_assists/src/split_import.rs
@@ -2,14 +2,15 @@ use std::iter::successors;
2 2
3use hir::db::HirDatabase; 3use hir::db::HirDatabase;
4use ra_syntax::{ 4use ra_syntax::{
5 TextUnit, AstNode, SyntaxKind::COLONCOLON, 5 T,
6 TextUnit, AstNode,
6 ast, 7 ast,
7}; 8};
8 9
9use crate::{AssistCtx, Assist, AssistId}; 10use crate::{AssistCtx, Assist, AssistId};
10 11
11pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> { 12pub(crate) fn split_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
12 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == COLONCOLON)?; 13 let colon_colon = ctx.token_at_offset().find(|leaf| leaf.kind() == T![::])?;
13 let path = ast::Path::cast(colon_colon.parent())?; 14 let path = ast::Path::cast(colon_colon.parent())?;
14 let top_path = successors(Some(path), |it| it.parent_path()).last()?; 15 let top_path = successors(Some(path), |it| it.parent_path()).last()?;
15 16
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index c95d452b3..b481ace9e 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -51,7 +51,10 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
51 println!("Total modules found: {}", visited_modules.len()); 51 println!("Total modules found: {}", visited_modules.len());
52 println!("Total declarations: {}", num_decls); 52 println!("Total declarations: {}", num_decls);
53 println!("Total functions: {}", funcs.len()); 53 println!("Total functions: {}", funcs.len());
54 let bar = indicatif::ProgressBar::new(funcs.len() as u64); 54 let bar = indicatif::ProgressBar::with_draw_target(
55 funcs.len() as u64,
56 indicatif::ProgressDrawTarget::stderr_nohz(),
57 );
55 bar.set_style( 58 bar.set_style(
56 indicatif::ProgressStyle::default_bar().template("{wide_bar} {pos}/{len}\n{msg}"), 59 indicatif::ProgressStyle::default_bar().template("{wide_bar} {pos}/{len}\n{msg}"),
57 ); 60 );
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 1cd400752..bf567721a 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -15,7 +15,7 @@ pub use crate::{
15 }, 15 },
16}; 16};
17 17
18pub trait CheckCanceled: panic::RefUnwindSafe { 18pub trait CheckCanceled {
19 /// Aborts current query if there are pending changes. 19 /// Aborts current query if there are pending changes.
20 /// 20 ///
21 /// rust-analyzer needs to be able to answer semantic questions about the 21 /// rust-analyzer needs to be able to answer semantic questions about the
@@ -36,14 +36,15 @@ pub trait CheckCanceled: panic::RefUnwindSafe {
36 Self: Sized, 36 Self: Sized,
37 F: FnOnce(&Self) -> T + panic::UnwindSafe, 37 F: FnOnce(&Self) -> T + panic::UnwindSafe,
38 { 38 {
39 panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() { 39 let this = panic::AssertUnwindSafe(self);
40 panic::catch_unwind(|| f(*this)).map_err(|err| match err.downcast::<Canceled>() {
40 Ok(canceled) => *canceled, 41 Ok(canceled) => *canceled,
41 Err(payload) => panic::resume_unwind(payload), 42 Err(payload) => panic::resume_unwind(payload),
42 }) 43 })
43 } 44 }
44} 45}
45 46
46impl<T: salsa::Database + panic::RefUnwindSafe> CheckCanceled for T { 47impl<T: salsa::Database> CheckCanceled for T {
47 fn check_canceled(&self) { 48 fn check_canceled(&self) {
48 if self.salsa_runtime().is_current_revision_canceled() { 49 if self.salsa_runtime().is_current_revision_canceled() {
49 Canceled::throw() 50 Canceled::throw()
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index 603be1854..aac5a1d23 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -3,7 +3,7 @@
3use std::iter::successors; 3use std::iter::successors;
4use itertools::Itertools; 4use itertools::Itertools;
5use ra_syntax::{ 5use ra_syntax::{
6 SyntaxNode, SyntaxKind::*, SyntaxToken, SyntaxKind, 6 SyntaxNode, SyntaxKind::*, SyntaxToken, SyntaxKind, T,
7 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
8}; 8};
9 9
@@ -38,7 +38,7 @@ pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> {
38 return None; 38 return None;
39 } 39 }
40 let non_trivial_children = block.syntax().children().filter(|it| match it.kind() { 40 let non_trivial_children = block.syntax().children().filter(|it| match it.kind() {
41 WHITESPACE | L_CURLY | R_CURLY => false, 41 WHITESPACE | T!['{'] | T!['}'] => false,
42 _ => it != &expr.syntax(), 42 _ => it != &expr.syntax(),
43 }); 43 });
44 if non_trivial_children.count() > 0 { 44 if non_trivial_children.count() > 0 {
@@ -49,8 +49,8 @@ pub fn extract_trivial_expression(block: &ast::Block) -> Option<&ast::Expr> {
49 49
50pub fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str { 50pub fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str {
51 match left { 51 match left {
52 L_PAREN | L_BRACK => return "", 52 T!['('] | T!['['] => return "",
53 L_CURLY => { 53 T!['{'] => {
54 if let USE_TREE = right { 54 if let USE_TREE = right {
55 return ""; 55 return "";
56 } 56 }
@@ -58,13 +58,13 @@ pub fn compute_ws(left: SyntaxKind, right: SyntaxKind) -> &'static str {
58 _ => (), 58 _ => (),
59 } 59 }
60 match right { 60 match right {
61 R_PAREN | R_BRACK => return "", 61 T![')'] | T![']'] => return "",
62 R_CURLY => { 62 T!['}'] => {
63 if let USE_TREE = left { 63 if let USE_TREE = left {
64 return ""; 64 return "";
65 } 65 }
66 } 66 }
67 DOT => return "", 67 T![.] => return "",
68 _ => (), 68 _ => (),
69 } 69 }
70 " " 70 " "
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml
index 68ffcb2e9..294d047d8 100644
--- a/crates/ra_hir/Cargo.toml
+++ b/crates/ra_hir/Cargo.toml
@@ -21,10 +21,10 @@ tt = { path = "../ra_tt", package = "ra_tt" }
21test_utils = { path = "../test_utils" } 21test_utils = { path = "../test_utils" }
22ra_prof = { path = "../ra_prof" } 22ra_prof = { path = "../ra_prof" }
23 23
24chalk-solve = { git = "https://github.com/rust-lang/chalk.git" } 24chalk-solve = { git = "https://github.com/flodiebold/chalk.git", branch = "fuel" }
25chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git" } 25chalk-rust-ir = { git = "https://github.com/flodiebold/chalk.git", branch = "fuel" }
26chalk-ir = { git = "https://github.com/rust-lang/chalk.git" } 26chalk-ir = { git = "https://github.com/flodiebold/chalk.git", branch = "fuel" }
27 27
28[dev-dependencies] 28[dev-dependencies]
29flexi_logger = "0.11.0" 29flexi_logger = "0.11.0"
30insta = "0.7.0" 30insta = "0.8.1"
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 8e827d4f5..11cdf9c34 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -11,7 +11,7 @@ use crate::{
11 DefWithBody, Trait, 11 DefWithBody, Trait,
12 ids, 12 ids,
13 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap}, 13 nameres::{Namespace, ImportSourceMap, RawItems, CrateDefMap},
14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor, GenericPredicate}, 14 ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, CallableDef, FnSig, TypeCtor, GenericPredicate, Substs},
15 adt::{StructData, EnumData}, 15 adt::{StructData, EnumData},
16 impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock}, 16 impl_block::{ModuleImplBlocks, ImplSourceMap, ImplBlock},
17 generics::{GenericParams, GenericDef}, 17 generics::{GenericParams, GenericDef},
@@ -126,7 +126,7 @@ pub trait HirDatabase: DefDatabase {
126 #[salsa::invoke(ExprScopes::expr_scopes_query)] 126 #[salsa::invoke(ExprScopes::expr_scopes_query)]
127 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>; 127 fn expr_scopes(&self, def: DefWithBody) -> Arc<ExprScopes>;
128 128
129 #[salsa::invoke(crate::ty::infer)] 129 #[salsa::invoke(crate::ty::infer_query)]
130 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>; 130 fn infer(&self, def: DefWithBody) -> Arc<InferenceResult>;
131 131
132 #[salsa::invoke(crate::ty::type_for_def)] 132 #[salsa::invoke(crate::ty::type_for_def)]
@@ -141,6 +141,9 @@ pub trait HirDatabase: DefDatabase {
141 #[salsa::invoke(crate::ty::generic_predicates)] 141 #[salsa::invoke(crate::ty::generic_predicates)]
142 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>; 142 fn generic_predicates(&self, def: GenericDef) -> Arc<[GenericPredicate]>;
143 143
144 #[salsa::invoke(crate::ty::generic_defaults)]
145 fn generic_defaults(&self, def: GenericDef) -> Substs;
146
144 #[salsa::invoke(crate::expr::body_with_source_map_query)] 147 #[salsa::invoke(crate::expr::body_with_source_map_query)]
145 fn body_with_source_map( 148 fn body_with_source_map(
146 &self, 149 &self,
@@ -153,7 +156,7 @@ pub trait HirDatabase: DefDatabase {
153 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] 156 #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)]
154 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; 157 fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>;
155 158
156 #[salsa::invoke(crate::ty::traits::impls_for_trait)] 159 #[salsa::invoke(crate::ty::traits::impls_for_trait_query)]
157 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>; 160 fn impls_for_trait(&self, krate: Crate, trait_: Trait) -> Arc<[ImplBlock]>;
158 161
159 /// This provides the Chalk trait solver instance. Because Chalk always 162 /// This provides the Chalk trait solver instance. Because Chalk always
@@ -161,11 +164,11 @@ pub trait HirDatabase: DefDatabase {
161 /// because Chalk does its own internal caching, the solver is wrapped in a 164 /// because Chalk does its own internal caching, the solver is wrapped in a
162 /// Mutex and the query is marked volatile, to make sure the cached state is 165 /// Mutex and the query is marked volatile, to make sure the cached state is
163 /// thrown away when input facts change. 166 /// thrown away when input facts change.
164 #[salsa::invoke(crate::ty::traits::solver)] 167 #[salsa::invoke(crate::ty::traits::solver_query)]
165 #[salsa::volatile] 168 #[salsa::volatile]
166 fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>; 169 fn solver(&self, krate: Crate) -> Arc<Mutex<crate::ty::traits::Solver>>;
167 170
168 #[salsa::invoke(crate::ty::traits::implements)] 171 #[salsa::invoke(crate::ty::traits::implements_query)]
169 fn implements( 172 fn implements(
170 &self, 173 &self,
171 krate: Crate, 174 krate: Crate,
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index aebed6788..3f758f283 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -5,13 +5,11 @@ use ra_syntax::ast::{AstNode, StructLit};
5 5
6use crate::{ 6use crate::{
7 expr::AstPtr, 7 expr::AstPtr,
8 HirDatabase, 8 HirDatabase, Function, Name,
9 Function,
10 Name,
11 diagnostics::{DiagnosticSink, MissingFields}, 9 diagnostics::{DiagnosticSink, MissingFields},
12 adt::AdtDef, 10 adt::AdtDef,
13 Path, 11 Path,
14 ty::InferenceResult 12 ty::InferenceResult,
15}; 13};
16use super::{Expr, StructLitField, ExprId}; 14use super::{Expr, StructLitField, ExprId};
17 15
@@ -50,43 +48,46 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
50 spread: &Option<ExprId>, 48 spread: &Option<ExprId>,
51 db: &impl HirDatabase, 49 db: &impl HirDatabase,
52 ) { 50 ) {
53 if let Some(_) = spread { 51 if spread.is_some() {
54 return; 52 return;
55 } 53 }
54
55 let struct_def = match self.infer[id].as_adt() {
56 Some((AdtDef::Struct(s), _)) => s,
57 _ => return,
58 };
59
56 let lit_fields: FxHashSet<_> = fields.into_iter().map(|f| &f.name).collect(); 60 let lit_fields: FxHashSet<_> = fields.into_iter().map(|f| &f.name).collect();
57 let struct_ty = &self.infer[id]; 61 let missed_fields: Vec<Name> = struct_def
58 if let Some((AdtDef::Struct(s), _)) = struct_ty.as_adt() { 62 .fields(db)
59 let missed_fields: Vec<Name> = s 63 .iter()
60 .fields(db) 64 .filter_map(|f| {
61 .iter() 65 let name = f.name(db);
62 .filter_map(|f| { 66 if lit_fields.contains(&name) {
63 let name = f.name(db); 67 None
64 if lit_fields.contains(&name) { 68 } else {
65 None 69 Some(name)
66 } else { 70 }
67 Some(name) 71 })
68 } 72 .collect();
69 }) 73 if missed_fields.is_empty() {
70 .collect(); 74 return;
71 if missed_fields.is_empty() { 75 }
72 return; 76 let source_map = self.func.body_source_map(db);
73 } 77 let file_id = self.func.source(db).0;
74 let source_map = self.func.body_source_map(db); 78 let source_file = db.parse(file_id.original_file(db));
75 let file_id = self.func.source(db).0; 79 if let Some(field_list_node) = source_map
76 let source_file = db.parse(file_id.original_file(db)); 80 .expr_syntax(id)
77 if let Some(field_list_node) = source_map 81 .map(|ptr| ptr.to_node(source_file.syntax()))
78 .expr_syntax(id) 82 .and_then(StructLit::cast)
79 .map(|ptr| ptr.to_node(source_file.syntax())) 83 .and_then(|lit| lit.named_field_list())
80 .and_then(StructLit::cast) 84 {
81 .and_then(|lit| lit.named_field_list()) 85 let field_list_ptr = AstPtr::new(field_list_node);
82 { 86 self.sink.push(MissingFields {
83 let field_list_ptr = AstPtr::new(field_list_node); 87 file: file_id,
84 self.sink.push(MissingFields { 88 field_list: field_list_ptr,
85 file: file_id, 89 missed_fields,
86 field_list: field_list_ptr, 90 })
87 missed_fields,
88 })
89 }
90 } 91 }
91 } 92 }
92} 93}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index c29b96f50..79a7fa23a 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -5,7 +5,7 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultTypeParamOwner};
9 9
10use crate::{ 10use crate::{
11 db::{ HirDatabase, DefDatabase}, 11 db::{ HirDatabase, DefDatabase},
@@ -18,6 +18,7 @@ pub struct GenericParam {
18 // FIXME: give generic params proper IDs 18 // FIXME: give generic params proper IDs
19 pub(crate) idx: u32, 19 pub(crate) idx: u32,
20 pub(crate) name: Name, 20 pub(crate) name: Name,
21 pub(crate) default: Option<Path>,
21} 22}
22 23
23/// Data about the generic parameters of a function, struct, impl, etc. 24/// Data about the generic parameters of a function, struct, impl, etc.
@@ -68,7 +69,11 @@ impl GenericParams {
68 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), 69 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start),
69 GenericDef::Trait(it) => { 70 GenericDef::Trait(it) => {
70 // traits get the Self type as an implicit first type parameter 71 // traits get the Self type as an implicit first type parameter
71 generics.params.push(GenericParam { idx: start, name: Name::self_type() }); 72 generics.params.push(GenericParam {
73 idx: start,
74 name: Name::self_type(),
75 default: None,
76 });
72 generics.fill(&*it.source(db).1, start + 1); 77 generics.fill(&*it.source(db).1, start + 1);
73 } 78 }
74 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), 79 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start),
@@ -90,7 +95,9 @@ impl GenericParams {
90 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { 95 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
91 for (idx, type_param) in params.type_params().enumerate() { 96 for (idx, type_param) in params.type_params().enumerate() {
92 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); 97 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
93 let param = GenericParam { idx: idx as u32 + start, name: name.clone() }; 98 let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast);
99
100 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
94 self.params.push(param); 101 self.params.push(param);
95 102
96 let type_ref = TypeRef::Path(name.into()); 103 let type_ref = TypeRef::Path(name.into());
@@ -190,13 +197,13 @@ impl From<crate::adt::AdtDef> for GenericDef {
190 } 197 }
191} 198}
192 199
193pub trait HasGenericParams { 200pub trait HasGenericParams: Copy {
194 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>; 201 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>;
195} 202}
196 203
197impl<T> HasGenericParams for T 204impl<T> HasGenericParams for T
198where 205where
199 T: Into<GenericDef>, 206 T: Into<GenericDef> + Copy,
200{ 207{
201 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> { 208 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> {
202 db.generic_params(self.into()) 209 db.generic_params(self.into())
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index fa5882dea..b84cb7503 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -236,7 +236,7 @@ impl MockDatabase {
236} 236}
237 237
238#[derive(Default)] 238#[derive(Default)]
239pub struct CrateGraphFixture(pub FxHashMap<String, (String, Edition, Vec<String>)>); 239pub struct CrateGraphFixture(pub Vec<(String, (String, Edition, Vec<String>))>);
240 240
241#[macro_export] 241#[macro_export]
242macro_rules! crate_graph { 242macro_rules! crate_graph {
@@ -246,10 +246,10 @@ macro_rules! crate_graph {
246 #[allow(unused_mut, unused_assignments)] 246 #[allow(unused_mut, unused_assignments)]
247 let mut edition = ra_db::Edition::Edition2018; 247 let mut edition = ra_db::Edition::Edition2018;
248 $(edition = ra_db::Edition::from_string($edition);)? 248 $(edition = ra_db::Edition::from_string($edition);)?
249 res.0.insert( 249 res.0.push((
250 $crate_name.to_string(), 250 $crate_name.to_string(),
251 ($crate_path.to_string(), edition, vec![$($dep.to_string()),*]) 251 ($crate_path.to_string(), edition, vec![$($dep.to_string()),*])
252 ); 252 ));
253 )* 253 )*
254 res 254 res
255 }} 255 }}
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 9a999e66c..e3a82cf03 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -5,7 +5,7 @@ use ra_syntax::{ast, SmolStr};
5/// `Name` is a wrapper around string, which is used in hir for both references 5/// `Name` is a wrapper around string, which is used in hir for both references
6/// and declarations. In theory, names should also carry hygiene info, but we are 6/// and declarations. In theory, names should also carry hygiene info, but we are
7/// not there yet! 7/// not there yet!
8#[derive(Clone, PartialEq, Eq, Hash)] 8#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Name { 9pub struct Name {
10 text: SmolStr, 10 text: SmolStr,
11} 11}
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs
index 572bd1bf7..14c8ee50b 100644
--- a/crates/ra_hir/src/nameres/tests.rs
+++ b/crates/ra_hir/src/nameres/tests.rs
@@ -8,7 +8,11 @@ use ra_db::SourceDatabase;
8use test_utils::covers; 8use test_utils::covers;
9use insta::assert_snapshot_matches; 9use insta::assert_snapshot_matches;
10 10
11use crate::{Crate, mock::{MockDatabase, CrateGraphFixture}, nameres::Resolution}; 11use crate::{
12 Crate,
13 mock::{MockDatabase, CrateGraphFixture},
14 nameres::Resolution,
15};
12 16
13use super::*; 17use super::*;
14 18
@@ -25,12 +29,15 @@ fn compute_crate_def_map(fixture: &str, graph: Option<CrateGraphFixture>) -> Arc
25fn render_crate_def_map(map: &CrateDefMap) -> String { 29fn render_crate_def_map(map: &CrateDefMap) -> String {
26 let mut buf = String::new(); 30 let mut buf = String::new();
27 go(&mut buf, map, "\ncrate", map.root); 31 go(&mut buf, map, "\ncrate", map.root);
28 return buf; 32 return buf.trim().to_string();
29 33
30 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) { 34 fn go(buf: &mut String, map: &CrateDefMap, path: &str, module: CrateModuleId) {
31 *buf += path; 35 *buf += path;
32 *buf += "\n"; 36 *buf += "\n";
33 for (name, res) in map.modules[module].scope.items.iter() { 37
38 let mut entries = map.modules[module].scope.items.iter().collect::<Vec<_>>();
39 entries.sort_by_key(|(name, _)| *name);
40 for (name, res) in entries {
34 *buf += &format!("{}: {}\n", name, dump_resolution(res)) 41 *buf += &format!("{}: {}\n", name, dump_resolution(res))
35 } 42 }
36 for (name, child) in map.modules[module].children.iter() { 43 for (name, child) in map.modules[module].children.iter() {
@@ -54,8 +61,8 @@ fn def_map(fixtute: &str) -> String {
54 render_crate_def_map(&dm) 61 render_crate_def_map(&dm)
55} 62}
56 63
57fn def_map_with_crate_graph(fixtute: &str, graph: CrateGraphFixture) -> String { 64fn def_map_with_crate_graph(fixture: &str, graph: CrateGraphFixture) -> String {
58 let dm = compute_crate_def_map(fixtute, Some(graph)); 65 let dm = compute_crate_def_map(fixture, Some(graph));
59 render_crate_def_map(&dm) 66 render_crate_def_map(&dm)
60} 67}
61 68
@@ -79,21 +86,20 @@ fn crate_def_map_smoke_test() {
79 ", 86 ",
80 ); 87 );
81 assert_snapshot_matches!(map, @r###" 88 assert_snapshot_matches!(map, @r###"
82crate 89 â‹®crate
83V: t v 90 â‹®E: t
84E: t 91 â‹®S: t v
85foo: t 92 â‹®V: t v
86S: t v 93 â‹®foo: t
87 94 â‹®
88crate::foo 95 â‹®crate::foo
89bar: t 96 â‹®bar: t
90f: v 97 â‹®f: v
91 98 â‹®
92crate::foo::bar 99 â‹®crate::foo::bar
93Baz: t v 100 â‹®Baz: t v
94E: t 101 â‹®E: t
95"### 102 "###)
96 )
97} 103}
98 104
99#[test] 105#[test]
@@ -113,12 +119,12 @@ fn bogus_paths() {
113 ", 119 ",
114 ); 120 );
115 assert_snapshot_matches!(map, @r###" 121 assert_snapshot_matches!(map, @r###"
116crate 122 â‹®crate
117foo: t 123 â‹®S: t v
118S: t v 124 â‹®foo: t
119 125 â‹®
120crate::foo 126 â‹®crate::foo
121"### 127 "###
122 ) 128 )
123} 129}
124 130
@@ -137,13 +143,13 @@ fn use_as() {
137 ); 143 );
138 assert_snapshot_matches!(map, 144 assert_snapshot_matches!(map,
139 @r###" 145 @r###"
140crate 146 â‹®crate
141Foo: t v 147 â‹®Foo: t v
142foo: t 148 â‹®foo: t
143 149 â‹®
144crate::foo 150 â‹®crate::foo
145Baz: t v 151 â‹®Baz: t v
146"### 152 "###
147 ); 153 );
148} 154}
149 155
@@ -164,21 +170,19 @@ fn use_trees() {
164 pub enum Quux {}; 170 pub enum Quux {};
165 ", 171 ",
166 ); 172 );
167 assert_snapshot_matches!(map, 173 assert_snapshot_matches!(map, @r###"
168 @r###" 174 â‹®crate
169crate 175 â‹®Baz: t v
170Quux: t 176 â‹®Quux: t
171Baz: t v 177 â‹®foo: t
172foo: t 178 â‹®
173 179 â‹®crate::foo
174crate::foo 180 â‹®bar: t
175bar: t 181 â‹®
176 182 â‹®crate::foo::bar
177crate::foo::bar 183 â‹®Baz: t v
178Quux: t 184 â‹®Quux: t
179Baz: t v 185 "###);
180"###
181 );
182} 186}
183 187
184#[test] 188#[test]
@@ -199,20 +203,18 @@ fn re_exports() {
199 pub struct Baz; 203 pub struct Baz;
200 ", 204 ",
201 ); 205 );
202 assert_snapshot_matches!(map, 206 assert_snapshot_matches!(map, @r###"
203 @r###" 207 â‹®crate
204crate 208 â‹®Baz: t v
205Baz: t v 209 â‹®foo: t
206foo: t 210 â‹®
207 211 â‹®crate::foo
208crate::foo 212 â‹®Baz: t v
209bar: t 213 â‹®bar: t
210Baz: t v 214 â‹®
211 215 â‹®crate::foo::bar
212crate::foo::bar 216 â‹®Baz: t v
213Baz: t v 217 "###);
214"###
215 );
216} 218}
217 219
218#[test] 220#[test]
@@ -237,10 +239,10 @@ fn std_prelude() {
237 }, 239 },
238 ); 240 );
239 assert_snapshot_matches!(map, @r###" 241 assert_snapshot_matches!(map, @r###"
240crate 242 â‹®crate
241Bar: t v 243 â‹®Bar: t v
242Baz: t v 244 â‹®Baz: t v
243"###); 245 "###);
244} 246}
245 247
246#[test] 248#[test]
@@ -254,10 +256,10 @@ fn can_import_enum_variant() {
254 ", 256 ",
255 ); 257 );
256 assert_snapshot_matches!(map, @r###" 258 assert_snapshot_matches!(map, @r###"
257crate 259 â‹®crate
258V: t v 260 â‹®E: t
259E: t 261 â‹®V: t v
260"### 262 "###
261 ); 263 );
262} 264}
263 265
@@ -285,20 +287,18 @@ fn edition_2015_imports() {
285 }, 287 },
286 ); 288 );
287 289
288 assert_snapshot_matches!(map, 290 assert_snapshot_matches!(map, @r###"
289 @r###" 291 â‹®crate
290crate 292 â‹®bar: t
291bar: t 293 â‹®foo: t
292foo: t 294 â‹®
293 295 â‹®crate::bar
294crate::bar 296 â‹®Bar: t v
295Bar: t v 297 â‹®
296 298 â‹®crate::foo
297crate::foo 299 â‹®Bar: t v
298FromLib: t v 300 â‹®FromLib: t v
299Bar: t v 301 "###);
300"###
301 );
302} 302}
303 303
304#[test] 304#[test]
@@ -317,16 +317,14 @@ fn module_resolution_works_for_non_standard_filenames() {
317 }, 317 },
318 ); 318 );
319 319
320 assert_snapshot_matches!(map, 320 assert_snapshot_matches!(map, @r###"
321 @r###" 321 â‹®crate
322crate 322 â‹®Bar: t v
323Bar: t v 323 â‹®foo: t
324foo: t 324 â‹®
325 325 â‹®crate::foo
326crate::foo 326 â‹®Bar: t v
327Bar: t v 327 "###);
328"###
329 );
330} 328}
331 329
332#[test] 330#[test]
@@ -348,12 +346,10 @@ fn name_res_works_for_broken_modules() {
348 pub struct Baz; 346 pub struct Baz;
349 ", 347 ",
350 ); 348 );
351 assert_snapshot_matches!(map, 349 assert_snapshot_matches!(map, @r###"
352 @r###" 350 â‹®crate
353crate 351 â‹®Baz: _
354Baz: _ 352 "###);
355"###
356 );
357} 353}
358 354
359#[test] 355#[test]
@@ -369,19 +365,17 @@ fn item_map_using_self() {
369 pub struct Baz; 365 pub struct Baz;
370 ", 366 ",
371 ); 367 );
372 assert_snapshot_matches!(map, 368 assert_snapshot_matches!(map, @r###"
373 @r###" 369 â‹®crate
374crate 370 â‹®Baz: t v
375Baz: t v 371 â‹®foo: t
376foo: t 372 â‹®
377 373 â‹®crate::foo
378crate::foo 374 â‹®bar: t
379bar: t 375 â‹®
380 376 â‹®crate::foo::bar
381crate::foo::bar 377 â‹®Baz: t v
382Baz: t v 378 "###);
383"###
384 );
385} 379}
386 380
387#[test] 381#[test]
@@ -400,12 +394,10 @@ fn item_map_across_crates() {
400 }, 394 },
401 ); 395 );
402 396
403 assert_snapshot_matches!(map, 397 assert_snapshot_matches!(map, @r###"
404 @r###" 398 â‹®crate
405crate 399 â‹®Baz: t v
406Baz: t v 400 "###);
407"###
408 );
409} 401}
410 402
411#[test] 403#[test]
@@ -430,12 +422,14 @@ fn extern_crate_rename() {
430 }, 422 },
431 ); 423 );
432 424
433 assert_snapshot_matches!(map, 425 assert_snapshot_matches!(map, @r###"
434 @r###" 426 â‹®crate
435crate 427 â‹®alloc_crate: t
436Arc: t v 428 â‹®sync: t
437"### 429 â‹®
438 ); 430 â‹®crate::sync
431 â‹®Arc: t v
432 "###);
439} 433}
440 434
441#[test] 435#[test]
@@ -462,9 +456,13 @@ fn extern_crate_rename_2015_edition() {
462 456
463 assert_snapshot_matches!(map, 457 assert_snapshot_matches!(map,
464 @r###" 458 @r###"
465crate 459 â‹®crate
466Arc: t v 460 â‹®alloc_crate: t
467"### 461 â‹®sync: t
462 â‹®
463 â‹®crate::sync
464 â‹®Arc: t v
465 "###
468 ); 466 );
469} 467}
470 468
@@ -490,12 +488,10 @@ fn import_across_source_roots() {
490 }, 488 },
491 ); 489 );
492 490
493 assert_snapshot_matches!(map, 491 assert_snapshot_matches!(map, @r###"
494 @r###" 492 â‹®crate
495crate 493 â‹®C: t v
496C: t v 494 "###);
497"###
498 );
499} 495}
500 496
501#[test] 497#[test]
@@ -519,12 +515,10 @@ fn reexport_across_crates() {
519 }, 515 },
520 ); 516 );
521 517
522 assert_snapshot_matches!(map, 518 assert_snapshot_matches!(map, @r###"
523 @r###" 519 â‹®crate
524crate 520 â‹®Baz: t v
525Baz: t v 521 "###);
526"###
527 );
528} 522}
529 523
530#[test] 524#[test]
@@ -544,13 +538,11 @@ fn values_dont_shadow_extern_crates() {
544 }, 538 },
545 ); 539 );
546 540
547 assert_snapshot_matches!(map, 541 assert_snapshot_matches!(map, @r###"
548 @r###" 542 â‹®crate
549crate 543 â‹®Bar: t v
550Bar: t v 544 â‹®foo: v
551foo: v 545 "###);
552"###
553 );
554} 546}
555 547
556#[test] 548#[test]
diff --git a/crates/ra_hir/src/nameres/tests/globs.rs b/crates/ra_hir/src/nameres/tests/globs.rs
index 6e50c7ff6..e1519ca6b 100644
--- a/crates/ra_hir/src/nameres/tests/globs.rs
+++ b/crates/ra_hir/src/nameres/tests/globs.rs
@@ -18,20 +18,20 @@ fn glob_1() {
18 ", 18 ",
19 ); 19 );
20 assert_snapshot_matches!(map, @r###" 20 assert_snapshot_matches!(map, @r###"
21crate 21 â‹®crate
22bar: t 22 â‹®Baz: t v
23Foo: t v 23 â‹®Foo: t v
24Baz: t v 24 â‹®bar: t
25foo: t 25 â‹®foo: t
26 26 â‹®
27crate::foo 27 â‹®crate::foo
28bar: t 28 â‹®Baz: t v
29Foo: t v 29 â‹®Foo: t v
30Baz: t v 30 â‹®bar: t
31 31 â‹®
32crate::foo::bar 32 â‹®crate::foo::bar
33Baz: t v 33 â‹®Baz: t v
34"### 34 "###
35 ); 35 );
36} 36}
37 37
@@ -54,22 +54,22 @@ fn glob_2() {
54 ", 54 ",
55 ); 55 );
56 assert_snapshot_matches!(map, @r###" 56 assert_snapshot_matches!(map, @r###"
57crate 57 â‹®crate
58bar: t 58 â‹®Baz: t v
59Foo: t v 59 â‹®Foo: t v
60Baz: t v 60 â‹®bar: t
61foo: t 61 â‹®foo: t
62 62 â‹®
63crate::foo 63 â‹®crate::foo
64bar: t 64 â‹®Baz: t v
65Foo: t v 65 â‹®Foo: t v
66Baz: t v 66 â‹®bar: t
67 67 â‹®
68crate::foo::bar 68 â‹®crate::foo::bar
69bar: t 69 â‹®Baz: t v
70Foo: t v 70 â‹®Foo: t v
71Baz: t v 71 â‹®bar: t
72"### 72 "###
73 ); 73 );
74} 74}
75 75
@@ -90,9 +90,9 @@ fn glob_across_crates() {
90 }, 90 },
91 ); 91 );
92 assert_snapshot_matches!(map, @r###" 92 assert_snapshot_matches!(map, @r###"
93crate 93 â‹®crate
94Baz: t v 94 â‹®Baz: t v
95"### 95 "###
96 ); 96 );
97} 97}
98 98
@@ -109,10 +109,10 @@ fn glob_enum() {
109 ", 109 ",
110 ); 110 );
111 assert_snapshot_matches!(map, @r###" 111 assert_snapshot_matches!(map, @r###"
112crate 112 â‹®crate
113Foo: t 113 â‹®Bar: t v
114Bar: t v 114 â‹®Baz: t v
115Baz: t v 115 â‹®Foo: t
116"### 116 "###
117 ); 117 );
118} 118}
diff --git a/crates/ra_hir/src/nameres/tests/macros.rs b/crates/ra_hir/src/nameres/tests/macros.rs
index 8781b026b..f7ca380ad 100644
--- a/crates/ra_hir/src/nameres/tests/macros.rs
+++ b/crates/ra_hir/src/nameres/tests/macros.rs
@@ -18,14 +18,14 @@ fn macro_rules_are_globally_visible() {
18 ", 18 ",
19 ); 19 );
20 assert_snapshot_matches!(map, @r###" 20 assert_snapshot_matches!(map, @r###"
21crate 21 â‹®crate
22nested: t 22 â‹®Foo: t v
23Foo: t v 23 â‹®nested: t
24 24 â‹®
25crate::nested 25 â‹®crate::nested
26Bar: t v 26 â‹®Bar: t v
27Baz: t v 27 â‹®Baz: t v
28"###); 28 "###);
29} 29}
30 30
31#[test] 31#[test]
@@ -45,15 +45,15 @@ fn macro_rules_can_define_modules() {
45 ", 45 ",
46 ); 46 );
47 assert_snapshot_matches!(map, @r###" 47 assert_snapshot_matches!(map, @r###"
48crate 48 â‹®crate
49n1: t 49 â‹®n1: t
50 50 â‹®
51crate::n1 51 â‹®crate::n1
52n2: t 52 â‹®n2: t
53 53 â‹®
54crate::n1::n2 54 â‹®crate::n1::n2
55X: t v 55 â‹®X: t v
56"###); 56 "###);
57} 57}
58 58
59#[test] 59#[test]
@@ -81,14 +81,14 @@ fn macro_rules_from_other_crates_are_visible() {
81 }, 81 },
82 ); 82 );
83 assert_snapshot_matches!(map, @r###" 83 assert_snapshot_matches!(map, @r###"
84crate 84 â‹®crate
85bar: t 85 â‹®Bar: t v
86Foo: t v 86 â‹®Foo: t v
87Bar: t v 87 â‹®bar: t
88 88 â‹®
89crate::bar 89 â‹®crate::bar
90bar: t 90 â‹®Bar: t v
91Foo: t v 91 â‹®Foo: t v
92Bar: t v 92 â‹®bar: t
93"###); 93 "###);
94} 94}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index cfe07156b..3679a2242 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -19,8 +19,8 @@ use std::{fmt, mem};
19use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams}; 19use crate::{Name, AdtDef, type_ref::Mutability, db::HirDatabase, Trait, GenericParams};
20use display::{HirDisplay, HirFormatter}; 20use display::{HirDisplay, HirFormatter};
21 21
22pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig, generic_predicates}; 22pub(crate) use lower::{TypableDef, type_for_def, type_for_field, callable_item_sig, generic_predicates, generic_defaults};
23pub(crate) use infer::{infer, InferenceResult, InferTy}; 23pub(crate) use infer::{infer_query, InferenceResult, InferTy};
24pub use lower::CallableDef; 24pub use lower::CallableDef;
25 25
26/// A type constructor or type name: this might be something like the primitive 26/// A type constructor or type name: this might be something like the primitive
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 1e7d97f51..a48272981 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -23,6 +23,7 @@ use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError};
23use rustc_hash::FxHashMap; 23use rustc_hash::FxHashMap;
24 24
25use ra_arena::map::ArenaMap; 25use ra_arena::map::ArenaMap;
26use ra_prof::profile;
26use test_utils::tested_by; 27use test_utils::tested_by;
27 28
28use crate::{ 29use crate::{
@@ -51,7 +52,8 @@ use super::{
51mod unify; 52mod unify;
52 53
53/// The entry point of type inference. 54/// The entry point of type inference.
54pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { 55pub fn infer_query(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> {
56 let _p = profile("infer_query");
55 db.check_canceled(); 57 db.check_canceled();
56 let body = def.body(db); 58 let body = def.body(db);
57 let resolver = def.resolver(db); 59 let resolver = def.resolver(db);
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index 8ca7e957d..bc9719725 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -56,7 +56,12 @@ where
56 self.var_stack.pop(); 56 self.var_stack.pop();
57 result 57 result
58 } else { 58 } else {
59 let free_var = InferTy::TypeVar(self.ctx.var_unification_table.find(inner)); 59 let root = self.ctx.var_unification_table.find(inner);
60 let free_var = match tv {
61 InferTy::TypeVar(_) => InferTy::TypeVar(root),
62 InferTy::IntVar(_) => InferTy::IntVar(root),
63 InferTy::FloatVar(_) => InferTy::FloatVar(root),
64 };
60 let position = self.add(free_var); 65 let position = self.add(free_var);
61 Ty::Bound(position as u32) 66 Ty::Bound(position as u32)
62 } 67 }
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 09d26ce5a..a1a2d0f6b 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -9,17 +9,18 @@ use std::sync::Arc;
9use std::iter; 9use std::iter;
10 10
11use crate::{ 11use crate::{
12 Function, Struct, StructField, Enum, EnumVariant, Path, 12 Function, Struct, StructField, Enum, EnumVariant, Path, ModuleDef, TypeAlias, Const, Static,
13 ModuleDef, TypeAlias,
14 Const, Static,
15 HirDatabase, 13 HirDatabase,
16 type_ref::TypeRef, 14 type_ref::TypeRef,
17 name::KnownName, 15 name::KnownName,
18 nameres::Namespace, 16 nameres::Namespace,
19 resolve::{Resolver, Resolution}, 17 resolve::{Resolver, Resolution},
20 path::{PathSegment, GenericArg}, 18 path::{PathSegment, GenericArg},
21 generics::{GenericParams, HasGenericParams}, 19 generics::{HasGenericParams},
22 adt::VariantDef, Trait, generics::{ WherePredicate, GenericDef} 20 adt::VariantDef,
21 Trait,
22 generics::{WherePredicate, GenericDef},
23 ty::AdtDef,
23}; 24};
24use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate}; 25use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef, GenericPredicate};
25 26
@@ -120,15 +121,15 @@ impl Ty {
120 segment: &PathSegment, 121 segment: &PathSegment,
121 resolved: TypableDef, 122 resolved: TypableDef,
122 ) -> Substs { 123 ) -> Substs {
123 let def_generics = match resolved { 124 let def_generic: Option<GenericDef> = match resolved {
124 TypableDef::Function(func) => func.generic_params(db), 125 TypableDef::Function(func) => Some(func.into()),
125 TypableDef::Struct(s) => s.generic_params(db), 126 TypableDef::Struct(s) => Some(s.into()),
126 TypableDef::Enum(e) => e.generic_params(db), 127 TypableDef::Enum(e) => Some(e.into()),
127 TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db), 128 TypableDef::EnumVariant(var) => Some(var.parent_enum(db).into()),
128 TypableDef::TypeAlias(t) => t.generic_params(db), 129 TypableDef::TypeAlias(t) => Some(t.into()),
129 TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), 130 TypableDef::Const(_) | TypableDef::Static(_) => None,
130 }; 131 };
131 substs_from_path_segment(db, resolver, segment, &def_generics, false) 132 substs_from_path_segment(db, resolver, segment, def_generic, false)
132 } 133 }
133 134
134 /// Collect generic arguments from a path into a `Substs`. See also 135 /// Collect generic arguments from a path into a `Substs`. See also
@@ -172,10 +173,12 @@ pub(super) fn substs_from_path_segment(
172 db: &impl HirDatabase, 173 db: &impl HirDatabase,
173 resolver: &Resolver, 174 resolver: &Resolver,
174 segment: &PathSegment, 175 segment: &PathSegment,
175 def_generics: &GenericParams, 176 def_generic: Option<GenericDef>,
176 add_self_param: bool, 177 add_self_param: bool,
177) -> Substs { 178) -> Substs {
178 let mut substs = Vec::new(); 179 let mut substs = Vec::new();
180 let def_generics = def_generic.map(|def| def.generic_params(db)).unwrap_or_default();
181
179 let parent_param_count = def_generics.count_parent_params(); 182 let parent_param_count = def_generics.count_parent_params();
180 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); 183 substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count));
181 if add_self_param { 184 if add_self_param {
@@ -199,12 +202,24 @@ pub(super) fn substs_from_path_segment(
199 } 202 }
200 } 203 }
201 // add placeholders for args that were not provided 204 // add placeholders for args that were not provided
202 // FIXME: handle defaults
203 let supplied_params = substs.len(); 205 let supplied_params = substs.len();
204 for _ in supplied_params..def_generics.count_params_including_parent() { 206 for _ in supplied_params..def_generics.count_params_including_parent() {
205 substs.push(Ty::Unknown); 207 substs.push(Ty::Unknown);
206 } 208 }
207 assert_eq!(substs.len(), def_generics.count_params_including_parent()); 209 assert_eq!(substs.len(), def_generics.count_params_including_parent());
210
211 // handle defaults
212 if let Some(def_generic) = def_generic {
213 let default_substs = db.generic_defaults(def_generic);
214 assert_eq!(substs.len(), default_substs.len());
215
216 for (i, default_ty) in default_substs.iter().enumerate() {
217 if substs[i] == Ty::Unknown {
218 substs[i] = default_ty.clone();
219 }
220 }
221 }
222
208 Substs(substs.into()) 223 Substs(substs.into())
209} 224}
210 225
@@ -249,7 +264,7 @@ impl TraitRef {
249 resolved: Trait, 264 resolved: Trait,
250 ) -> Substs { 265 ) -> Substs {
251 let segment = path.segments.last().expect("path should have at least one segment"); 266 let segment = path.segments.last().expect("path should have at least one segment");
252 substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true) 267 substs_from_path_segment(db, resolver, segment, Some(resolved.into()), true)
253 } 268 }
254 269
255 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef { 270 pub(crate) fn for_trait(db: &impl HirDatabase, trait_: Trait) -> TraitRef {
@@ -274,9 +289,9 @@ impl TraitRef {
274pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty { 289pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
275 match (def, ns) { 290 match (def, ns) {
276 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f), 291 (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
277 (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s), 292 (TypableDef::Struct(s), Namespace::Types) => type_for_adt(db, s),
278 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s), 293 (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s),
279 (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e), 294 (TypableDef::Enum(e), Namespace::Types) => type_for_adt(db, e),
280 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v), 295 (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
281 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t), 296 (TypableDef::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
282 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c), 297 (TypableDef::Const(c), Namespace::Values) => type_for_const(db, c),
@@ -331,6 +346,22 @@ pub(crate) fn generic_predicates(
331 predicates.into() 346 predicates.into()
332} 347}
333 348
349/// Resolve the default type params from generics
350pub(crate) fn generic_defaults(db: &impl HirDatabase, def: GenericDef) -> Substs {
351 let resolver = def.resolver(db);
352 let generic_params = def.generic_params(db);
353
354 let defaults = generic_params
355 .params_including_parent()
356 .into_iter()
357 .map(|p| {
358 p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path))
359 })
360 .collect::<Vec<_>>();
361
362 Substs(defaults.into())
363}
364
334fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { 365fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
335 let signature = def.signature(db); 366 let signature = def.signature(db);
336 let resolver = def.resolver(db); 367 let resolver = def.resolver(db);
@@ -375,7 +406,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
375 .iter() 406 .iter()
376 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 407 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
377 .collect::<Vec<_>>(); 408 .collect::<Vec<_>>();
378 let ret = type_for_struct(db, def); 409 let ret = type_for_adt(db, def);
379 FnSig::from_params_and_return(params, ret) 410 FnSig::from_params_and_return(params, ret)
380} 411}
381 412
@@ -383,7 +414,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
383fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { 414fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
384 let var_data = def.variant_data(db); 415 let var_data = def.variant_data(db);
385 if var_data.fields().is_none() { 416 if var_data.fields().is_none() {
386 return type_for_struct(db, def); // Unit struct 417 return type_for_adt(db, def); // Unit struct
387 } 418 }
388 let generics = def.generic_params(db); 419 let generics = def.generic_params(db);
389 let substs = Substs::identity(&generics); 420 let substs = Substs::identity(&generics);
@@ -403,7 +434,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant)
403 .collect::<Vec<_>>(); 434 .collect::<Vec<_>>();
404 let generics = def.parent_enum(db).generic_params(db); 435 let generics = def.parent_enum(db).generic_params(db);
405 let substs = Substs::identity(&generics); 436 let substs = Substs::identity(&generics);
406 let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs); 437 let ret = type_for_adt(db, def.parent_enum(db)).subst(&substs);
407 FnSig::from_params_and_return(params, ret) 438 FnSig::from_params_and_return(params, ret)
408} 439}
409 440
@@ -411,21 +442,16 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant)
411fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { 442fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
412 let var_data = def.variant_data(db); 443 let var_data = def.variant_data(db);
413 if var_data.fields().is_none() { 444 if var_data.fields().is_none() {
414 return type_for_enum(db, def.parent_enum(db)); // Unit variant 445 return type_for_adt(db, def.parent_enum(db)); // Unit variant
415 } 446 }
416 let generics = def.parent_enum(db).generic_params(db); 447 let generics = def.parent_enum(db).generic_params(db);
417 let substs = Substs::identity(&generics); 448 let substs = Substs::identity(&generics);
418 Ty::apply(TypeCtor::FnDef(def.into()), substs) 449 Ty::apply(TypeCtor::FnDef(def.into()), substs)
419} 450}
420 451
421fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { 452fn type_for_adt(db: &impl HirDatabase, adt: impl Into<AdtDef> + HasGenericParams) -> Ty {
422 let generics = s.generic_params(db); 453 let generics = adt.generic_params(db);
423 Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics)) 454 Ty::apply(TypeCtor::Adt(adt.into()), Substs::identity(&generics))
424}
425
426fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
427 let generics = s.generic_params(db);
428 Ty::apply(TypeCtor::Adt(s.into()), Substs::identity(&generics))
429} 455}
430 456
431fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { 457fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty {
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index f8364203d..cd24faba5 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -1449,6 +1449,35 @@ fn test() {
1449} 1449}
1450 1450
1451#[test] 1451#[test]
1452fn infer_associated_method_generics_with_default_param() {
1453 assert_snapshot_matches!(
1454 infer(r#"
1455struct Gen<T=u32> {
1456 val: T
1457}
1458
1459impl<T> Gen<T> {
1460 pub fn make() -> Gen<T> {
1461 loop { }
1462 }
1463}
1464
1465fn test() {
1466 let a = Gen::make();
1467}
1468"#),
1469 @r###"
1470[80; 104) '{ ... }': !
1471[90; 98) 'loop { }': !
1472[95; 98) '{ }': ()
1473[118; 146) '{ ...e(); }': ()
1474[128; 129) 'a': Gen<u32>
1475[132; 141) 'Gen::make': fn make<u32>() -> Gen<T>
1476[132; 143) 'Gen::make()': Gen<u32>"###
1477 );
1478}
1479
1480#[test]
1452fn infer_associated_method_generics_without_args() { 1481fn infer_associated_method_generics_without_args() {
1453 assert_snapshot_matches!( 1482 assert_snapshot_matches!(
1454 infer(r#" 1483 infer(r#"
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index 7de04c044..e6c78c0d4 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -4,6 +4,7 @@ use std::sync::{Arc, Mutex};
4use rustc_hash::FxHashSet; 4use rustc_hash::FxHashSet;
5use log::debug; 5use log::debug;
6use chalk_ir::cast::Cast; 6use chalk_ir::cast::Cast;
7use ra_prof::profile;
7 8
8use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; 9use crate::{Crate, Trait, db::HirDatabase, ImplBlock};
9use super::{TraitRef, Ty, Canonical}; 10use super::{TraitRef, Ty, Canonical};
@@ -25,7 +26,7 @@ struct ChalkContext<'a, DB> {
25 krate: Crate, 26 krate: Crate,
26} 27}
27 28
28pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> { 29pub(crate) fn solver_query(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>> {
29 // krate parameter is just so we cache a unique solver per crate 30 // krate parameter is just so we cache a unique solver per crate
30 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE }; 31 let solver_choice = chalk_solve::SolverChoice::SLG { max_size: CHALK_SOLVER_MAX_SIZE };
31 debug!("Creating new solver for crate {:?}", _krate); 32 debug!("Creating new solver for crate {:?}", _krate);
@@ -33,7 +34,7 @@ pub(crate) fn solver(_db: &impl HirDatabase, _krate: Crate) -> Arc<Mutex<Solver>
33} 34}
34 35
35/// Collects impls for the given trait in the whole dependency tree of `krate`. 36/// Collects impls for the given trait in the whole dependency tree of `krate`.
36pub(crate) fn impls_for_trait( 37pub(crate) fn impls_for_trait_query(
37 db: &impl HirDatabase, 38 db: &impl HirDatabase,
38 krate: Crate, 39 krate: Crate,
39 trait_: Trait, 40 trait_: Trait,
@@ -60,7 +61,7 @@ fn solve(
60 let context = ChalkContext { db, krate }; 61 let context = ChalkContext { db, krate };
61 let solver = db.solver(krate); 62 let solver = db.solver(krate);
62 debug!("solve goal: {:?}", goal); 63 debug!("solve goal: {:?}", goal);
63 let solution = solver.lock().unwrap().solve(&context, goal); 64 let solution = solver.lock().unwrap().solve_with_fuel(&context, goal, Some(1000));
64 debug!("solve({:?}) => {:?}", goal, solution); 65 debug!("solve({:?}) => {:?}", goal, solution);
65 solution 66 solution
66} 67}
@@ -76,11 +77,12 @@ pub enum Obligation {
76} 77}
77 78
78/// Check using Chalk whether trait is implemented for given parameters including `Self` type. 79/// Check using Chalk whether trait is implemented for given parameters including `Self` type.
79pub(crate) fn implements( 80pub(crate) fn implements_query(
80 db: &impl HirDatabase, 81 db: &impl HirDatabase,
81 krate: Crate, 82 krate: Crate,
82 trait_ref: Canonical<TraitRef>, 83 trait_ref: Canonical<TraitRef>,
83) -> Option<Solution> { 84) -> Option<Solution> {
85 let _p = profile("implements_query");
84 let goal: chalk_ir::Goal = trait_ref.value.to_chalk(db).cast(); 86 let goal: chalk_ir::Goal = trait_ref.value.to_chalk(db).cast();
85 debug!("goal: {:?}", goal); 87 debug!("goal: {:?}", goal);
86 let env = chalk_ir::Environment::new(); 88 let env = chalk_ir::Environment::new();
diff --git a/crates/ra_ide_api/Cargo.toml b/crates/ra_ide_api/Cargo.toml
index 333706c1a..d399d5e2e 100644
--- a/crates/ra_ide_api/Cargo.toml
+++ b/crates/ra_ide_api/Cargo.toml
@@ -29,7 +29,7 @@ test_utils = { path = "../test_utils" }
29ra_assists = { path = "../ra_assists" } 29ra_assists = { path = "../ra_assists" }
30 30
31[dev-dependencies] 31[dev-dependencies]
32insta = "0.7.0" 32insta = "0.8.1"
33 33
34[dev-dependencies.proptest] 34[dev-dependencies.proptest]
35version = "0.9.0" 35version = "0.9.0"
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index e23d178b0..9a0eb2c14 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -4,7 +4,7 @@ use itertools::Itertools;
4use hir::{source_binder, diagnostics::{Diagnostic as _, DiagnosticSink}}; 4use hir::{source_binder, diagnostics::{Diagnostic as _, DiagnosticSink}};
5use ra_db::SourceDatabase; 5use ra_db::SourceDatabase;
6use ra_syntax::{ 6use ra_syntax::{
7 Location, SourceFile, SyntaxKind, TextRange, SyntaxNode, 7 T, Location, SourceFile, TextRange, SyntaxNode,
8 ast::{self, AstNode, NamedFieldList, NamedField}, 8 ast::{self, AstNode, NamedFieldList, NamedField},
9}; 9};
10use ra_assists::ast_editor::{AstEditor, AstBuilder}; 10use ra_assists::ast_editor::{AstEditor, AstBuilder};
@@ -130,9 +130,7 @@ fn text_edit_for_remove_unnecessary_braces_with_self_in_use_statement(
130 single_use_tree: &ast::UseTree, 130 single_use_tree: &ast::UseTree,
131) -> Option<TextEdit> { 131) -> Option<TextEdit> {
132 let use_tree_list_node = single_use_tree.syntax().parent()?; 132 let use_tree_list_node = single_use_tree.syntax().parent()?;
133 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() 133 if single_use_tree.path()?.segment()?.syntax().first_child_or_token()?.kind() == T![self] {
134 == SyntaxKind::SELF_KW
135 {
136 let start = use_tree_list_node.prev_sibling_or_token()?.range().start(); 134 let start = use_tree_list_node.prev_sibling_or_token()?.range().start();
137 let end = use_tree_list_node.range().end(); 135 let end = use_tree_list_node.range().end();
138 let range = TextRange::from_to(start, end); 136 let range = TextRange::from_to(start, end);
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 163fa8c3c..4553faad0 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -157,7 +157,7 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
157 }) 157 })
158 .next() 158 .next()
159 .and_then(|it| it.as_token()) 159 .and_then(|it| it.as_token())
160 .filter(|node| node.kind() == COMMA) 160 .filter(|node| node.kind() == T![,])
161 } 161 }
162 162
163 if let Some(comma_node) = nearby_comma(node, Direction::Prev) { 163 if let Some(comma_node) = nearby_comma(node, Direction::Prev) {
diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs
index 598717311..4ca005466 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide_api/src/join_lines.rs
@@ -1,7 +1,8 @@
1use itertools::Itertools; 1use itertools::Itertools;
2use ra_syntax::{ 2use ra_syntax::{
3 T,
3 SourceFile, TextRange, TextUnit, SyntaxNode, SyntaxElement, SyntaxToken, 4 SourceFile, TextRange, TextUnit, SyntaxNode, SyntaxElement, SyntaxToken,
4 SyntaxKind::{self, WHITESPACE, COMMA, R_CURLY, R_PAREN, R_BRACK}, 5 SyntaxKind::{self, WHITESPACE},
5 algo::{find_covering_element, non_trivia_sibling}, 6 algo::{find_covering_element, non_trivia_sibling},
6 ast::{self, AstNode, AstToken}, 7 ast::{self, AstNode, AstToken},
7 Direction, 8 Direction,
@@ -89,7 +90,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: SyntaxToken, offset: TextUn
89 if is_trailing_comma(prev.kind(), next.kind()) { 90 if is_trailing_comma(prev.kind(), next.kind()) {
90 // Removes: trailing comma, newline (incl. surrounding whitespace) 91 // Removes: trailing comma, newline (incl. surrounding whitespace)
91 edit.delete(TextRange::from_to(prev.range().start(), token.range().end())); 92 edit.delete(TextRange::from_to(prev.range().start(), token.range().end()));
92 } else if prev.kind() == COMMA && next.kind() == R_CURLY { 93 } else if prev.kind() == T![,] && next.kind() == T!['}'] {
93 // Removes: comma, newline (incl. surrounding whitespace) 94 // Removes: comma, newline (incl. surrounding whitespace)
94 let space = if let Some(left) = prev.prev_sibling_or_token() { 95 let space = if let Some(left) = prev.prev_sibling_or_token() {
95 compute_ws(left.kind(), next.kind()) 96 compute_ws(left.kind(), next.kind())
@@ -116,7 +117,7 @@ fn remove_newline(edit: &mut TextEditBuilder, token: SyntaxToken, offset: TextUn
116 117
117fn has_comma_after(node: &SyntaxNode) -> bool { 118fn has_comma_after(node: &SyntaxNode) -> bool {
118 match non_trivia_sibling(node.into(), Direction::Next) { 119 match non_trivia_sibling(node.into(), Direction::Next) {
119 Some(n) => n.kind() == COMMA, 120 Some(n) => n.kind() == T![,],
120 _ => false, 121 _ => false,
121 } 122 }
122} 123}
@@ -150,7 +151,7 @@ fn join_single_use_tree(edit: &mut TextEditBuilder, token: SyntaxToken) -> Optio
150 151
151fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool { 152fn is_trailing_comma(left: SyntaxKind, right: SyntaxKind) -> bool {
152 match (left, right) { 153 match (left, right) {
153 (COMMA, R_PAREN) | (COMMA, R_BRACK) => true, 154 (T![,], T![')']) | (T![,], T![']']) => true,
154 _ => false, 155 _ => false,
155 } 156 }
156} 157}
diff --git a/crates/ra_ide_api/src/matching_brace.rs b/crates/ra_ide_api/src/matching_brace.rs
index bebd16a69..eaa4b620c 100644
--- a/crates/ra_ide_api/src/matching_brace.rs
+++ b/crates/ra_ide_api/src/matching_brace.rs
@@ -1,13 +1,14 @@
1use ra_syntax::{ 1use ra_syntax::{
2 SourceFile, TextUnit, 2 SourceFile, TextUnit,
3 algo::find_token_at_offset, 3 algo::find_token_at_offset,
4 SyntaxKind::{self, *}, 4 SyntaxKind::{self},
5 ast::AstNode, 5 ast::AstNode,
6 T
6}; 7};
7 8
8pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> { 9pub fn matching_brace(file: &SourceFile, offset: TextUnit) -> Option<TextUnit> {
9 const BRACES: &[SyntaxKind] = 10 const BRACES: &[SyntaxKind] =
10 &[L_CURLY, R_CURLY, L_BRACK, R_BRACK, L_PAREN, R_PAREN, L_ANGLE, R_ANGLE]; 11 &[T!['{'], T!['}'], T!['['], T![']'], T!['('], T![')'], T![<], T![>]];
11 let (brace_node, brace_idx) = find_token_at_offset(file.syntax(), offset) 12 let (brace_node, brace_idx) = find_token_at_offset(file.syntax(), offset)
12 .filter_map(|node| { 13 .filter_map(|node| {
13 let idx = BRACES.iter().position(|&brace| brace == node.kind())?; 14 let idx = BRACES.iter().position(|&brace| brace == node.kind())?;
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs
index d9a28d2b5..2158291dc 100644
--- a/crates/ra_ide_api/src/syntax_highlighting.rs
+++ b/crates/ra_ide_api/src/syntax_highlighting.rs
@@ -1,6 +1,6 @@
1use rustc_hash::FxHashSet; 1use rustc_hash::FxHashSet;
2 2
3use ra_syntax::{ast, AstNode, TextRange, Direction, SyntaxKind::*, SyntaxElement}; 3use ra_syntax::{ast, AstNode, TextRange, Direction, SyntaxKind, SyntaxKind::*, SyntaxElement, T};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5 5
6use crate::{FileId, db::RootDatabase}; 6use crate::{FileId, db::RootDatabase};
@@ -11,6 +11,21 @@ pub struct HighlightedRange {
11 pub tag: &'static str, 11 pub tag: &'static str,
12} 12}
13 13
14fn is_control_keyword(kind: SyntaxKind) -> bool {
15 match kind {
16 T![for]
17 | T![loop]
18 | T![while]
19 | T![continue]
20 | T![break]
21 | T![if]
22 | T![else]
23 | T![match]
24 | T![return] => true,
25 _ => false,
26 }
27}
28
14pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> { 29pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRange> {
15 let source_file = db.parse(file_id); 30 let source_file = db.parse(file_id);
16 31
@@ -29,6 +44,8 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
29 NAME => "function", 44 NAME => "function",
30 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", 45 INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal",
31 LIFETIME => "parameter", 46 LIFETIME => "parameter",
47 T![unsafe] => "keyword.unsafe",
48 k if is_control_keyword(k) => "keyword.control",
32 k if k.is_keyword() => "keyword", 49 k if k.is_keyword() => "keyword",
33 _ => { 50 _ => {
34 if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) { 51 if let Some(macro_call) = node.as_node().and_then(ast::MacroCall::cast) {
@@ -40,7 +57,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa
40 let mut range_end = name_ref.syntax().range().end(); 57 let mut range_end = name_ref.syntax().range().end();
41 for sibling in path.syntax().siblings_with_tokens(Direction::Next) { 58 for sibling in path.syntax().siblings_with_tokens(Direction::Next) {
42 match sibling.kind() { 59 match sibling.kind() {
43 EXCL | IDENT => range_end = sibling.range().end(), 60 T![!] | IDENT => range_end = sibling.range().end(),
44 _ => (), 61 _ => (),
45 } 62 }
46 } 63 }
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index 3a4dbb5f5..7fff8deff 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -281,7 +281,11 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
281 return Err(ExpandError::UnexpectedToken); 281 return Err(ExpandError::UnexpectedToken);
282 } 282 }
283 } 283 }
284 _ => return Err(ExpandError::UnexpectedToken), 284 crate::Leaf::Literal(literal) => {
285 if input.eat_literal().map(|i| &i.text) != Some(&literal.text) {
286 return Err(ExpandError::UnexpectedToken);
287 }
288 }
285 }, 289 },
286 crate::TokenTree::Repeat(crate::Repeat { subtree, kind, separator }) => { 290 crate::TokenTree::Repeat(crate::Repeat { subtree, kind, separator }) => {
287 // Dirty hack to make macro-expansion terminate. 291 // Dirty hack to make macro-expansion terminate.
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index 3554dc110..c938acf64 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -1,5 +1,5 @@
1use ra_parser::{TokenSource}; 1use ra_parser::{TokenSource};
2use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*}; 2use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*, T};
3use std::cell::{RefCell}; 3use std::cell::{RefCell};
4 4
5// A Sequece of Token, 5// A Sequece of Token,
@@ -284,9 +284,9 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> {
284 284
285fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken { 285fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
286 let (kinds, texts) = match d { 286 let (kinds, texts) = match d {
287 tt::Delimiter::Parenthesis => ([L_PAREN, R_PAREN], "()"), 287 tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"),
288 tt::Delimiter::Brace => ([L_CURLY, R_CURLY], "{}"), 288 tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"),
289 tt::Delimiter::Bracket => ([L_BRACK, R_BRACK], "[]"), 289 tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"),
290 tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""), 290 tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""),
291 }; 291 };
292 292
@@ -299,8 +299,8 @@ fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken {
299fn convert_literal(l: &tt::Literal) -> TtToken { 299fn convert_literal(l: &tt::Literal) -> TtToken {
300 let kind = 300 let kind =
301 classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() { 301 classify_literal(&l.text).map(|tkn| tkn.kind).unwrap_or_else(|| match l.text.as_ref() {
302 "true" => SyntaxKind::TRUE_KW, 302 "true" => T![true],
303 "false" => SyntaxKind::FALSE_KW, 303 "false" => T![false],
304 _ => panic!("Fail to convert given literal {:#?}", &l), 304 _ => panic!("Fail to convert given literal {:#?}", &l),
305 }); 305 });
306 306
@@ -320,11 +320,11 @@ fn convert_ident(ident: &tt::Ident) -> TtToken {
320fn convert_punct(p: &tt::Punct) -> TtToken { 320fn convert_punct(p: &tt::Punct) -> TtToken {
321 let kind = match p.char { 321 let kind = match p.char {
322 // lexer may produce compound tokens for these ones 322 // lexer may produce compound tokens for these ones
323 '.' => DOT, 323 '.' => T![.],
324 ':' => COLON, 324 ':' => T![:],
325 '=' => EQ, 325 '=' => T![=],
326 '!' => EXCL, 326 '!' => T![!],
327 '-' => MINUS, 327 '-' => T![-],
328 c => SyntaxKind::from_char(c).unwrap(), 328 c => SyntaxKind::from_char(c).unwrap(),
329 }; 329 };
330 let text = { 330 let text = {
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 5e6a6f2a1..d8e344557 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -1,7 +1,7 @@
1use ra_parser::{TreeSink, ParseError}; 1use ra_parser::{TreeSink, ParseError};
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc, SyntaxElement, 3 AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc, SyntaxElement,
4 ast, SyntaxKind::*, TextUnit 4 ast, SyntaxKind::*, TextUnit, T
5}; 5};
6 6
7use crate::subtree_source::{SubtreeTokenSource, Querier}; 7use crate::subtree_source::{SubtreeTokenSource, Querier};
@@ -211,9 +211,9 @@ fn convert_tt(
211 let first_child = tt.first_child_or_token()?; 211 let first_child = tt.first_child_or_token()?;
212 let last_child = tt.last_child_or_token()?; 212 let last_child = tt.last_child_or_token()?;
213 let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { 213 let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) {
214 (L_PAREN, R_PAREN) => (tt::Delimiter::Parenthesis, true), 214 (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true),
215 (L_CURLY, R_CURLY) => (tt::Delimiter::Brace, true), 215 (T!['{'], T!['}']) => (tt::Delimiter::Brace, true),
216 (L_BRACK, R_BRACK) => (tt::Delimiter::Bracket, true), 216 (T!['['], T![']']) => (tt::Delimiter::Bracket, true),
217 _ => (tt::Delimiter::None, false), 217 _ => (tt::Delimiter::None, false),
218 }; 218 };
219 219
@@ -248,23 +248,22 @@ fn convert_tt(
248 248
249 token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); 249 token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into());
250 } else { 250 } else {
251 let child: tt::TokenTree = if token.kind() == SyntaxKind::TRUE_KW 251 let child: tt::TokenTree =
252 || token.kind() == SyntaxKind::FALSE_KW 252 if token.kind() == T![true] || token.kind() == T![false] {
253 { 253 tt::Leaf::from(tt::Literal { text: token.text().clone() }).into()
254 tt::Leaf::from(tt::Literal { text: token.text().clone() }).into() 254 } else if token.kind().is_keyword()
255 } else if token.kind().is_keyword() 255 || token.kind() == IDENT
256 || token.kind() == IDENT 256 || token.kind() == LIFETIME
257 || token.kind() == LIFETIME 257 {
258 { 258 let relative_range = token.range() - global_offset;
259 let relative_range = token.range() - global_offset; 259 let id = token_map.alloc(relative_range);
260 let id = token_map.alloc(relative_range); 260 let text = token.text().clone();
261 let text = token.text().clone(); 261 tt::Leaf::from(tt::Ident { text, id }).into()
262 tt::Leaf::from(tt::Ident { text, id }).into() 262 } else if token.kind().is_literal() {
263 } else if token.kind().is_literal() { 263 tt::Leaf::from(tt::Literal { text: token.text().clone() }).into()
264 tt::Leaf::from(tt::Literal { text: token.text().clone() }).into() 264 } else {
265 } else { 265 return None;
266 return None; 266 };
267 };
268 token_trees.push(child); 267 token_trees.push(child);
269 } 268 }
270 } 269 }
@@ -305,10 +304,8 @@ impl<'a, Q: Querier> TtTreeSink<'a, Q> {
305} 304}
306 305
307fn is_delimiter(kind: SyntaxKind) -> bool { 306fn is_delimiter(kind: SyntaxKind) -> bool {
308 use SyntaxKind::*;
309
310 match kind { 307 match kind {
311 L_PAREN | L_BRACK | L_CURLY | R_PAREN | R_BRACK | R_CURLY => true, 308 T!['('] | T!['['] | T!['{'] | T![')'] | T![']'] | T!['}'] => true,
312 _ => false, 309 _ => false,
313 } 310 }
314} 311}
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 004faf77e..e3a5ceecf 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -575,6 +575,20 @@ fn test_tt_to_stmts() {
575 ); 575 );
576} 576}
577 577
578#[test]
579fn test_match_literal() {
580 let rules = create_rules(
581 r#"
582 macro_rules! foo {
583 ('(') => {
584 fn foo() {}
585 }
586 }
587"#,
588 );
589 assert_expansion(MacroKind::Items, &rules, "foo! ['(']", "fn foo () {}");
590}
591
578// The following tests are port from intellij-rust directly 592// The following tests are port from intellij-rust directly
579// https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt 593// https://github.com/intellij-rust/intellij-rust/blob/c4e9feee4ad46e7953b1948c112533360b6087bb/src/test/kotlin/org/rust/lang/core/macros/RsMacroExpansionTest.kt
580 594
diff --git a/crates/ra_parser/src/event.rs b/crates/ra_parser/src/event.rs
index 87cf4eca0..51beb0866 100644
--- a/crates/ra_parser/src/event.rs
+++ b/crates/ra_parser/src/event.rs
@@ -38,7 +38,7 @@ pub(crate) enum Event {
38 /// The events for it would look like this: 38 /// The events for it would look like this:
39 /// 39 ///
40 /// 40 ///
41 /// START(PATH) IDENT('foo') FINISH START(PATH) COLONCOLON IDENT('bar') FINISH 41 /// START(PATH) IDENT('foo') FINISH START(PATH) T![::] IDENT('bar') FINISH
42 /// | /\ 42 /// | /\
43 /// | | 43 /// | |
44 /// +------forward-parent------+ 44 /// +------forward-parent------+
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index a538ec081..cf603eba1 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -59,7 +59,7 @@ pub(crate) fn macro_stmts(p: &mut Parser) {
59 let m = p.start(); 59 let m = p.start();
60 60
61 while !p.at(EOF) { 61 while !p.at(EOF) {
62 if p.current() == SEMI { 62 if p.current() == T![;] {
63 p.bump(); 63 p.bump();
64 continue; 64 continue;
65 } 65 }
@@ -103,7 +103,7 @@ pub(crate) fn block(p: &mut Parser) {
103pub(crate) fn meta_item(p: &mut Parser) { 103pub(crate) fn meta_item(p: &mut Parser) {
104 fn is_delimiter(p: &mut Parser) -> bool { 104 fn is_delimiter(p: &mut Parser) -> bool {
105 match p.current() { 105 match p.current() {
106 L_CURLY | L_PAREN | L_BRACK => true, 106 T!['{'] | T!['('] | T!['['] => true,
107 _ => false, 107 _ => false,
108 } 108 }
109 } 109 }
@@ -123,12 +123,12 @@ pub(crate) fn meta_item(p: &mut Parser) {
123 // https://doc.rust-lang.org/reference/paths.html#simple-paths 123 // https://doc.rust-lang.org/reference/paths.html#simple-paths
124 // The start of an meta must be a simple path 124 // The start of an meta must be a simple path
125 match p.current() { 125 match p.current() {
126 IDENT | COLONCOLON | SUPER_KW | SELF_KW | CRATE_KW => p.bump(), 126 IDENT | T![::] | T![super] | T![self] | T![crate] => p.bump(),
127 EQ => { 127 T![=] => {
128 p.bump(); 128 p.bump();
129 match p.current() { 129 match p.current() {
130 c if c.is_literal() => p.bump(), 130 c if c.is_literal() => p.bump(),
131 TRUE_KW | FALSE_KW => p.bump(), 131 T![true] | T![false] => p.bump(),
132 _ => {} 132 _ => {}
133 } 133 }
134 break; 134 break;
@@ -158,7 +158,7 @@ pub(crate) fn reparser(
158 MATCH_ARM_LIST => items::match_arm_list, 158 MATCH_ARM_LIST => items::match_arm_list,
159 USE_TREE_LIST => items::use_tree_list, 159 USE_TREE_LIST => items::use_tree_list,
160 EXTERN_ITEM_LIST => items::extern_item_list, 160 EXTERN_ITEM_LIST => items::extern_item_list,
161 TOKEN_TREE if first_child? == L_CURLY => items::token_tree, 161 TOKEN_TREE if first_child? == T!['{'] => items::token_tree,
162 ITEM_LIST => match parent? { 162 ITEM_LIST => match parent? {
163 IMPL_BLOCK => items::impl_item_list, 163 IMPL_BLOCK => items::impl_item_list,
164 TRAIT_DEF => items::trait_item_list, 164 TRAIT_DEF => items::trait_item_list,
@@ -184,26 +184,26 @@ impl BlockLike {
184 184
185pub(crate) fn opt_visibility(p: &mut Parser) -> bool { 185pub(crate) fn opt_visibility(p: &mut Parser) -> bool {
186 match p.current() { 186 match p.current() {
187 PUB_KW => { 187 T![pub] => {
188 let m = p.start(); 188 let m = p.start();
189 p.bump(); 189 p.bump();
190 if p.at(L_PAREN) { 190 if p.at(T!['(']) {
191 match p.nth(1) { 191 match p.nth(1) {
192 // test crate_visibility 192 // test crate_visibility
193 // pub(crate) struct S; 193 // pub(crate) struct S;
194 // pub(self) struct S; 194 // pub(self) struct S;
195 // pub(self) struct S; 195 // pub(self) struct S;
196 // pub(self) struct S; 196 // pub(self) struct S;
197 CRATE_KW | SELF_KW | SUPER_KW => { 197 T![crate] | T![self] | T![super] => {
198 p.bump(); 198 p.bump();
199 p.bump(); 199 p.bump();
200 p.expect(R_PAREN); 200 p.expect(T![')']);
201 } 201 }
202 IN_KW => { 202 T![in] => {
203 p.bump(); 203 p.bump();
204 p.bump(); 204 p.bump();
205 paths::use_path(p); 205 paths::use_path(p);
206 p.expect(R_PAREN); 206 p.expect(T![')']);
207 } 207 }
208 _ => (), 208 _ => (),
209 } 209 }
@@ -217,7 +217,7 @@ pub(crate) fn opt_visibility(p: &mut Parser) -> bool {
217 // 217 //
218 // test crate_keyword_path 218 // test crate_keyword_path
219 // fn foo() { crate::foo(); } 219 // fn foo() { crate::foo(); }
220 CRATE_KW if p.nth(1) != COLONCOLON => { 220 T![crate] if p.nth(1) != T![::] => {
221 let m = p.start(); 221 let m = p.start();
222 p.bump(); 222 p.bump();
223 m.complete(p, VISIBILITY); 223 m.complete(p, VISIBILITY);
@@ -228,10 +228,10 @@ pub(crate) fn opt_visibility(p: &mut Parser) -> bool {
228} 228}
229 229
230fn opt_alias(p: &mut Parser) { 230fn opt_alias(p: &mut Parser) {
231 if p.at(AS_KW) { 231 if p.at(T![as]) {
232 let m = p.start(); 232 let m = p.start();
233 p.bump(); 233 p.bump();
234 if !p.eat(UNDERSCORE) { 234 if !p.eat(T![_]) {
235 name(p); 235 name(p);
236 } 236 }
237 m.complete(p, ALIAS); 237 m.complete(p, ALIAS);
@@ -239,7 +239,7 @@ fn opt_alias(p: &mut Parser) {
239} 239}
240 240
241fn abi(p: &mut Parser) { 241fn abi(p: &mut Parser) {
242 assert!(p.at(EXTERN_KW)); 242 assert!(p.at(T![extern]));
243 let abi = p.start(); 243 let abi = p.start();
244 p.bump(); 244 p.bump();
245 match p.current() { 245 match p.current() {
@@ -250,7 +250,7 @@ fn abi(p: &mut Parser) {
250} 250}
251 251
252fn opt_fn_ret_type(p: &mut Parser) -> bool { 252fn opt_fn_ret_type(p: &mut Parser) -> bool {
253 if p.at(THIN_ARROW) { 253 if p.at(T![->]) {
254 let m = p.start(); 254 let m = p.start();
255 p.bump(); 255 p.bump();
256 types::type_(p); 256 types::type_(p);
@@ -280,21 +280,21 @@ fn name_ref(p: &mut Parser) {
280 let m = p.start(); 280 let m = p.start();
281 p.bump(); 281 p.bump();
282 m.complete(p, NAME_REF); 282 m.complete(p, NAME_REF);
283 } else if p.at(SELF_KW) { 283 } else if p.at(T![self]) {
284 let m = p.start(); 284 let m = p.start();
285 p.bump(); 285 p.bump();
286 m.complete(p, SELF_KW); 286 m.complete(p, T![self]);
287 } else { 287 } else {
288 p.err_and_bump("expected identifier"); 288 p.err_and_bump("expected identifier");
289 } 289 }
290} 290}
291 291
292fn error_block(p: &mut Parser, message: &str) { 292fn error_block(p: &mut Parser, message: &str) {
293 assert!(p.at(L_CURLY)); 293 assert!(p.at(T!['{']));
294 let m = p.start(); 294 let m = p.start();
295 p.error(message); 295 p.error(message);
296 p.bump(); 296 p.bump();
297 expressions::expr_block_contents(p); 297 expressions::expr_block_contents(p);
298 p.eat(R_CURLY); 298 p.eat(T!['}']);
299 m.complete(p, ERROR); 299 m.complete(p, ERROR);
300} 300}
diff --git a/crates/ra_parser/src/grammar/attributes.rs b/crates/ra_parser/src/grammar/attributes.rs
index cd30e8a45..20d58445f 100644
--- a/crates/ra_parser/src/grammar/attributes.rs
+++ b/crates/ra_parser/src/grammar/attributes.rs
@@ -1,28 +1,28 @@
1use super::*; 1use super::*;
2 2
3pub(super) fn inner_attributes(p: &mut Parser) { 3pub(super) fn inner_attributes(p: &mut Parser) {
4 while p.current() == POUND && p.nth(1) == EXCL { 4 while p.current() == T![#] && p.nth(1) == T![!] {
5 attribute(p, true) 5 attribute(p, true)
6 } 6 }
7} 7}
8 8
9pub(super) fn outer_attributes(p: &mut Parser) { 9pub(super) fn outer_attributes(p: &mut Parser) {
10 while p.at(POUND) { 10 while p.at(T![#]) {
11 attribute(p, false) 11 attribute(p, false)
12 } 12 }
13} 13}
14 14
15fn attribute(p: &mut Parser, inner: bool) { 15fn attribute(p: &mut Parser, inner: bool) {
16 let attr = p.start(); 16 let attr = p.start();
17 assert!(p.at(POUND)); 17 assert!(p.at(T![#]));
18 p.bump(); 18 p.bump();
19 19
20 if inner { 20 if inner {
21 assert!(p.at(EXCL)); 21 assert!(p.at(T![!]));
22 p.bump(); 22 p.bump();
23 } 23 }
24 24
25 if p.at(L_BRACK) { 25 if p.at(T!['[']) {
26 items::token_tree(p); 26 items::token_tree(p);
27 } else { 27 } else {
28 p.error("expected `[`"); 28 p.error("expected `[`");
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 9fe529f53..bb6c78b5f 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -36,14 +36,14 @@ fn expr_no_struct(p: &mut Parser) {
36// fn c() { 1; 2; } 36// fn c() { 1; 2; }
37// fn d() { 1; 2 } 37// fn d() { 1; 2 }
38pub(crate) fn block(p: &mut Parser) { 38pub(crate) fn block(p: &mut Parser) {
39 if !p.at(L_CURLY) { 39 if !p.at(T!['{']) {
40 p.error("expected a block"); 40 p.error("expected a block");
41 return; 41 return;
42 } 42 }
43 let m = p.start(); 43 let m = p.start();
44 p.bump(); 44 p.bump();
45 expr_block_contents(p); 45 expr_block_contents(p);
46 p.expect(R_CURLY); 46 p.expect(T!['}']);
47 m.complete(p, BLOCK); 47 m.complete(p, BLOCK);
48} 48}
49 49
@@ -65,10 +65,10 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
65 // #[C] #[D] {} 65 // #[C] #[D] {}
66 // #[D] return (); 66 // #[D] return ();
67 // } 67 // }
68 let has_attrs = p.at(POUND); 68 let has_attrs = p.at(T![#]);
69 attributes::outer_attributes(p); 69 attributes::outer_attributes(p);
70 70
71 if p.at(LET_KW) { 71 if p.at(T![let]) {
72 let_stmt(p, m, with_semi); 72 let_stmt(p, m, with_semi);
73 return; 73 return;
74 } 74 }
@@ -90,7 +90,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
90 p.error(format!("attributes are not allowed on {:?}", kind)); 90 p.error(format!("attributes are not allowed on {:?}", kind));
91 } 91 }
92 92
93 if p.at(R_CURLY) { 93 if p.at(T!['}']) {
94 // test attr_on_last_expr_in_block 94 // test attr_on_last_expr_in_block
95 // fn foo() { 95 // fn foo() {
96 // { #[A] bar!()? } 96 // { #[A] bar!()? }
@@ -121,15 +121,15 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
121 match with_semi { 121 match with_semi {
122 StmtWithSemi::Yes => { 122 StmtWithSemi::Yes => {
123 if blocklike.is_block() { 123 if blocklike.is_block() {
124 p.eat(SEMI); 124 p.eat(T![;]);
125 } else { 125 } else {
126 p.expect(SEMI); 126 p.expect(T![;]);
127 } 127 }
128 } 128 }
129 StmtWithSemi::No => {} 129 StmtWithSemi::No => {}
130 StmtWithSemi::Optional => { 130 StmtWithSemi::Optional => {
131 if p.at(SEMI) { 131 if p.at(T![;]) {
132 p.eat(SEMI); 132 p.eat(T![;]);
133 } 133 }
134 } 134 }
135 } 135 }
@@ -145,24 +145,24 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
145 // let d: i32 = 92; 145 // let d: i32 = 92;
146 // } 146 // }
147 fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) { 147 fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) {
148 assert!(p.at(LET_KW)); 148 assert!(p.at(T![let]));
149 p.bump(); 149 p.bump();
150 patterns::pattern(p); 150 patterns::pattern(p);
151 if p.at(COLON) { 151 if p.at(T![:]) {
152 types::ascription(p); 152 types::ascription(p);
153 } 153 }
154 if p.eat(EQ) { 154 if p.eat(T![=]) {
155 expressions::expr(p); 155 expressions::expr(p);
156 } 156 }
157 157
158 match with_semi { 158 match with_semi {
159 StmtWithSemi::Yes => { 159 StmtWithSemi::Yes => {
160 p.expect(SEMI); 160 p.expect(T![;]);
161 } 161 }
162 StmtWithSemi::No => {} 162 StmtWithSemi::No => {}
163 StmtWithSemi::Optional => { 163 StmtWithSemi::Optional => {
164 if p.at(SEMI) { 164 if p.at(T![;]) {
165 p.eat(SEMI); 165 p.eat(T![;]);
166 } 166 }
167 } 167 }
168 } 168 }
@@ -174,12 +174,12 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
174 // This is checked by a validator 174 // This is checked by a validator
175 attributes::inner_attributes(p); 175 attributes::inner_attributes(p);
176 176
177 while !p.at(EOF) && !p.at(R_CURLY) { 177 while !p.at(EOF) && !p.at(T!['}']) {
178 // test nocontentexpr 178 // test nocontentexpr
179 // fn foo(){ 179 // fn foo(){
180 // ;;;some_expr();;;;{;;;};;;;Ok(()) 180 // ;;;some_expr();;;;{;;;};;;;Ok(())
181 // } 181 // }
182 if p.current() == SEMI { 182 if p.current() == T![;] {
183 p.bump(); 183 p.bump();
184 continue; 184 continue;
185 } 185 }
@@ -202,41 +202,41 @@ enum Op {
202fn current_op(p: &Parser) -> (u8, Op) { 202fn current_op(p: &Parser) -> (u8, Op) {
203 if let Some(t) = p.current3() { 203 if let Some(t) = p.current3() {
204 match t { 204 match t {
205 (L_ANGLE, L_ANGLE, EQ) => return (1, Op::Composite(SHLEQ, 3)), 205 (T![<], T![<], T![=]) => return (1, Op::Composite(T![<<=], 3)),
206 (R_ANGLE, R_ANGLE, EQ) => return (1, Op::Composite(SHREQ, 3)), 206 (T![>], T![>], T![=]) => return (1, Op::Composite(T![>>=], 3)),
207 _ => (), 207 _ => (),
208 } 208 }
209 } 209 }
210 210
211 if let Some(t) = p.current2() { 211 if let Some(t) = p.current2() {
212 match t { 212 match t {
213 (PLUS, EQ) => return (1, Op::Composite(PLUSEQ, 2)), 213 (T![+], T![=]) => return (1, Op::Composite(T![+=], 2)),
214 (MINUS, EQ) => return (1, Op::Composite(MINUSEQ, 2)), 214 (T![-], T![=]) => return (1, Op::Composite(T![-=], 2)),
215 (STAR, EQ) => return (1, Op::Composite(STAREQ, 2)), 215 (T![*], T![=]) => return (1, Op::Composite(T![*=], 2)),
216 (PERCENT, EQ) => return (1, Op::Composite(PERCENTEQ, 2)), 216 (T![%], T![=]) => return (1, Op::Composite(T![%=], 2)),
217 (SLASH, EQ) => return (1, Op::Composite(SLASHEQ, 2)), 217 (T![/], T![=]) => return (1, Op::Composite(T![/=], 2)),
218 (PIPE, EQ) => return (1, Op::Composite(PIPEEQ, 2)), 218 (T![|], T![=]) => return (1, Op::Composite(T![|=], 2)),
219 (AMP, EQ) => return (1, Op::Composite(AMPEQ, 2)), 219 (T![&], T![=]) => return (1, Op::Composite(T![&=], 2)),
220 (CARET, EQ) => return (1, Op::Composite(CARETEQ, 2)), 220 (T![^], T![=]) => return (1, Op::Composite(T![^=], 2)),
221 (PIPE, PIPE) => return (3, Op::Composite(PIPEPIPE, 2)), 221 (T![|], T![|]) => return (3, Op::Composite(T![||], 2)),
222 (AMP, AMP) => return (4, Op::Composite(AMPAMP, 2)), 222 (T![&], T![&]) => return (4, Op::Composite(T![&&], 2)),
223 (L_ANGLE, EQ) => return (5, Op::Composite(LTEQ, 2)), 223 (T![<], T![=]) => return (5, Op::Composite(T![<=], 2)),
224 (R_ANGLE, EQ) => return (5, Op::Composite(GTEQ, 2)), 224 (T![>], T![=]) => return (5, Op::Composite(T![>=], 2)),
225 (L_ANGLE, L_ANGLE) => return (9, Op::Composite(SHL, 2)), 225 (T![<], T![<]) => return (9, Op::Composite(T![<<], 2)),
226 (R_ANGLE, R_ANGLE) => return (9, Op::Composite(SHR, 2)), 226 (T![>], T![>]) => return (9, Op::Composite(T![>>], 2)),
227 _ => (), 227 _ => (),
228 } 228 }
229 } 229 }
230 230
231 let bp = match p.current() { 231 let bp = match p.current() {
232 EQ => 1, 232 T![=] => 1,
233 DOTDOT | DOTDOTEQ => 2, 233 T![..] | T![..=] => 2,
234 EQEQ | NEQ | L_ANGLE | R_ANGLE => 5, 234 T![==] | T![!=] | T![<] | T![>] => 5,
235 PIPE => 6, 235 T![|] => 6,
236 CARET => 7, 236 T![^] => 7,
237 AMP => 8, 237 T![&] => 8,
238 MINUS | PLUS => 10, 238 T![-] | T![+] => 10,
239 STAR | SLASH | PERCENT => 11, 239 T![*] | T![/] | T![%] => 11,
240 _ => 0, 240 _ => 0,
241 }; 241 };
242 (bp, Op::Simple) 242 (bp, Op::Simple)
@@ -284,7 +284,7 @@ fn expr_bp(
284 newly_dollar_open = false; 284 newly_dollar_open = false;
285 } 285 }
286 286
287 let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ; 287 let is_range = p.current() == T![..] || p.current() == T![..=];
288 let (op_bp, op) = current_op(p); 288 let (op_bp, op) = current_op(p);
289 if op_bp < bp { 289 if op_bp < bp {
290 break; 290 break;
@@ -318,10 +318,10 @@ fn lhs(
318 // let _ = &1; 318 // let _ = &1;
319 // let _ = &mut &f(); 319 // let _ = &mut &f();
320 // } 320 // }
321 AMP => { 321 T![&] => {
322 m = p.start(); 322 m = p.start();
323 p.bump(); 323 p.bump();
324 p.eat(MUT_KW); 324 p.eat(T![mut]);
325 REF_EXPR 325 REF_EXPR
326 } 326 }
327 // test unary_expr 327 // test unary_expr
@@ -330,14 +330,14 @@ fn lhs(
330 // !!true; 330 // !!true;
331 // --1; 331 // --1;
332 // } 332 // }
333 STAR | EXCL | MINUS => { 333 T![*] | T![!] | T![-] => {
334 m = p.start(); 334 m = p.start();
335 p.bump(); 335 p.bump();
336 PREFIX_EXPR 336 PREFIX_EXPR
337 } 337 }
338 // test full_range_expr 338 // test full_range_expr
339 // fn foo() { xs[..]; } 339 // fn foo() { xs[..]; }
340 DOTDOT | DOTDOTEQ => { 340 T![..] | T![..=] => {
341 m = p.start(); 341 m = p.start();
342 p.bump(); 342 p.bump();
343 if p.at_ts(EXPR_FIRST) { 343 if p.at_ts(EXPR_FIRST) {
@@ -375,21 +375,21 @@ fn postfix_expr(
375 // [] => {} 375 // [] => {}
376 // } 376 // }
377 // } 377 // }
378 L_PAREN if allow_calls => call_expr(p, lhs), 378 T!['('] if allow_calls => call_expr(p, lhs),
379 L_BRACK if allow_calls => index_expr(p, lhs), 379 T!['['] if allow_calls => index_expr(p, lhs),
380 DOT if p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON) => { 380 T![.] if p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]) => {
381 method_call_expr(p, lhs) 381 method_call_expr(p, lhs)
382 } 382 }
383 DOT => field_expr(p, lhs), 383 T![.] => field_expr(p, lhs),
384 // test postfix_range 384 // test postfix_range
385 // fn foo() { let x = 1..; } 385 // fn foo() { let x = 1..; }
386 DOTDOT | DOTDOTEQ if !EXPR_FIRST.contains(p.nth(1)) => { 386 T![..] | T![..=] if !EXPR_FIRST.contains(p.nth(1)) => {
387 let m = lhs.precede(p); 387 let m = lhs.precede(p);
388 p.bump(); 388 p.bump();
389 m.complete(p, RANGE_EXPR) 389 m.complete(p, RANGE_EXPR)
390 } 390 }
391 QUESTION => try_expr(p, lhs), 391 T![?] => try_expr(p, lhs),
392 AS_KW => cast_expr(p, lhs), 392 T![as] => cast_expr(p, lhs),
393 _ => break, 393 _ => break,
394 }; 394 };
395 allow_calls = true 395 allow_calls = true
@@ -405,7 +405,7 @@ fn postfix_expr(
405// f(<Foo as Trait>::func()); 405// f(<Foo as Trait>::func());
406// } 406// }
407fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 407fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
408 assert!(p.at(L_PAREN)); 408 assert!(p.at(T!['(']));
409 let m = lhs.precede(p); 409 let m = lhs.precede(p);
410 arg_list(p); 410 arg_list(p);
411 m.complete(p, CALL_EXPR) 411 m.complete(p, CALL_EXPR)
@@ -416,11 +416,11 @@ fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
416// x[1][2]; 416// x[1][2];
417// } 417// }
418fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 418fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
419 assert!(p.at(L_BRACK)); 419 assert!(p.at(T!['[']));
420 let m = lhs.precede(p); 420 let m = lhs.precede(p);
421 p.bump(); 421 p.bump();
422 expr(p); 422 expr(p);
423 p.expect(R_BRACK); 423 p.expect(T![']']);
424 m.complete(p, INDEX_EXPR) 424 m.complete(p, INDEX_EXPR)
425} 425}
426 426
@@ -430,12 +430,12 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
430// y.bar::<T>(1, 2,); 430// y.bar::<T>(1, 2,);
431// } 431// }
432fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 432fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
433 assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON)); 433 assert!(p.at(T![.]) && p.nth(1) == IDENT && (p.nth(2) == T!['('] || p.nth(2) == T![::]));
434 let m = lhs.precede(p); 434 let m = lhs.precede(p);
435 p.bump(); 435 p.bump();
436 name_ref(p); 436 name_ref(p);
437 type_args::opt_type_arg_list(p, true); 437 type_args::opt_type_arg_list(p, true);
438 if p.at(L_PAREN) { 438 if p.at(T!['(']) {
439 arg_list(p); 439 arg_list(p);
440 } 440 }
441 m.complete(p, METHOD_CALL_EXPR) 441 m.complete(p, METHOD_CALL_EXPR)
@@ -455,7 +455,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
455// x.0x01; 455// x.0x01;
456// } 456// }
457fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 457fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
458 assert!(p.at(DOT)); 458 assert!(p.at(T![.]));
459 let m = lhs.precede(p); 459 let m = lhs.precede(p);
460 p.bump(); 460 p.bump();
461 if p.at(IDENT) { 461 if p.at(IDENT) {
@@ -463,7 +463,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
463 } else if p.at(INT_NUMBER) { 463 } else if p.at(INT_NUMBER) {
464 p.bump(); 464 p.bump();
465 } else if p.at(FLOAT_NUMBER) { 465 } else if p.at(FLOAT_NUMBER) {
466 // FIXME: How to recover and instead parse INT + DOT? 466 // FIXME: How to recover and instead parse INT + T![.]?
467 p.bump(); 467 p.bump();
468 } else { 468 } else {
469 p.error("expected field name or number") 469 p.error("expected field name or number")
@@ -476,7 +476,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
476// x?; 476// x?;
477// } 477// }
478fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 478fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
479 assert!(p.at(QUESTION)); 479 assert!(p.at(T![?]));
480 let m = lhs.precede(p); 480 let m = lhs.precede(p);
481 p.bump(); 481 p.bump();
482 m.complete(p, TRY_EXPR) 482 m.complete(p, TRY_EXPR)
@@ -490,7 +490,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
490// 0x36 as u8 <= 0x37; 490// 0x36 as u8 <= 0x37;
491// } 491// }
492fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 492fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
493 assert!(p.at(AS_KW)); 493 assert!(p.at(T![as]));
494 let m = lhs.precede(p); 494 let m = lhs.precede(p);
495 p.bump(); 495 p.bump();
496 // Use type_no_bounds(), because cast expressions are not 496 // Use type_no_bounds(), because cast expressions are not
@@ -500,20 +500,20 @@ fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
500} 500}
501 501
502fn arg_list(p: &mut Parser) { 502fn arg_list(p: &mut Parser) {
503 assert!(p.at(L_PAREN)); 503 assert!(p.at(T!['(']));
504 let m = p.start(); 504 let m = p.start();
505 p.bump(); 505 p.bump();
506 while !p.at(R_PAREN) && !p.at(EOF) { 506 while !p.at(T![')']) && !p.at(EOF) {
507 if !p.at_ts(EXPR_FIRST) { 507 if !p.at_ts(EXPR_FIRST) {
508 p.error("expected expression"); 508 p.error("expected expression");
509 break; 509 break;
510 } 510 }
511 expr(p); 511 expr(p);
512 if !p.at(R_PAREN) && !p.expect(COMMA) { 512 if !p.at(T![')']) && !p.expect(T![,]) {
513 break; 513 break;
514 } 514 }
515 } 515 }
516 p.eat(R_PAREN); 516 p.eat(T![')']);
517 m.complete(p, ARG_LIST); 517 m.complete(p, ARG_LIST);
518} 518}
519 519
@@ -525,15 +525,15 @@ fn arg_list(p: &mut Parser) {
525// let _ = format!(); 525// let _ = format!();
526// } 526// }
527fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) { 527fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
528 assert!(paths::is_path_start(p) || p.at(L_ANGLE)); 528 assert!(paths::is_path_start(p) || p.at(T![<]));
529 let m = p.start(); 529 let m = p.start();
530 paths::expr_path(p); 530 paths::expr_path(p);
531 match p.current() { 531 match p.current() {
532 L_CURLY if !r.forbid_structs => { 532 T!['{'] if !r.forbid_structs => {
533 named_field_list(p); 533 named_field_list(p);
534 (m.complete(p, STRUCT_LIT), BlockLike::NotBlock) 534 (m.complete(p, STRUCT_LIT), BlockLike::NotBlock)
535 } 535 }
536 EXCL => { 536 T![!] => {
537 let block_like = items::macro_call_after_excl(p); 537 let block_like = items::macro_call_after_excl(p);
538 (m.complete(p, MACRO_CALL), block_like) 538 (m.complete(p, MACRO_CALL), block_like)
539 } 539 }
@@ -548,35 +548,35 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
548// S { x, y: 32, ..Default::default() }; 548// S { x, y: 32, ..Default::default() };
549// } 549// }
550pub(crate) fn named_field_list(p: &mut Parser) { 550pub(crate) fn named_field_list(p: &mut Parser) {
551 assert!(p.at(L_CURLY)); 551 assert!(p.at(T!['{']));
552 let m = p.start(); 552 let m = p.start();
553 p.bump(); 553 p.bump();
554 while !p.at(EOF) && !p.at(R_CURLY) { 554 while !p.at(EOF) && !p.at(T!['}']) {
555 match p.current() { 555 match p.current() {
556 // test struct_literal_field_with_attr 556 // test struct_literal_field_with_attr
557 // fn main() { 557 // fn main() {
558 // S { #[cfg(test)] field: 1 } 558 // S { #[cfg(test)] field: 1 }
559 // } 559 // }
560 IDENT | POUND => { 560 IDENT | T![#] => {
561 let m = p.start(); 561 let m = p.start();
562 attributes::outer_attributes(p); 562 attributes::outer_attributes(p);
563 name_ref(p); 563 name_ref(p);
564 if p.eat(COLON) { 564 if p.eat(T![:]) {
565 expr(p); 565 expr(p);
566 } 566 }
567 m.complete(p, NAMED_FIELD); 567 m.complete(p, NAMED_FIELD);
568 } 568 }
569 DOTDOT => { 569 T![..] => {
570 p.bump(); 570 p.bump();
571 expr(p); 571 expr(p);
572 } 572 }
573 L_CURLY => error_block(p, "expected a field"), 573 T!['{'] => error_block(p, "expected a field"),
574 _ => p.err_and_bump("expected identifier"), 574 _ => p.err_and_bump("expected identifier"),
575 } 575 }
576 if !p.at(R_CURLY) { 576 if !p.at(T!['}']) {
577 p.expect(COMMA); 577 p.expect(T![,]);
578 } 578 }
579 } 579 }
580 p.expect(R_CURLY); 580 p.expect(T!['}']);
581 m.complete(p, NAMED_FIELD_LIST); 581 m.complete(p, NAMED_FIELD_LIST);
582} 582}
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 8dc7e44a9..8b1a1de49 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -60,29 +60,29 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
60 if let Some(m) = literal(p) { 60 if let Some(m) = literal(p) {
61 return Some((m, BlockLike::NotBlock)); 61 return Some((m, BlockLike::NotBlock));
62 } 62 }
63 if paths::is_path_start(p) || p.at(L_ANGLE) { 63 if paths::is_path_start(p) || p.at(T![<]) {
64 return Some(path_expr(p, r)); 64 return Some(path_expr(p, r));
65 } 65 }
66 let la = p.nth(1); 66 let la = p.nth(1);
67 let done = match p.current() { 67 let done = match p.current() {
68 L_PAREN => tuple_expr(p), 68 T!['('] => tuple_expr(p),
69 L_BRACK => array_expr(p), 69 T!['['] => array_expr(p),
70 PIPE => lambda_expr(p), 70 T![|] => lambda_expr(p),
71 MOVE_KW if la == PIPE => lambda_expr(p), 71 T![move] if la == T![|] => lambda_expr(p),
72 ASYNC_KW if la == PIPE || (la == MOVE_KW && p.nth(2) == PIPE) => lambda_expr(p), 72 T![async] if la == T![|] || (la == T![move] && p.nth(2) == T![|]) => lambda_expr(p),
73 IF_KW => if_expr(p), 73 T![if] => if_expr(p),
74 74
75 LOOP_KW => loop_expr(p, None), 75 T![loop] => loop_expr(p, None),
76 FOR_KW => for_expr(p, None), 76 T![for] => for_expr(p, None),
77 WHILE_KW => while_expr(p, None), 77 T![while] => while_expr(p, None),
78 LIFETIME if la == COLON => { 78 LIFETIME if la == T![:] => {
79 let m = p.start(); 79 let m = p.start();
80 label(p); 80 label(p);
81 match p.current() { 81 match p.current() {
82 LOOP_KW => loop_expr(p, Some(m)), 82 T![loop] => loop_expr(p, Some(m)),
83 FOR_KW => for_expr(p, Some(m)), 83 T![for] => for_expr(p, Some(m)),
84 WHILE_KW => while_expr(p, Some(m)), 84 T![while] => while_expr(p, Some(m)),
85 L_CURLY => block_expr(p, Some(m)), 85 T!['{'] => block_expr(p, Some(m)),
86 _ => { 86 _ => {
87 // test_err misplaced_label_err 87 // test_err misplaced_label_err
88 // fn main() { 88 // fn main() {
@@ -94,22 +94,22 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
94 } 94 }
95 } 95 }
96 } 96 }
97 ASYNC_KW if la == L_CURLY || (la == MOVE_KW && p.nth(2) == L_CURLY) => { 97 T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => {
98 let m = p.start(); 98 let m = p.start();
99 p.bump(); 99 p.bump();
100 p.eat(MOVE_KW); 100 p.eat(T![move]);
101 block_expr(p, Some(m)) 101 block_expr(p, Some(m))
102 } 102 }
103 MATCH_KW => match_expr(p), 103 T![match] => match_expr(p),
104 UNSAFE_KW if la == L_CURLY => { 104 T![unsafe] if la == T!['{'] => {
105 let m = p.start(); 105 let m = p.start();
106 p.bump(); 106 p.bump();
107 block_expr(p, Some(m)) 107 block_expr(p, Some(m))
108 } 108 }
109 L_CURLY => block_expr(p, None), 109 T!['{'] => block_expr(p, None),
110 RETURN_KW => return_expr(p), 110 T![return] => return_expr(p),
111 CONTINUE_KW => continue_expr(p), 111 T![continue] => continue_expr(p),
112 BREAK_KW => break_expr(p, r), 112 T![break] => break_expr(p, r),
113 _ => { 113 _ => {
114 p.err_recover("expected expression", EXPR_RECOVERY_SET); 114 p.err_recover("expected expression", EXPR_RECOVERY_SET);
115 return None; 115 return None;
@@ -129,25 +129,25 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
129// (1,); 129// (1,);
130// } 130// }
131fn tuple_expr(p: &mut Parser) -> CompletedMarker { 131fn tuple_expr(p: &mut Parser) -> CompletedMarker {
132 assert!(p.at(L_PAREN)); 132 assert!(p.at(T!['(']));
133 let m = p.start(); 133 let m = p.start();
134 p.expect(L_PAREN); 134 p.expect(T!['(']);
135 135
136 let mut saw_comma = false; 136 let mut saw_comma = false;
137 let mut saw_expr = false; 137 let mut saw_expr = false;
138 while !p.at(EOF) && !p.at(R_PAREN) { 138 while !p.at(EOF) && !p.at(T![')']) {
139 saw_expr = true; 139 saw_expr = true;
140 if !p.at_ts(EXPR_FIRST) { 140 if !p.at_ts(EXPR_FIRST) {
141 p.error("expected expression"); 141 p.error("expected expression");
142 break; 142 break;
143 } 143 }
144 expr(p); 144 expr(p);
145 if !p.at(R_PAREN) { 145 if !p.at(T![')']) {
146 saw_comma = true; 146 saw_comma = true;
147 p.expect(COMMA); 147 p.expect(T![,]);
148 } 148 }
149 } 149 }
150 p.expect(R_PAREN); 150 p.expect(T![')']);
151 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR }) 151 m.complete(p, if saw_expr && !saw_comma { PAREN_EXPR } else { TUPLE_EXPR })
152} 152}
153 153
@@ -159,21 +159,21 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
159// [1; 2]; 159// [1; 2];
160// } 160// }
161fn array_expr(p: &mut Parser) -> CompletedMarker { 161fn array_expr(p: &mut Parser) -> CompletedMarker {
162 assert!(p.at(L_BRACK)); 162 assert!(p.at(T!['[']));
163 let m = p.start(); 163 let m = p.start();
164 p.bump(); 164 p.bump();
165 if p.eat(R_BRACK) { 165 if p.eat(T![']']) {
166 return m.complete(p, ARRAY_EXPR); 166 return m.complete(p, ARRAY_EXPR);
167 } 167 }
168 expr(p); 168 expr(p);
169 if p.eat(SEMI) { 169 if p.eat(T![;]) {
170 expr(p); 170 expr(p);
171 p.expect(R_BRACK); 171 p.expect(T![']']);
172 return m.complete(p, ARRAY_EXPR); 172 return m.complete(p, ARRAY_EXPR);
173 } 173 }
174 while !p.at(EOF) && !p.at(R_BRACK) { 174 while !p.at(EOF) && !p.at(T![']']) {
175 p.expect(COMMA); 175 p.expect(T![,]);
176 if p.at(R_BRACK) { 176 if p.at(T![']']) {
177 break; 177 break;
178 } 178 }
179 if !p.at_ts(EXPR_FIRST) { 179 if !p.at_ts(EXPR_FIRST) {
@@ -182,7 +182,7 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
182 } 182 }
183 expr(p); 183 expr(p);
184 } 184 }
185 p.expect(R_BRACK); 185 p.expect(T![']']);
186 m.complete(p, ARRAY_EXPR) 186 m.complete(p, ARRAY_EXPR)
187} 187}
188 188
@@ -198,17 +198,17 @@ fn array_expr(p: &mut Parser) -> CompletedMarker {
198// } 198// }
199fn lambda_expr(p: &mut Parser) -> CompletedMarker { 199fn lambda_expr(p: &mut Parser) -> CompletedMarker {
200 assert!( 200 assert!(
201 p.at(PIPE) 201 p.at(T![|])
202 || (p.at(MOVE_KW) && p.nth(1) == PIPE) 202 || (p.at(T![move]) && p.nth(1) == T![|])
203 || (p.at(ASYNC_KW) && p.nth(1) == PIPE) 203 || (p.at(T![async]) && p.nth(1) == T![|])
204 || (p.at(ASYNC_KW) && p.nth(1) == MOVE_KW && p.nth(2) == PIPE) 204 || (p.at(T![async]) && p.nth(1) == T![move] && p.nth(2) == T![|])
205 ); 205 );
206 let m = p.start(); 206 let m = p.start();
207 p.eat(ASYNC_KW); 207 p.eat(T![async]);
208 p.eat(MOVE_KW); 208 p.eat(T![move]);
209 params::param_list_opt_types(p); 209 params::param_list_opt_types(p);
210 if opt_fn_ret_type(p) { 210 if opt_fn_ret_type(p) {
211 if !p.at(L_CURLY) { 211 if !p.at(T!['{']) {
212 p.error("expected `{`"); 212 p.error("expected `{`");
213 } 213 }
214 } 214 }
@@ -224,14 +224,14 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
224// if S {}; 224// if S {};
225// } 225// }
226fn if_expr(p: &mut Parser) -> CompletedMarker { 226fn if_expr(p: &mut Parser) -> CompletedMarker {
227 assert!(p.at(IF_KW)); 227 assert!(p.at(T![if]));
228 let m = p.start(); 228 let m = p.start();
229 p.bump(); 229 p.bump();
230 cond(p); 230 cond(p);
231 block(p); 231 block(p);
232 if p.at(ELSE_KW) { 232 if p.at(T![else]) {
233 p.bump(); 233 p.bump();
234 if p.at(IF_KW) { 234 if p.at(T![if]) {
235 if_expr(p); 235 if_expr(p);
236 } else { 236 } else {
237 block(p); 237 block(p);
@@ -247,7 +247,7 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
247// 'c: for x in () {} 247// 'c: for x in () {}
248// } 248// }
249fn label(p: &mut Parser) { 249fn label(p: &mut Parser) {
250 assert!(p.at(LIFETIME) && p.nth(1) == COLON); 250 assert!(p.at(LIFETIME) && p.nth(1) == T![:]);
251 let m = p.start(); 251 let m = p.start();
252 p.bump(); 252 p.bump();
253 p.bump(); 253 p.bump();
@@ -259,7 +259,7 @@ fn label(p: &mut Parser) {
259// loop {}; 259// loop {};
260// } 260// }
261fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 261fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
262 assert!(p.at(LOOP_KW)); 262 assert!(p.at(T![loop]));
263 let m = m.unwrap_or_else(|| p.start()); 263 let m = m.unwrap_or_else(|| p.start());
264 p.bump(); 264 p.bump();
265 block(p); 265 block(p);
@@ -272,7 +272,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
272// while let Some(x) = it.next() {}; 272// while let Some(x) = it.next() {};
273// } 273// }
274fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 274fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
275 assert!(p.at(WHILE_KW)); 275 assert!(p.at(T![while]));
276 let m = m.unwrap_or_else(|| p.start()); 276 let m = m.unwrap_or_else(|| p.start());
277 p.bump(); 277 p.bump();
278 cond(p); 278 cond(p);
@@ -285,11 +285,11 @@ fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
285// for x in [] {}; 285// for x in [] {};
286// } 286// }
287fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 287fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
288 assert!(p.at(FOR_KW)); 288 assert!(p.at(T![for]));
289 let m = m.unwrap_or_else(|| p.start()); 289 let m = m.unwrap_or_else(|| p.start());
290 p.bump(); 290 p.bump();
291 patterns::pattern(p); 291 patterns::pattern(p);
292 p.expect(IN_KW); 292 p.expect(T![in]);
293 expr_no_struct(p); 293 expr_no_struct(p);
294 block(p); 294 block(p);
295 m.complete(p, FOR_EXPR) 295 m.complete(p, FOR_EXPR)
@@ -305,9 +305,9 @@ fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
305// } 305// }
306fn cond(p: &mut Parser) { 306fn cond(p: &mut Parser) {
307 let m = p.start(); 307 let m = p.start();
308 if p.eat(LET_KW) { 308 if p.eat(T![let]) {
309 patterns::pattern_list(p); 309 patterns::pattern_list(p);
310 p.expect(EQ); 310 p.expect(T![=]);
311 } 311 }
312 expr_no_struct(p); 312 expr_no_struct(p);
313 m.complete(p, CONDITION); 313 m.complete(p, CONDITION);
@@ -319,11 +319,11 @@ fn cond(p: &mut Parser) {
319// match S {}; 319// match S {};
320// } 320// }
321fn match_expr(p: &mut Parser) -> CompletedMarker { 321fn match_expr(p: &mut Parser) -> CompletedMarker {
322 assert!(p.at(MATCH_KW)); 322 assert!(p.at(T![match]));
323 let m = p.start(); 323 let m = p.start();
324 p.bump(); 324 p.bump();
325 expr_no_struct(p); 325 expr_no_struct(p);
326 if p.at(L_CURLY) { 326 if p.at(T!['{']) {
327 match_arm_list(p); 327 match_arm_list(p);
328 } else { 328 } else {
329 p.error("expected `{`") 329 p.error("expected `{`")
@@ -332,9 +332,9 @@ fn match_expr(p: &mut Parser) -> CompletedMarker {
332} 332}
333 333
334pub(crate) fn match_arm_list(p: &mut Parser) { 334pub(crate) fn match_arm_list(p: &mut Parser) {
335 assert!(p.at(L_CURLY)); 335 assert!(p.at(T!['{']));
336 let m = p.start(); 336 let m = p.start();
337 p.eat(L_CURLY); 337 p.eat(T!['{']);
338 338
339 // test match_arms_inner_attribute 339 // test match_arms_inner_attribute
340 // fn foo() { 340 // fn foo() {
@@ -347,8 +347,8 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
347 // } 347 // }
348 attributes::inner_attributes(p); 348 attributes::inner_attributes(p);
349 349
350 while !p.at(EOF) && !p.at(R_CURLY) { 350 while !p.at(EOF) && !p.at(T!['}']) {
351 if p.at(L_CURLY) { 351 if p.at(T!['{']) {
352 error_block(p, "expected match arm"); 352 error_block(p, "expected match arm");
353 continue; 353 continue;
354 } 354 }
@@ -362,12 +362,12 @@ pub(crate) fn match_arm_list(p: &mut Parser) {
362 // } 362 // }
363 // } 363 // }
364 if match_arm(p).is_block() { 364 if match_arm(p).is_block() {
365 p.eat(COMMA); 365 p.eat(T![,]);
366 } else if !p.at(R_CURLY) { 366 } else if !p.at(T!['}']) {
367 p.expect(COMMA); 367 p.expect(T![,]);
368 } 368 }
369 } 369 }
370 p.expect(R_CURLY); 370 p.expect(T!['}']);
371 m.complete(p, MATCH_ARM_LIST); 371 m.complete(p, MATCH_ARM_LIST);
372} 372}
373 373
@@ -399,10 +399,10 @@ fn match_arm(p: &mut Parser) -> BlockLike {
399 attributes::outer_attributes(p); 399 attributes::outer_attributes(p);
400 400
401 patterns::pattern_list_r(p, TokenSet::empty()); 401 patterns::pattern_list_r(p, TokenSet::empty());
402 if p.at(IF_KW) { 402 if p.at(T![if]) {
403 match_guard(p); 403 match_guard(p);
404 } 404 }
405 p.expect(FAT_ARROW); 405 p.expect(T![=>]);
406 let blocklike = expr_stmt(p).1; 406 let blocklike = expr_stmt(p).1;
407 m.complete(p, MATCH_ARM); 407 m.complete(p, MATCH_ARM);
408 blocklike 408 blocklike
@@ -415,7 +415,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
415// } 415// }
416// } 416// }
417fn match_guard(p: &mut Parser) -> CompletedMarker { 417fn match_guard(p: &mut Parser) -> CompletedMarker {
418 assert!(p.at(IF_KW)); 418 assert!(p.at(T![if]));
419 let m = p.start(); 419 let m = p.start();
420 p.bump(); 420 p.bump();
421 expr(p); 421 expr(p);
@@ -429,7 +429,7 @@ fn match_guard(p: &mut Parser) -> CompletedMarker {
429// 'label: {}; 429// 'label: {};
430// } 430// }
431fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker { 431fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
432 assert!(p.at(L_CURLY)); 432 assert!(p.at(T!['{']));
433 let m = m.unwrap_or_else(|| p.start()); 433 let m = m.unwrap_or_else(|| p.start());
434 block(p); 434 block(p);
435 m.complete(p, BLOCK_EXPR) 435 m.complete(p, BLOCK_EXPR)
@@ -441,7 +441,7 @@ fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
441// return 92; 441// return 92;
442// } 442// }
443fn return_expr(p: &mut Parser) -> CompletedMarker { 443fn return_expr(p: &mut Parser) -> CompletedMarker {
444 assert!(p.at(RETURN_KW)); 444 assert!(p.at(T![return]));
445 let m = p.start(); 445 let m = p.start();
446 p.bump(); 446 p.bump();
447 if p.at_ts(EXPR_FIRST) { 447 if p.at_ts(EXPR_FIRST) {
@@ -458,7 +458,7 @@ fn return_expr(p: &mut Parser) -> CompletedMarker {
458// } 458// }
459// } 459// }
460fn continue_expr(p: &mut Parser) -> CompletedMarker { 460fn continue_expr(p: &mut Parser) -> CompletedMarker {
461 assert!(p.at(CONTINUE_KW)); 461 assert!(p.at(T![continue]));
462 let m = p.start(); 462 let m = p.start();
463 p.bump(); 463 p.bump();
464 p.eat(LIFETIME); 464 p.eat(LIFETIME);
@@ -475,7 +475,7 @@ fn continue_expr(p: &mut Parser) -> CompletedMarker {
475// } 475// }
476// } 476// }
477fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker { 477fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
478 assert!(p.at(BREAK_KW)); 478 assert!(p.at(T![break]));
479 let m = p.start(); 479 let m = p.start();
480 p.bump(); 480 p.bump();
481 p.eat(LIFETIME); 481 p.eat(LIFETIME);
@@ -486,7 +486,7 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
486 // for i in break {} 486 // for i in break {}
487 // match break {} 487 // match break {}
488 // } 488 // }
489 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(L_CURLY)) { 489 if p.at_ts(EXPR_FIRST) && !(r.forbid_structs && p.at(T!['{'])) {
490 expr(p); 490 expr(p);
491 } 491 }
492 m.complete(p, BREAK_EXPR) 492 m.complete(p, BREAK_EXPR)
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 97f8122a9..6728e395f 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -19,7 +19,7 @@ use super::*;
19// struct S; 19// struct S;
20pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) { 20pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
21 attributes::inner_attributes(p); 21 attributes::inner_attributes(p);
22 while !p.at(EOF) && !(stop_on_r_curly && p.at(R_CURLY)) { 22 while !p.at(EOF) && !(stop_on_r_curly && p.at(T!['}'])) {
23 item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod) 23 item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
24 } 24 }
25} 25}
@@ -45,20 +45,20 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF
45 match macro_call(p) { 45 match macro_call(p) {
46 BlockLike::Block => (), 46 BlockLike::Block => (),
47 BlockLike::NotBlock => { 47 BlockLike::NotBlock => {
48 p.expect(SEMI); 48 p.expect(T![;]);
49 } 49 }
50 } 50 }
51 m.complete(p, MACRO_CALL); 51 m.complete(p, MACRO_CALL);
52 } else { 52 } else {
53 m.abandon(p); 53 m.abandon(p);
54 if p.at(L_CURLY) { 54 if p.at(T!['{']) {
55 error_block(p, "expected an item"); 55 error_block(p, "expected an item");
56 } else if p.at(R_CURLY) && !stop_on_r_curly { 56 } else if p.at(T!['}']) && !stop_on_r_curly {
57 let e = p.start(); 57 let e = p.start();
58 p.error("unmatched `}`"); 58 p.error("unmatched `}`");
59 p.bump(); 59 p.bump();
60 e.complete(p, ERROR); 60 e.complete(p, ERROR);
61 } else if !p.at(EOF) && !p.at(R_CURLY) { 61 } else if !p.at(EOF) && !p.at(T!['}']) {
62 p.err_and_bump("expected an item"); 62 p.err_and_bump("expected an item");
63 } else { 63 } else {
64 p.error("expected an item"); 64 p.error("expected an item");
@@ -79,32 +79,32 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
79 let mut has_mods = false; 79 let mut has_mods = false;
80 80
81 // modifiers 81 // modifiers
82 has_mods |= p.eat(CONST_KW); 82 has_mods |= p.eat(T![const]);
83 83
84 // test_err unsafe_block_in_mod 84 // test_err unsafe_block_in_mod
85 // fn foo(){} unsafe { } fn bar(){} 85 // fn foo(){} unsafe { } fn bar(){}
86 if p.at(UNSAFE_KW) && p.nth(1) != L_CURLY { 86 if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
87 p.eat(UNSAFE_KW); 87 p.eat(T![unsafe]);
88 has_mods = true; 88 has_mods = true;
89 } 89 }
90 90
91 // test_err async_without_semicolon 91 // test_err async_without_semicolon
92 // fn foo() { let _ = async {} } 92 // fn foo() { let _ = async {} }
93 if p.at(ASYNC_KW) && p.nth(1) != L_CURLY && p.nth(1) != MOVE_KW && p.nth(1) != PIPE { 93 if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
94 p.eat(ASYNC_KW); 94 p.eat(T![async]);
95 has_mods = true; 95 has_mods = true;
96 } 96 }
97 97
98 if p.at(EXTERN_KW) { 98 if p.at(T![extern]) {
99 has_mods = true; 99 has_mods = true;
100 abi(p); 100 abi(p);
101 } 101 }
102 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW { 102 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == T![trait] {
103 p.bump_remap(AUTO_KW); 103 p.bump_remap(T![auto]);
104 has_mods = true; 104 has_mods = true;
105 } 105 }
106 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW { 106 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == T![impl ] {
107 p.bump_remap(DEFAULT_KW); 107 p.bump_remap(T![default]);
108 has_mods = true; 108 has_mods = true;
109 } 109 }
110 110
@@ -135,7 +135,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
135 // test_err wrong_order_fns 135 // test_err wrong_order_fns
136 // async unsafe fn foo() {} 136 // async unsafe fn foo() {}
137 // unsafe const fn bar() {} 137 // unsafe const fn bar() {}
138 FN_KW => { 138 T![fn] => {
139 fn_def(p, flavor); 139 fn_def(p, flavor);
140 m.complete(p, FN_DEF); 140 m.complete(p, FN_DEF);
141 } 141 }
@@ -148,7 +148,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
148 148
149 // test unsafe_auto_trait 149 // test unsafe_auto_trait
150 // unsafe auto trait T {} 150 // unsafe auto trait T {}
151 TRAIT_KW => { 151 T![trait] => {
152 traits::trait_def(p); 152 traits::trait_def(p);
153 m.complete(p, TRAIT_DEF); 153 m.complete(p, TRAIT_DEF);
154 } 154 }
@@ -161,7 +161,7 @@ pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Resul
161 161
162 // test unsafe_default_impl 162 // test unsafe_default_impl
163 // unsafe default impl Foo {} 163 // unsafe default impl Foo {}
164 IMPL_KW => { 164 T![impl ] => {
165 traits::impl_block(p); 165 traits::impl_block(p);
166 m.complete(p, IMPL_BLOCK); 166 m.complete(p, IMPL_BLOCK);
167 } 167 }
@@ -186,10 +186,10 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
186 match p.current() { 186 match p.current() {
187 // test extern_crate 187 // test extern_crate
188 // extern crate foo; 188 // extern crate foo;
189 EXTERN_KW if la == CRATE_KW => extern_crate_item(p, m), 189 T![extern] if la == T![crate] => extern_crate_item(p, m),
190 TYPE_KW => type_def(p, m), 190 T![type] => type_def(p, m),
191 MOD_KW => mod_item(p, m), 191 T![mod] => mod_item(p, m),
192 STRUCT_KW => { 192 T![struct] => {
193 // test struct_items 193 // test struct_items
194 // struct Foo; 194 // struct Foo;
195 // struct Foo {} 195 // struct Foo {}
@@ -199,7 +199,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
199 // a: i32, 199 // a: i32,
200 // b: f32, 200 // b: f32,
201 // } 201 // }
202 nominal::struct_def(p, m, STRUCT_KW); 202 nominal::struct_def(p, m, T![struct]);
203 } 203 }
204 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 204 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
205 // test union_items 205 // test union_items
@@ -208,16 +208,16 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
208 // a: i32, 208 // a: i32,
209 // b: f32, 209 // b: f32,
210 // } 210 // }
211 nominal::struct_def(p, m, UNION_KW); 211 nominal::struct_def(p, m, T![union]);
212 } 212 }
213 ENUM_KW => nominal::enum_def(p, m), 213 T![enum] => nominal::enum_def(p, m),
214 USE_KW => use_item::use_item(p, m), 214 T![use] => use_item::use_item(p, m),
215 CONST_KW if (la == IDENT || la == MUT_KW) => consts::const_def(p, m), 215 T![const] if (la == IDENT || la == T![mut]) => consts::const_def(p, m),
216 STATIC_KW => consts::static_def(p, m), 216 T![static] => consts::static_def(p, m),
217 // test extern_block 217 // test extern_block
218 // extern {} 218 // extern {}
219 EXTERN_KW 219 T![extern]
220 if la == L_CURLY || ((la == STRING || la == RAW_STRING) && p.nth(2) == L_CURLY) => 220 if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) =>
221 { 221 {
222 abi(p); 222 abi(p);
223 extern_item_list(p); 223 extern_item_list(p);
@@ -225,7 +225,7 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
225 } 225 }
226 _ => return Err(m), 226 _ => return Err(m),
227 }; 227 };
228 if p.at(SEMI) { 228 if p.at(T![;]) {
229 p.err_and_bump( 229 p.err_and_bump(
230 "expected item, found `;`\n\ 230 "expected item, found `;`\n\
231 consider removing this semicolon", 231 consider removing this semicolon",
@@ -235,27 +235,27 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
235} 235}
236 236
237fn extern_crate_item(p: &mut Parser, m: Marker) { 237fn extern_crate_item(p: &mut Parser, m: Marker) {
238 assert!(p.at(EXTERN_KW)); 238 assert!(p.at(T![extern]));
239 p.bump(); 239 p.bump();
240 assert!(p.at(CRATE_KW)); 240 assert!(p.at(T![crate]));
241 p.bump(); 241 p.bump();
242 name_ref(p); 242 name_ref(p);
243 opt_alias(p); 243 opt_alias(p);
244 p.expect(SEMI); 244 p.expect(T![;]);
245 m.complete(p, EXTERN_CRATE_ITEM); 245 m.complete(p, EXTERN_CRATE_ITEM);
246} 246}
247 247
248pub(crate) fn extern_item_list(p: &mut Parser) { 248pub(crate) fn extern_item_list(p: &mut Parser) {
249 assert!(p.at(L_CURLY)); 249 assert!(p.at(T!['{']));
250 let m = p.start(); 250 let m = p.start();
251 p.bump(); 251 p.bump();
252 mod_contents(p, true); 252 mod_contents(p, true);
253 p.expect(R_CURLY); 253 p.expect(T!['}']);
254 m.complete(p, EXTERN_ITEM_LIST); 254 m.complete(p, EXTERN_ITEM_LIST);
255} 255}
256 256
257fn fn_def(p: &mut Parser, flavor: ItemFlavor) { 257fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
258 assert!(p.at(FN_KW)); 258 assert!(p.at(T![fn]));
259 p.bump(); 259 p.bump();
260 260
261 name_r(p, ITEM_RECOVERY_SET); 261 name_r(p, ITEM_RECOVERY_SET);
@@ -263,7 +263,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
263 // fn foo<T: Clone + Copy>(){} 263 // fn foo<T: Clone + Copy>(){}
264 type_params::opt_type_param_list(p); 264 type_params::opt_type_param_list(p);
265 265
266 if p.at(L_PAREN) { 266 if p.at(T!['(']) {
267 match flavor { 267 match flavor {
268 ItemFlavor::Mod => params::param_list(p), 268 ItemFlavor::Mod => params::param_list(p),
269 ItemFlavor::Trait => params::param_list_opt_patterns(p), 269 ItemFlavor::Trait => params::param_list_opt_patterns(p),
@@ -282,7 +282,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
282 282
283 // test fn_decl 283 // test fn_decl
284 // trait T { fn foo(); } 284 // trait T { fn foo(); }
285 if p.at(SEMI) { 285 if p.at(T![;]) {
286 p.bump(); 286 p.bump();
287 } else { 287 } else {
288 expressions::block(p) 288 expressions::block(p)
@@ -292,7 +292,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
292// test type_item 292// test type_item
293// type Foo = Bar; 293// type Foo = Bar;
294fn type_def(p: &mut Parser, m: Marker) { 294fn type_def(p: &mut Parser, m: Marker) {
295 assert!(p.at(TYPE_KW)); 295 assert!(p.at(T![type]));
296 p.bump(); 296 p.bump();
297 297
298 name(p); 298 name(p);
@@ -301,7 +301,7 @@ fn type_def(p: &mut Parser, m: Marker) {
301 // type Result<T> = (); 301 // type Result<T> = ();
302 type_params::opt_type_param_list(p); 302 type_params::opt_type_param_list(p);
303 303
304 if p.at(COLON) { 304 if p.at(T![:]) {
305 type_params::bounds(p); 305 type_params::bounds(p);
306 } 306 }
307 307
@@ -309,32 +309,32 @@ fn type_def(p: &mut Parser, m: Marker) {
309 // type Foo where Foo: Copy = (); 309 // type Foo where Foo: Copy = ();
310 type_params::opt_where_clause(p); 310 type_params::opt_where_clause(p);
311 311
312 if p.eat(EQ) { 312 if p.eat(T![=]) {
313 types::type_(p); 313 types::type_(p);
314 } 314 }
315 p.expect(SEMI); 315 p.expect(T![;]);
316 m.complete(p, TYPE_ALIAS_DEF); 316 m.complete(p, TYPE_ALIAS_DEF);
317} 317}
318 318
319pub(crate) fn mod_item(p: &mut Parser, m: Marker) { 319pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
320 assert!(p.at(MOD_KW)); 320 assert!(p.at(T![mod]));
321 p.bump(); 321 p.bump();
322 322
323 name(p); 323 name(p);
324 if p.at(L_CURLY) { 324 if p.at(T!['{']) {
325 mod_item_list(p); 325 mod_item_list(p);
326 } else if !p.eat(SEMI) { 326 } else if !p.eat(T![;]) {
327 p.error("expected `;` or `{`"); 327 p.error("expected `;` or `{`");
328 } 328 }
329 m.complete(p, MODULE); 329 m.complete(p, MODULE);
330} 330}
331 331
332pub(crate) fn mod_item_list(p: &mut Parser) { 332pub(crate) fn mod_item_list(p: &mut Parser) {
333 assert!(p.at(L_CURLY)); 333 assert!(p.at(T!['{']));
334 let m = p.start(); 334 let m = p.start();
335 p.bump(); 335 p.bump();
336 mod_contents(p, true); 336 mod_contents(p, true);
337 p.expect(R_CURLY); 337 p.expect(T!['}']);
338 m.complete(p, ITEM_LIST); 338 m.complete(p, ITEM_LIST);
339} 339}
340 340
@@ -345,16 +345,16 @@ fn macro_call(p: &mut Parser) -> BlockLike {
345} 345}
346 346
347pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { 347pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
348 p.expect(EXCL); 348 p.expect(T![!]);
349 if p.at(IDENT) { 349 if p.at(IDENT) {
350 name(p); 350 name(p);
351 } 351 }
352 match p.current() { 352 match p.current() {
353 L_CURLY => { 353 T!['{'] => {
354 token_tree(p); 354 token_tree(p);
355 BlockLike::Block 355 BlockLike::Block
356 } 356 }
357