Repository: rust-analyzer/rust-analyzer
Pull request #1881 (2019-09-20 13:23:51)

don't confuse macro with !=


Patch:
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs
index 756acf4153..66cf325243 100644
--- a/crates/ra_assists/src/lib.rs
+++ b/crates/ra_assists/src/lib.rs
@@ -96,7 +96,6 @@ mod fill_match_arms;
 mod merge_match_arms;
 mod introduce_variable;
 mod inline_local_variable;
-mod raw_string;
 mod replace_if_let_with_match;
 mod split_import;
 mod remove_dbg;
@@ -126,10 +125,6 @@ fn all_assists<DB: HirDatabase>() -> &'static [fn(AssistCtx<DB>) -> Option<Assis
         move_guard::move_guard_to_arm_body,
         move_guard::move_arm_cond_to_match_guard,
         move_bounds::move_bounds_to_where_clause,
-        raw_string::add_hash,
-        raw_string::make_raw_string,
-        raw_string::make_usual_string,
-        raw_string::remove_hash,
     ]
 }
 
diff --git a/crates/ra_assists/src/raw_string.rs b/crates/ra_assists/src/raw_string.rs
deleted file mode 100644
index e002670601..0000000000
--- a/crates/ra_assists/src/raw_string.rs
+++ /dev/null
@@ -1,370 +0,0 @@
-use hir::db::HirDatabase;
-use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit};
-
-use crate::{Assist, AssistCtx, AssistId};
-
-pub(crate) fn make_raw_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let literal = ctx.node_at_offset::<Literal>()?;
-    if literal.token().kind() != ra_syntax::SyntaxKind::STRING {
-        return None;
-    }
-    ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| {
-        edit.target(literal.syntax().text_range());
-        edit.insert(literal.syntax().text_range().start(), "r");
-    });
-    ctx.build()
-}
-
-fn find_usual_string_range(s: &str) -> Option<TextRange> {
-    Some(TextRange::from_to(
-        TextUnit::from(s.find('"')? as u32),
-        TextUnit::from(s.rfind('"')? as u32),
-    ))
-}
-
-pub(crate) fn make_usual_string(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let literal = ctx.node_at_offset::<Literal>()?;
-    if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
-        return None;
-    }
-    let token = literal.token();
-    let text = token.text().as_str();
-    let usual_string_range = find_usual_string_range(text)?;
-    ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| {
-        edit.target(literal.syntax().text_range());
-        // parse inside string to escape `"`
-        let start_of_inside = usual_string_range.start().to_usize() + 1;
-        let end_of_inside = usual_string_range.end().to_usize();
-        let inside_str = &text[start_of_inside..end_of_inside];
-        let escaped = inside_str.escape_default().to_string();
-        edit.replace(literal.syntax().text_range(), format!("\"{}\"", escaped));
-    });
-    ctx.build()
-}
-
-pub(crate) fn add_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let literal = ctx.node_at_offset::<Literal>()?;
-    if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
-        return None;
-    }
-    ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| {
-        edit.target(literal.syntax().text_range());
-        edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#");
-        edit.insert(literal.syntax().text_range().end(), "#");
-    });
-    ctx.build()
-}
-
-pub(crate) fn remove_hash(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let literal = ctx.node_at_offset::<Literal>()?;
-    if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING {
-        return None;
-    }
-    let token = literal.token();
-    let text = token.text().as_str();
-    if text.starts_with("r\"") {
-        // no hash to remove
-        return None;
-    }
-    ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| {
-        edit.target(literal.syntax().text_range());
-        let result = &text[2..text.len() - 1];
-        let result = if result.starts_with("\"") {
-            // no more hash, escape
-            let internal_str = &result[1..result.len() - 1];
-            format!("\"{}\"", internal_str.escape_default().to_string())
-        } else {
-            result.to_owned()
-        };
-        edit.replace(literal.syntax().text_range(), format!("r{}", result));
-    });
-    ctx.build()
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target};
-
-    #[test]
-    fn make_raw_string_target() {
-        check_assist_target(
-            make_raw_string,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-            r#""random string""#,
-        );
-    }
-
-    #[test]
-    fn make_raw_string_works() {
-        check_assist(
-            make_raw_string,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn make_raw_string_with_escaped_works() {
-        check_assist(
-            make_raw_string,
-            r#"
-            fn f() {
-                let s = <|>"random\nstring";
-            }
-            "#,
-            r#"
-            fn f() {
-                let s = <|>r"random\nstring";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn make_raw_string_not_works() {
-        check_assist_not_applicable(
-            make_raw_string,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-        );
-    }
-
-    #[test]
-    fn add_hash_target() {
-        check_assist_target(
-            add_hash,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-            r#"r"random string""#,
-        );
-    }
-
-    #[test]
-    fn add_hash_works() {
-        check_assist(
-            add_hash,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-        )
-    }
-
-    #[test]
-    fn add_more_hash_works() {
-        check_assist(
-            add_hash,
-            r##"
-            fn f() {
-                let s = <|>r#"random"string"#;
-            }
-            "##,
-            r###"
-            fn f() {
-                let s = <|>r##"random"string"##;
-            }
-            "###,
-        )
-    }
-
-    #[test]
-    fn add_hash_not_works() {
-        check_assist_not_applicable(
-            add_hash,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-        );
-    }
-
-    #[test]
-    fn remove_hash_target() {
-        check_assist_target(
-            remove_hash,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-            r##"r#"random string"#"##,
-        );
-    }
-
-    #[test]
-    fn remove_hash_works() {
-        check_assist(
-            remove_hash,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn remove_hash_with_quote_works() {
-        check_assist(
-            remove_hash,
-            r##"
-            fn f() {
-                let s = <|>r#"random"str"ing"#;
-            }
-            "##,
-            r#"
-            fn f() {
-                let s = <|>r"random\"str\"ing";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn remove_more_hash_works() {
-        check_assist(
-            remove_hash,
-            r###"
-            fn f() {
-                let s = <|>r##"random string"##;
-            }
-            "###,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-        )
-    }
-
-    #[test]
-    fn remove_hash_not_works() {
-        check_assist_not_applicable(
-            remove_hash,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-        );
-    }
-
-    #[test]
-    fn remove_hash_no_hash_not_works() {
-        check_assist_not_applicable(
-            remove_hash,
-            r#"
-            fn f() {
-                let s = <|>r"random string";
-            }
-            "#,
-        );
-    }
-
-    #[test]
-    fn make_usual_string_target() {
-        check_assist_target(
-            make_usual_string,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-            r##"r#"random string"#"##,
-        );
-    }
-
-    #[test]
-    fn make_usual_string_works() {
-        check_assist(
-            make_usual_string,
-            r##"
-            fn f() {
-                let s = <|>r#"random string"#;
-            }
-            "##,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn make_usual_string_with_quote_works() {
-        check_assist(
-            make_usual_string,
-            r##"
-            fn f() {
-                let s = <|>r#"random"str"ing"#;
-            }
-            "##,
-            r#"
-            fn f() {
-                let s = <|>"random\"str\"ing";
-            }
-            "#,
-        )
-    }
-
-    #[test]
-    fn make_usual_string_more_hash_works() {
-        check_assist(
-            make_usual_string,
-            r###"
-            fn f() {
-                let s = <|>r##"random string"##;
-            }
-            "###,
-            r##"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "##,
-        )
-    }
-
-    #[test]
-    fn make_usual_string_not_works() {
-        check_assist_not_applicable(
-            make_usual_string,
-            r#"
-            fn f() {
-                let s = <|>"random string";
-            }
-            "#,
-        );
-    }
-}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 28002f7400..706d24c325 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -313,7 +313,7 @@ pub struct StructField {
     pub(crate) id: StructFieldId,
 }
 
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Debug)]
 pub enum FieldSource {
     Named(ast::RecordFieldDef),
     Pos(ast::TupleFieldDef),
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
deleted file mode 100644
index c6ad85fc7c..0000000000
--- a/crates/ra_hir/src/from_source.rs
+++ /dev/null
@@ -1,211 +0,0 @@
-use ra_db::{FileId, FilePosition};
-use ra_syntax::{
-    algo::find_node_at_offset,
-    ast::{self, AstNode, NameOwner},
-    SyntaxNode,
-};
-
-use crate::{
-    db::{AstDatabase, DefDatabase, HirDatabase},
-    ids::{AstItemDef, LocationCtx},
-    name::AsName,
-    Const, Crate, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, Module,
-    ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
-};
-
-pub trait FromSource: Sized {
-    type Ast;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>;
-}
-
-impl FromSource for Struct {
-    type Ast = ast::StructDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Struct { id })
-    }
-}
-impl FromSource for Union {
-    type Ast = ast::StructDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Union { id })
-    }
-}
-impl FromSource for Enum {
-    type Ast = ast::EnumDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Enum { id })
-    }
-}
-impl FromSource for Trait {
-    type Ast = ast::TraitDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Trait { id })
-    }
-}
-impl FromSource for Function {
-    type Ast = ast::FnDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Function { id })
-    }
-}
-impl FromSource for Const {
-    type Ast = ast::ConstDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Const { id })
-    }
-}
-impl FromSource for Static {
-    type Ast = ast::StaticDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(Static { id })
-    }
-}
-impl FromSource for TypeAlias {
-    type Ast = ast::TypeAliasDef;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let id = from_source(db, src)?;
-        Some(TypeAlias { id })
-    }
-}
-// FIXME: add impl FromSource for MacroDef
-
-impl FromSource for ImplBlock {
-    type Ast = ast::ImplBlock;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let module_src = crate::ModuleSource::from_child_node(
-            db,
-            src.file_id.original_file(db),
-            &src.ast.syntax(),
-        );
-        let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?;
-        let impls = module.impl_blocks(db);
-        impls.into_iter().find(|b| b.source(db) == src)
-    }
-}
-
-impl FromSource for EnumVariant {
-    type Ast = ast::EnumVariant;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let parent_enum = src.ast.parent_enum();
-        let src_enum = Source { file_id: src.file_id, ast: parent_enum };
-        let variants = Enum::from_source(db, src_enum)?.variants(db);
-        variants.into_iter().find(|v| v.source(db) == src)
-    }
-}
-
-impl FromSource for StructField {
-    type Ast = FieldSource;
-    fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
-        let variant_def: VariantDef = match src.ast {
-            FieldSource::Named(ref field) => {
-                let ast = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
-                let src = Source { file_id: src.file_id, ast };
-                let def = Struct::from_source(db, src)?;
-                VariantDef::from(def)
-            }
-            FieldSource::Pos(ref field) => {
-                let ast = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
-                let src = Source { file_id: src.file_id, ast };
-                let def = EnumVariant::from_source(db, src)?;
-                VariantDef::from(def)
-            }
-        };
-        variant_def
-            .variant_data(db)
-            .fields()
-            .into_iter()
-            .flat_map(|it| it.iter())
-            .map(|(id, _)| StructField { parent: variant_def.clone(), id })
-            .find(|f| f.source(db) == src)
-    }
-}
-
-// FIXME: simplify it
-impl ModuleSource {
-    pub fn from_position(
-        db: &(impl DefDatabase + AstDatabase),
-        position: FilePosition,
-    ) -> ModuleSource {
-        let parse = db.parse(position.file_id);
-        match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) {
-            Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()),
-            _ => {
-                let source_file = parse.tree().to_owned();
-                ModuleSource::SourceFile(source_file)
-            }
-        }
-    }
-
-    pub fn from_child_node(
-        db: &(impl DefDatabase + AstDatabase),
-        file_id: FileId,
-        child: &SyntaxNode,
-    ) -> ModuleSource {
-        if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
-            ModuleSource::Module(m.clone())
-        } else {
-            let source_file = db.parse(file_id).tree().to_owned();
-            ModuleSource::SourceFile(source_file)
-        }
-    }
-
-    pub fn from_file_id(db: &(impl DefDatabase + AstDatabase), file_id: FileId) -> ModuleSource {
-        let source_file = db.parse(file_id).tree().to_owned();
-        ModuleSource::SourceFile(source_file)
-    }
-}
-
-impl Module {
-    pub fn from_declaration(db: &impl HirDatabase, src: Source<ast::Module>) -> Option<Self> {
-        let src_parent = Source {
-            file_id: src.file_id,
-            ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None),
-        };
-        let parent_module = Module::from_definition(db, src_parent)?;
-        let child_name = src.ast.name()?;
-        parent_module.child(db, &child_name.as_name())
-    }
-
-    pub fn from_definition(
-        db: &(impl DefDatabase + AstDatabase),
-        src: Source<ModuleSource>,
-    ) -> Option<Self> {
-        let decl_id = match src.ast {
-            ModuleSource::Module(ref module) => {
-                assert!(!module.has_semi());
-                let ast_id_map = db.ast_id_map(src.file_id);
-                let item_id = ast_id_map.ast_id(module).with_file_id(src.file_id);
-                Some(item_id)
-            }
-            ModuleSource::SourceFile(_) => None,
-        };
-
-        let source_root_id = db.file_source_root(src.file_id.original_file(db));
-        db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
-            |krate| {
-                let def_map = db.crate_def_map(krate);
-                let module_id = def_map.find_module_by_source(src.file_id, decl_id)?;
-                Some(Module { krate, module_id })
-            },
-        )
-    }
-}
-
-fn from_source<N, DEF>(db: &(impl DefDatabase + AstDatabase), src: Source<N>) -> Option<DEF>
-where
-    N: AstNode,
-    DEF: AstItemDef<N>,
-{
-    let module_src =
-        crate::ModuleSource::from_child_node(db, src.file_id.original_file(db), &src.ast.syntax());
-    let module = Module::from_definition(db, Source { file_id: src.file_id, ast: module_src })?;
-    let ctx = LocationCtx::new(db, module, src.file_id);
-    Some(DEF::from_ast(ctx, &src.ast))
-}
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index a9de9fb6b1..e7a576aa0a 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -53,8 +53,6 @@ pub mod diagnostics;
 
 mod code_model;
 
-pub mod from_source;
-
 #[cfg(test)]
 mod marks;
 
@@ -69,7 +67,6 @@ pub use self::{
     adt::VariantDef,
     either::Either,
     expr::ExprScopes,
-    from_source::FromSource,
     generics::{GenericParam, GenericParams, HasGenericParams},
     ids::{HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile},
     impl_block::ImplBlock,
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs
index cb405091ee..8dcea50713 100644
--- a/crates/ra_hir/src/mock.rs
+++ b/crates/ra_hir/src/mock.rs
@@ -93,11 +93,7 @@ impl MockDatabase {
         let mut files: Vec<FileId> = self.files.values().copied().collect();
         files.sort();
         for file in files {
-            let src = crate::Source {
-                file_id: file.into(),
-                ast: crate::ModuleSource::new(self, Some(file), None),
-            };
-            let module = crate::Module::from_definition(self, src).unwrap();
+            let module = crate::source_binder::module_from_file_id(self, file).unwrap();
             module.diagnostics(
                 self,
                 &mut DiagnosticSink::new(|d| {
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 296acc3642..4d895f0a19 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -7,9 +7,10 @@
 /// purely for "IDE needs".
 use std::sync::Arc;
 
-use ra_db::FileId;
+use ra_db::{FileId, FilePosition};
 use ra_syntax::{
-    ast::{self, AstNode},
+    algo::find_node_at_offset,
+    ast::{self, AstNode, NameOwner},
     AstPtr,
     SyntaxKind::*,
     SyntaxNode, SyntaxNodePtr, TextRange, TextUnit,
@@ -27,28 +28,119 @@ use crate::{
     path::known,
     resolve::{ScopeDef, TypeNs, ValueNs},
     ty::method_resolution::implements_trait,
-    AsName, Const, DefWithBody, Either, Enum, FromSource, Function, HasBody, HirFileId, MacroDef,
-    Module, Name, Path, Resolver, Static, Struct, Ty,
+    AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HasBody, HirFileId, MacroDef,
+    Module, Name, Path, Resolver, Static, Struct, Trait, Ty,
 };
 
+/// Locates the module by `FileId`. Picks topmost module in the file.
+pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option<Module> {
+    module_from_source(db, file_id.into(), None)
+}
+
+/// Locates the child module by `mod child;` declaration.
+pub fn module_from_declaration(
+    db: &impl HirDatabase,
+    file_id: FileId,
+    decl: ast::Module,
+) -> Option<Module> {
+    let parent_module = module_from_file_id(db, file_id);
+    let child_name = decl.name();
+    match (parent_module, child_name) {
+        (Some(parent_module), Some(child_name)) => parent_module.child(db, &child_name.as_name()),
+        _ => None,
+    }
+}
+
+/// Locates the module by position in the source code.
+pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
+    let parse = db.parse(position.file_id);
+    match &find_node_at_offset::<ast::Module>(parse.tree().syntax(), position.offset) {
+        Some(m) if !m.has_semi() => module_from_inline(db, position.file_id, m.clone()),
+        _ => module_from_file_id(db, position.file_id),
+    }
+}
+
+fn module_from_inline(
+    db: &impl HirDatabase,
+    file_id: FileId,
+    module: ast::Module,
+) -> Option<Module> {
+    assert!(!module.has_semi());
+    let file_id = file_id.into();
+    let ast_id_map = db.ast_id_map(file_id);
+    let item_id = ast_id_map.ast_id(&module).with_file_id(file_id);
+    module_from_source(db, file_id, Some(item_id))
+}
+
+/// Locates the module by child syntax element within the module
+pub fn module_from_child_node(
+    db: &impl HirDatabase,
+    file_id: FileId,
+    child: &SyntaxNode,
+) -> Option<Module> {
+    if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
+        module_from_inline(db, file_id, m)
+    } else {
+        module_from_file_id(db, file_id)
+    }
+}
+
+fn module_from_source(
+    db: &impl HirDatabase,
+    file_id: HirFileId,
+    decl_id: Option<AstId<ast::Module>>,
+) -> Option<Module> {
+    let source_root_id = db.file_source_root(file_id.as_original_file());
+    db.source_root_crates(source_root_id).iter().map(|&crate_id| Crate { crate_id }).find_map(
+        |krate| {
+            let def_map = db.crate_def_map(krate);
+            let module_id = def_map.find_module_by_source(file_id, decl_id)?;
+            Some(Module { krate, module_id })
+        },
+    )
+}
+
+pub fn struct_from_module(
+    db: &impl HirDatabase,
+    module: Module,
+    struct_def: &ast::StructDef,
+) -> Struct {
+    let file_id = module.definition_source(db).file_id;
+    let ctx = LocationCtx::new(db, module, file_id);
+    Struct { id: ctx.to_def(struct_def) }
+}
+
+pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
+    let file_id = module.definition_source(db).file_id;
+    let ctx = LocationCtx::new(db, module, file_id);
+    Enum { id: ctx.to_def(enum_def) }
+}
+
+pub fn trait_from_module(
+    db: &impl HirDatabase,
+    module: Module,
+    trait_def: &ast::TraitDef,
+) -> Trait {
+    let file_id = module.definition_source(db).file_id;
+    let ctx = LocationCtx::new(db, module, file_id);
+    Trait { id: ctx.to_def(trait_def) }
+}
+
 fn try_get_resolver_for_node(
     db: &impl HirDatabase,
     file_id: FileId,
     node: &SyntaxNode,
 ) -> Option<Resolver> {
     if let Some(module) = ast::Module::cast(node.clone()) {
-        let src = crate::Source { file_id: file_id.into(), ast: module };
-        Some(crate::Module::from_declaration(db, src)?.resolver(db))
-    } else if let Some(file) = ast::SourceFile::cast(node.clone()) {
-        let src =
-            crate::Source { file_id: file_id.into(), ast: crate::ModuleSource::SourceFile(file) };
-        Some(crate::Module::from_definition(db, src)?.resolver(db))
+        Some(module_from_declaration(db, file_id, module)?.resolver(db))
+    } else if let Some(_) = ast::SourceFile::cast(node.clone()) {
+        Some(module_from_source(db, file_id.into(), None)?.resolver(db))
     } else if let Some(s) = ast::StructDef::cast(node.clone()) {
-        let src = crate::Source { file_id: file_id.into(), ast: s };
-        Some(Struct::from_source(db, src)?.resolver(db))
+        let module = module_from_child_node(db, file_id, s.syntax())?;
+        Some(struct_from_module(db, module, &s).resolver(db))
     } else if let Some(e) = ast::EnumDef::cast(node.clone()) {
-        let src = crate::Source { file_id: file_id.into(), ast: e };
-        Some(Enum::from_source(db, src)?.resolver(db))
+        let module = module_from_child_node(db, file_id, e.syntax())?;
+        Some(enum_from_module(db, module, &e).resolver(db))
     } else if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
         Some(def_with_body_from_child_node(db, file_id, node)?.resolver(db))
     } else {
@@ -62,10 +154,8 @@ fn def_with_body_from_child_node(
     file_id: FileId,
     node: &SyntaxNode,
 ) -> Option<DefWithBody> {
-    let src = crate::ModuleSource::from_child_node(db, file_id, node);
-    let module = Module::from_definition(db, crate::Source { file_id: file_id.into(), ast: src })?;
+    let module = module_from_child_node(db, file_id, node)?;
     let ctx = LocationCtx::new(db, module, file_id.into());
-
     node.ancestors().find_map(|node| {
         if let Some(def) = ast::FnDef::cast(node.clone()) {
             return Some(Function { id: ctx.to_def(&def) }.into());
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 59bd3689b5..7139947b34 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -1,3 +1,4 @@
+use hir::source_binder;
 use ra_syntax::{
     algo::{find_covering_element, find_node_at_offset},
     ast, AstNode, Parse, SourceFile,
@@ -46,11 +47,7 @@ impl<'a> CompletionContext<'a> {
         original_parse: &'a Parse<ast::SourceFile>,
         position: FilePosition,
     ) -> Option<CompletionContext<'a>> {
-        let src = hir::ModuleSource::from_position(db, position);
-        let module = hir::Module::from_definition(
-            db,
-            hir::Source { file_id: position.file_id.into(), ast: src },
-        );
+        let module = source_binder::module_from_position(db, position);
         let token =
             original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?;
         let analyzer =
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index 1ae152e5b1..c448aa8c5d 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -1,6 +1,9 @@
 use std::cell::RefCell;
 
-use hir::diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink};
+use hir::{
+    diagnostics::{AstDiagnostic, Diagnostic as _, DiagnosticSink},
+    source_binder,
+};
 use itertools::Itertools;
 use ra_assists::ast_editor::{AstBuilder, AstEditor};
 use ra_db::SourceDatabase;
@@ -86,10 +89,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
             fix: Some(fix),
         })
     });
-    let source_file = db.parse(file_id).tree().to_owned();
-    let src =
-        hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) };
-    if let Some(m) = hir::Module::from_definition(db, src) {
+    if let Some(m) = source_binder::module_from_file_id(db, file_id) {
         m.diagnostics(db, &mut sink);
     };
     drop(sink);
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index bc8863dadb..503dcacff4 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -96,8 +96,9 @@ pub(crate) fn name_definition(
 
     if let Some(module) = ast::Module::cast(parent.clone()) {
         if module.has_semi() {
-            let src = hir::Source { file_id: file_id.into(), ast: module };
-            if let Some(child_module) = hir::Module::from_declaration(db, src) {
+            if let Some(child_module) =
+                hir::source_binder::module_from_declaration(db, file_id, module)
+            {
                 let nav = NavigationTarget::from_module(db, child_module);
                 return Some(vec![nav]);
             }
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index f57f9a21b6..c5620dd522 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -1,4 +1,4 @@
-use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor};
+use hir::{db::HirDatabase, source_binder, ApplicationTy, Ty, TypeCtor};
 use ra_db::SourceDatabase;
 use ra_syntax::{algo::find_node_at_offset, ast, AstNode};
 
@@ -11,21 +11,17 @@ pub(crate) fn goto_implementation(
     let parse = db.parse(position.file_id);
     let syntax = parse.tree().syntax().clone();
 
-    let src = hir::ModuleSource::from_position(db, position);
-    let module = hir::Module::from_definition(
-        db,
-        hir::Source { file_id: position.file_id.into(), ast: src },
-    )?;
+    let module = source_binder::module_from_position(db, position)?;
 
     if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
         return Some(RangeInfo::new(
             nominal_def.syntax().text_range(),
-            impls_for_def(db, position, &nominal_def, module)?,
+            impls_for_def(db, &nominal_def, module)?,
         ));
     } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(&syntax, position.offset) {
         return Some(RangeInfo::new(
             trait_def.syntax().text_range(),
-            impls_for_trait(db, position, &trait_def, module)?,
+            impls_for_trait(db, &trait_def, module)?,
         ));
     }
 
@@ -34,19 +30,14 @@ pub(crate) fn goto_implementation(
 
 fn impls_for_def(
     db: &RootDatabase,
-    position: FilePosition,
     node: &ast::NominalDef,
     module: hir::Module,
 ) -> Option<Vec<NavigationTarget>> {
     let ty = match node {
         ast::NominalDef::StructDef(def) => {
-            let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() };
-            hir::Struct::from_source(db, src)?.ty(db)
-        }
-        ast::NominalDef::EnumDef(def) => {
-            let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() };
-            hir::Enum::from_source(db, src)?.ty(db)
+            source_binder::struct_from_module(db, module, &def).ty(db)
         }
+        ast::NominalDef::EnumDef(def) => source_binder::enum_from_module(db, module, &def).ty(db),
     };
 
     let krate = module.krate(db)?;
@@ -63,12 +54,10 @@ fn impls_for_def(
 
 fn impls_for_trait(
     db: &RootDatabase,
-    position: FilePosition,
     node: &ast::TraitDef,
     module: hir::Module,
 ) -> Option<Vec<NavigationTarget>> {
-    let src = hir::Source { file_id: position.file_id.into(), ast: node.clone() };
-    let tr = hir::Trait::from_source(db, src)?;
+    let tr = source_binder::trait_from_module(db, module, node);
 
     let krate = module.krate(db)?;
     let impls = db.impls_in_crate(krate);
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 412dc4d719..e90fbd4285 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -223,7 +223,6 @@ impl Query {
     }
 }
 
-/// Info associated with a text range.
 #[derive(Debug)]
 pub struct RangeInfo<T> {
     pub range: TextRange,
@@ -236,8 +235,6 @@ impl<T> RangeInfo<T> {
     }
 }
 
-/// Contains information about a call site. Specifically the
-/// `FunctionSignature`and current parameter.
 #[derive(Debug)]
 pub struct CallInfo {
     pub signature: FunctionSignature,
@@ -328,12 +325,11 @@ impl Analysis {
         (host.analysis(), file_id)
     }
 
-    /// Features for Analysis.
     pub fn feature_flags(&self) -> &FeatureFlags {
         &self.db.feature_flags
     }
 
-    /// Debug info about the current state of the analysis.
+    /// Debug info about the current state of the analysis
     pub fn status(&self) -> Cancelable<String> {
         self.with_db(|db| status::status(&*db))
     }
@@ -444,7 +440,6 @@ impl Analysis {
         })
     }
 
-    /// Returns the definitions from the symbol at `position`.
     pub fn goto_definition(
         &self,
         position: FilePosition,
@@ -452,7 +447,6 @@ impl Analysis {
         self.with_db(|db| goto_definition::goto_definition(db, position))
     }
 
-    /// Returns the impls from the symbol at `position`.
     pub fn goto_implementation(
         &self,
         position: FilePosition,
@@ -460,7 +454,6 @@ impl Analysis {
         self.with_db(|db| impls::goto_implementation(db, position))
     }
 
-    /// Returns the type definitions for the symbol at `position`.
     pub fn goto_type_definition(
         &self,
         position: FilePosition,
@@ -547,7 +540,6 @@ impl Analysis {
         self.with_db(|db| references::rename(db, position, new_name))
     }
 
-    /// Performs an operation on that may be Canceled.
     fn with_db<F: FnOnce(&db::RootDatabase) -> T + std::panic::UnwindSafe, T>(
         &self,
         f: F,
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs
index 3668da8d74..7d5f9ea2c2 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide_api/src/parent_module.rs
@@ -5,11 +5,7 @@ use crate::{db::RootDatabase, NavigationTarget};
 /// This returns `Vec` because a module may be included from several places. We
 /// don't handle this case yet though, so the Vec has length at most one.
 pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<NavigationTarget> {
-    let src = hir::ModuleSource::from_position(db, position);
-    let module = match hir::Module::from_definition(
-        db,
-        hir::Source { file_id: position.file_id.into(), ast: src },
-    ) {
+    let module = match hir::source_binder::module_from_position(db, position) {
         None => return Vec::new(),
         Some(it) => it,
     };
@@ -19,12 +15,10 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
 
 /// Returns `Vec` for the same reason as `parent_module`
 pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
-    let src = hir::ModuleSource::from_file_id(db, file_id);
-    let module =
-        match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src }) {
-            Some(it) => it,
-            None => return Vec::new(),
-        };
+    let module = match hir::source_binder::module_from_file_id(db, file_id) {
+        Some(it) => it,
+        None => return Vec::new(),
+    };
     let krate = match module.krate(db) {
         Some(it) => it,
         None => return Vec::new(),
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index acca71f2a8..5f1f0efc30 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -1,4 +1,4 @@
-use hir::{Either, ModuleSource};
+use hir::{source_binder, Either, ModuleSource};
 use ra_db::SourceDatabase;
 use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode};
 use relative_path::{RelativePath, RelativePathBuf};
@@ -135,8 +135,9 @@ fn rename_mod(
 ) -> Option<SourceChange> {
     let mut source_file_edits = Vec::new();
     let mut file_system_edits = Vec::new();
-    let module_src = hir::Source { file_id: position.file_id.into(), ast: ast_module.clone() };
-    if let Some(module) = hir::Module::from_declaration(db, module_src) {
+    if let Some(module) =
+        source_binder::module_from_declaration(db, position.file_id, ast_module.clone())
+    {
         let src = module.definition_source(db);
         let file_id = src.file_id.as_original_file();
         match src.ast {
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs
index 095ca56c4c..9d84b3d084 100644
--- a/crates/ra_ide_api/src/runnables.rs
+++ b/crates/ra_ide_api/src/runnables.rs
@@ -63,9 +63,7 @@ fn runnable_mod(db: &RootDatabase, file_id: FileId, module: ast::Module) -> Opti
         return None;
     }
     let range = module.syntax().text_range();
-    let src = hir::ModuleSource::from_child_node(db, file_id, &module.syntax());
-    let module =
-        hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src })?;
+    let module = hir::source_binder::module_from_child_node(db, file_id, module.syntax())?;
 
     let path = module.path_to_root(db).into_iter().rev().filter_map(|it| it.name(db)).join("::");
     Some(Runnable { range, kind: RunnableKind::TestMod { path } })
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index e2355aff9a..0158f9b8ad 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -212,7 +212,7 @@ fn opt_visibility(p: &mut Parser) -> bool {
         // fn foo() { crate::foo(); }
         T![crate] if !p.nth_at(1, T![::]) => {
             let m = p.start();
-            p.bump(T![crate]);
+            p.bump_any();
             m.complete(p, VISIBILITY);
         }
         _ => return false,
@@ -223,7 +223,7 @@ fn opt_visibility(p: &mut Parser) -> bool {
 fn opt_alias(p: &mut Parser) {
     if p.at(T![as]) {
         let m = p.start();
-        p.bump(T![as]);
+        p.bump_any();
         if !p.eat(T![_]) {
             name(p);
         }
@@ -234,7 +234,7 @@ fn opt_alias(p: &mut Parser) {
 fn abi(p: &mut Parser) {
     assert!(p.at(T![extern]));
     let abi = p.start();
-    p.bump(T![extern]);
+    p.bump_any();
     match p.current() {
         STRING | RAW_STRING => p.bump_any(),
         _ => (),
@@ -257,7 +257,7 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool {
 fn name_r(p: &mut Parser, recovery: TokenSet) {
     if p.at(IDENT) {
         let m = p.start();
-        p.bump(IDENT);
+        p.bump_any();
         m.complete(p, NAME);
     } else {
         p.err_recover("expected a name", recovery);
@@ -271,11 +271,11 @@ fn name(p: &mut Parser) {
 fn name_ref(p: &mut Parser) {
     if p.at(IDENT) {
         let m = p.start();
-        p.bump(IDENT);
+        p.bump_any();
         m.complete(p, NAME_REF);
     } else if p.at(T![self]) {
         let m = p.start();
-        p.bump(T![self]);
+        p.bump_any();
         m.complete(p, T![self]);
     } else {
         p.err_and_bump("expected identifier");
@@ -296,7 +296,7 @@ fn error_block(p: &mut Parser, message: &str) {
     assert!(p.at(T!['{']));
     let m = p.start();
     p.error(message);
-    p.bump(T!['{']);
+    p.bump_any();
     expressions::expr_block_contents(p);
     p.eat(T!['}']);
     m.complete(p, ERROR);
diff --git a/crates/ra_parser/src/grammar/attributes.rs b/crates/ra_parser/src/grammar/attributes.rs
index 1cfd301b5d..81a363a579 100644
--- a/crates/ra_parser/src/grammar/attributes.rs
+++ b/crates/ra_parser/src/grammar/attributes.rs
@@ -15,11 +15,11 @@ pub(super) fn outer_attributes(p: &mut Parser) {
 fn attribute(p: &mut Parser, inner: bool) {
     let attr = p.start();
     assert!(p.at(T![#]));
-    p.bump(T![#]);
+    p.bump_any();
 
     if inner {
         assert!(p.at(T![!]));
-        p.bump(T![!]);
+        p.bump_any();
     }
 
     if p.at(T!['[']) {
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index 80b085280d..1dd9a586c7 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -43,7 +43,7 @@ pub(crate) fn block(p: &mut Parser) {
 pub(crate) fn naked_block(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     expr_block_contents(p);
     p.expect(T!['}']);
     m.complete(p, BLOCK);
@@ -150,7 +150,7 @@ pub(super) fn stmt(p: &mut Parser, with_semi: StmtWithSemi) {
     // }
     fn let_stmt(p: &mut Parser, m: Marker, with_semi: StmtWithSemi) {
         assert!(p.at(T![let]));
-        p.bump(T![let]);
+        p.bump_any();
         patterns::pattern(p);
         if p.at(T![:]) {
             types::ascription(p);
@@ -195,7 +195,7 @@ pub(crate) fn expr_block_contents(p: &mut Parser) {
         // }
 
         if p.at(T![;]) {
-            p.bump(T![;]);
+            p.bump_any();
             continue;
         }
 
@@ -297,7 +297,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)>
         // }
         T![&] => {
             m = p.start();
-            p.bump(T![&]);
+            p.bump_any();
             p.eat(T![mut]);
             REF_EXPR
         }
@@ -438,7 +438,7 @@ fn call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(T!['[']));
     let m = lhs.precede(p);
-    p.bump(T!['[']);
+    p.bump_any();
     expr(p);
     p.expect(T![']']);
     m.complete(p, INDEX_EXPR)
@@ -478,7 +478,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(T![.]));
     let m = lhs.precede(p);
-    p.bump(T![.]);
+    p.bump_any();
     if p.at(IDENT) || p.at(INT_NUMBER) {
         name_ref_or_index(p)
     } else if p.at(FLOAT_NUMBER) {
@@ -497,7 +497,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(T![?]));
     let m = lhs.precede(p);
-    p.bump(T![?]);
+    p.bump_any();
     m.complete(p, TRY_EXPR)
 }
 
@@ -511,7 +511,7 @@ fn try_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(T![as]));
     let m = lhs.precede(p);
-    p.bump(T![as]);
+    p.bump_any();
     // Use type_no_bounds(), because cast expressions are not
     // allowed to have bounds.
     types::type_no_bounds(p);
@@ -521,7 +521,7 @@ fn cast_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 fn arg_list(p: &mut Parser) {
     assert!(p.at(T!['(']));
     let m = p.start();
-    p.bump(T!['(']);
+    p.bump_any();
     while !p.at(T![')']) && !p.at(EOF) {
         if !p.at_ts(EXPR_FIRST) {
             p.error("expected expression");
@@ -570,7 +570,7 @@ fn path_expr(p: &mut Parser, r: Restrictions) -> (CompletedMarker, BlockLike) {
 pub(crate) fn record_field_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(EOF) && !p.at(T!['}']) {
         match p.current() {
             // test record_literal_field_with_attr
diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs
index 6c7fdc2cd4..6e295fbf93 100644
--- a/crates/ra_parser/src/grammar/expressions/atom.rs
+++ b/crates/ra_parser/src/grammar/expressions/atom.rs
@@ -101,14 +101,14 @@ pub(super) fn atom_expr(p: &mut Parser, r: Restrictions) -> Option<(CompletedMar
         }
         T![async] if la == T!['{'] || (la == T![move] && p.nth(2) == T!['{']) => {
             let m = p.start();
-            p.bump(T![async]);
+            p.bump_any();
             p.eat(T![move]);
             block_expr(p, Some(m))
         }
         T![match] => match_expr(p),
         T![unsafe] if la == T!['{'] => {
             let m = p.start();
-            p.bump(T![unsafe]);
+            p.bump_any();
             block_expr(p, Some(m))
         }
         T!['{'] => {
@@ -180,7 +180,7 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
 fn array_expr(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T!['[']));
     let m = p.start();
-    p.bump(T!['[']);
+    p.bump_any();
     if p.eat(T![']']) {
         return m.complete(p, ARRAY_EXPR);
     }
@@ -262,11 +262,11 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker {
 fn if_expr(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![if]));
     let m = p.start();
-    p.bump(T![if]);
+    p.bump_any();
     cond(p);
     block(p);
     if p.at(T![else]) {
-        p.bump(T![else]);
+        p.bump_any();
         if p.at(T![if]) {
             if_expr(p);
         } else {
@@ -285,7 +285,7 @@ fn if_expr(p: &mut Parser) -> CompletedMarker {
 fn label(p: &mut Parser) {
     assert!(p.at(LIFETIME) && p.nth(1) == T![:]);
     let m = p.start();
-    p.bump(LIFETIME);
+    p.bump_any();
     p.bump_any();
     m.complete(p, LABEL);
 }
@@ -297,7 +297,7 @@ fn label(p: &mut Parser) {
 fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     assert!(p.at(T![loop]));
     let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![loop]);
+    p.bump_any();
     block(p);
     m.complete(p, LOOP_EXPR)
 }
@@ -310,7 +310,7 @@ fn loop_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
 fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     assert!(p.at(T![while]));
     let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![while]);
+    p.bump_any();
     cond(p);
     block(p);
     m.complete(p, WHILE_EXPR)
@@ -323,7 +323,7 @@ fn while_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
 fn for_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     assert!(p.at(T![for]));
     let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![for]);
+    p.bump_any();
     patterns::pattern(p);
     p.expect(T![in]);
     expr_no_struct(p);
@@ -357,7 +357,7 @@ fn cond(p: &mut Parser) {
 fn match_expr(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![match]));
     let m = p.start();
-    p.bump(T![match]);
+    p.bump_any();
     expr_no_struct(p);
     if p.at(T!['{']) {
         match_arm_list(p);
@@ -453,7 +453,7 @@ fn match_arm(p: &mut Parser) -> BlockLike {
 fn match_guard(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![if]));
     let m = p.start();
-    p.bump(T![if]);
+    p.bump_any();
     expr(p);
     m.complete(p, MATCH_GUARD)
 }
@@ -479,7 +479,7 @@ pub(super) fn block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
 fn return_expr(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![return]));
     let m = p.start();
-    p.bump(T![return]);
+    p.bump_any();
     if p.at_ts(EXPR_FIRST) {
         expr(p);
     }
@@ -496,7 +496,7 @@ fn return_expr(p: &mut Parser) -> CompletedMarker {
 fn continue_expr(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![continue]));
     let m = p.start();
-    p.bump(T![continue]);
+    p.bump_any();
     p.eat(LIFETIME);
     m.complete(p, CONTINUE_EXPR)
 }
@@ -513,7 +513,7 @@ fn continue_expr(p: &mut Parser) -> CompletedMarker {
 fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
     assert!(p.at(T![break]));
     let m = p.start();
-    p.bump(T![break]);
+    p.bump_any();
     p.eat(LIFETIME);
     // test break_ambiguity
     // fn foo(){
@@ -535,7 +535,7 @@ fn break_expr(p: &mut Parser, r: Restrictions) -> CompletedMarker {
 fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     assert!(p.at(T![try]));
     let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![try]);
+    p.bump_any();
     block(p);
     m.complete(p, TRY_EXPR)
 }
@@ -549,7 +549,7 @@ fn try_block_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
 fn box_expr(p: &mut Parser, m: Option<Marker>) -> CompletedMarker {
     assert!(p.at(T![box]));
     let m = m.unwrap_or_else(|| p.start());
-    p.bump(T![box]);
+    p.bump_any();
     if p.at_ts(EXPR_FIRST) {
         expr(p);
     }
diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs
index 4c67a5c2e2..4dd80d4431 100644
--- a/crates/ra_parser/src/grammar/items.rs
+++ b/crates/ra_parser/src/grammar/items.rs
@@ -64,7 +64,7 @@ pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemF
         } else if p.at(T!['}']) && !stop_on_r_curly {
             let e = p.start();
             p.error("unmatched `}`");
-            p.bump(T!['}']);
+            p.bump_any();
             e.complete(p, ERROR);
         } else if !p.at(EOF) && !p.at(T!['}']) {
             p.err_and_bump("expected an item");
@@ -276,9 +276,9 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
 
 fn extern_crate_item(p: &mut Parser, m: Marker) {
     assert!(p.at(T![extern]));
-    p.bump(T![extern]);
+    p.bump_any();
     assert!(p.at(T![crate]));
-    p.bump(T![crate]);
+    p.bump_any();
     name_ref(p);
     opt_alias(p);
     p.expect(T![;]);
@@ -288,7 +288,7 @@ fn extern_crate_item(p: &mut Parser, m: Marker) {
 pub(crate) fn extern_item_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     mod_contents(p, true);
     p.expect(T!['}']);
     m.complete(p, EXTERN_ITEM_LIST);
@@ -296,7 +296,7 @@ pub(crate) fn extern_item_list(p: &mut Parser) {
 
 fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
     assert!(p.at(T![fn]));
-    p.bump(T![fn]);
+    p.bump_any();
 
     name_r(p, ITEM_RECOVERY_SET);
     // test function_type_params
@@ -323,7 +323,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
     // test fn_decl
     // trait T { fn foo(); }
     if p.at(T![;]) {
-        p.bump(T![;]);
+        p.bump_any();
     } else {
         expressions::block(p)
     }
@@ -333,7 +333,7 @@ fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
 // type Foo = Bar;
 fn type_def(p: &mut Parser, m: Marker) {
     assert!(p.at(T![type]));
-    p.bump(T![type]);
+    p.bump_any();
 
     name(p);
 
@@ -357,7 +357,7 @@ fn type_def(p: &mut Parser, m: Marker) {
 
 pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
     assert!(p.at(T![mod]));
-    p.bump(T![mod]);
+    p.bump_any();
 
     name(p);
     if p.at(T!['{']) {
@@ -371,7 +371,7 @@ pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
 pub(crate) fn mod_item_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     mod_contents(p, true);
     p.expect(T!['}']);
     m.complete(p, ITEM_LIST);
diff --git a/crates/ra_parser/src/grammar/items/consts.rs b/crates/ra_parser/src/grammar/items/consts.rs
index 310260689e..63e0e6e0c0 100644
--- a/crates/ra_parser/src/grammar/items/consts.rs
+++ b/crates/ra_parser/src/grammar/items/consts.rs
@@ -10,7 +10,7 @@ pub(super) fn const_def(p: &mut Parser, m: Marker) {
 
 fn const_or_static(p: &mut Parser, m: Marker, kw: SyntaxKind, def: SyntaxKind) {
     assert!(p.at(kw));
-    p.bump(kw);
+    p.bump_any();
     p.eat(T![mut]); // FIXME: validator to forbid const mut
 
     // Allow `_` in place of an identifier in a `const`.
diff --git a/crates/ra_parser/src/grammar/items/nominal.rs b/crates/ra_parser/src/grammar/items/nominal.rs
index bede3b6927..460acd65eb 100644
--- a/crates/ra_parser/src/grammar/items/nominal.rs
+++ b/crates/ra_parser/src/grammar/items/nominal.rs
@@ -11,7 +11,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
             type_params::opt_where_clause(p);
             match p.current() {
                 T![;] => {
-                    p.bump(T![;]);
+                    p.bump_any();
                 }
                 T!['{'] => record_field_def_list(p),
                 _ => {
@@ -21,7 +21,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
             }
         }
         T![;] if kind == T![struct] => {
-            p.bump(T![;]);
+            p.bump_any();
         }
         T!['{'] => record_field_def_list(p),
         T!['('] if kind == T![struct] => {
@@ -44,7 +44,7 @@ pub(super) fn struct_def(p: &mut Parser, m: Marker, kind: SyntaxKind) {
 
 pub(super) fn enum_def(p: &mut Parser, m: Marker) {
     assert!(p.at(T![enum]));
-    p.bump(T![enum]);
+    p.bump_any();
     name_r(p, ITEM_RECOVERY_SET);
     type_params::opt_type_param_list(p);
     type_params::opt_where_clause(p);
@@ -59,7 +59,7 @@ pub(super) fn enum_def(p: &mut Parser, m: Marker) {
 pub(crate) fn enum_variant_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(EOF) && !p.at(T!['}']) {
         if p.at(T!['{']) {
             error_block(p, "expected enum variant");
@@ -73,7 +73,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
                 T!['{'] => record_field_def_list(p),
                 T!['('] => tuple_field_def_list(p),
                 T![=] => {
-                    p.bump(T![=]);
+                    p.bump_any();
                     expressions::expr(p);
                 }
                 _ => (),
@@ -94,7 +94,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
 pub(crate) fn record_field_def_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(T!['}']) && !p.at(EOF) {
         if p.at(T!['{']) {
             error_block(p, "expected field");
diff --git a/crates/ra_parser/src/grammar/items/traits.rs b/crates/ra_parser/src/grammar/items/traits.rs
index 3742fd197f..b49221a4be 100644
--- a/crates/ra_parser/src/grammar/items/traits.rs
+++ b/crates/ra_parser/src/grammar/items/traits.rs
@@ -5,7 +5,7 @@ use super::*;
 // trait X<U: Debug + Display>: Hash + Clone where U: Copy {}
 pub(super) fn trait_def(p: &mut Parser) {
     assert!(p.at(T![trait]));
-    p.bump(T![trait]);
+    p.bump_any();
     name_r(p, ITEM_RECOVERY_SET);
     type_params::opt_type_param_list(p);
     if p.at(T![:]) {
@@ -29,7 +29,7 @@ pub(super) fn trait_def(p: &mut Parser) {
 pub(crate) fn trait_item_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(EOF) && !p.at(T!['}']) {
         if p.at(T!['{']) {
             error_block(p, "expected an item");
@@ -45,7 +45,7 @@ pub(crate) fn trait_item_list(p: &mut Parser) {
 // impl Foo {}
 pub(super) fn impl_block(p: &mut Parser) {
     assert!(p.at(T![impl]));
-    p.bump(T![impl]);
+    p.bump_any();
     if choose_type_params_over_qpath(p) {
         type_params::opt_type_param_list(p);
     }
@@ -78,7 +78,7 @@ pub(super) fn impl_block(p: &mut Parser) {
 pub(crate) fn impl_item_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     // test impl_inner_attributes
     // enum F{}
     // impl F {
diff --git a/crates/ra_parser/src/grammar/items/use_item.rs b/crates/ra_parser/src/grammar/items/use_item.rs
index 2af2ad3157..f28f522b83 100644
--- a/crates/ra_parser/src/grammar/items/use_item.rs
+++ b/crates/ra_parser/src/grammar/items/use_item.rs
@@ -2,7 +2,7 @@ use super::*;
 
 pub(super) fn use_item(p: &mut Parser, m: Marker) {
     assert!(p.at(T![use]));
-    p.bump(T![use]);
+    p.bump_any();
     use_tree(p);
     p.expect(T![;]);
     m.complete(p, USE_ITEM);
@@ -84,7 +84,7 @@ fn use_tree(p: &mut Parser) {
                     p.bump(T![::]);
                     match p.current() {
                         T![*] => {
-                            p.bump(T![*]);
+                            p.bump_any();
                         }
                         // test use_tree_list_after_path
                         // use crate::{Item};
@@ -114,7 +114,7 @@ fn use_tree(p: &mut Parser) {
 pub(crate) fn use_tree_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(EOF) && !p.at(T!['}']) {
         use_tree(p);
         if !p.at(T!['}']) {
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index efc3292438..5893b22fdc 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -39,7 +39,7 @@ fn list_(p: &mut Parser, flavor: Flavor) {
     let (bra, ket) = if flavor.type_required() { (T!['('], T![')']) } else { (T![|], T![|]) };
     assert!(p.at(bra));
     let m = p.start();
-    p.bump(bra);
+    p.bump_any();
     if flavor.type_required() {
         // test self_param_outer_attr
         // fn f(#[must_use] self) {}
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs
index a4ffd69601..919b0f37db 100644
--- a/crates/ra_parser/src/grammar/patterns.rs
+++ b/crates/ra_parser/src/grammar/patterns.rs
@@ -106,7 +106,7 @@ fn literal_pat(p: &mut Parser) -> CompletedMarker {
     assert!(is_literal_pat_start(p));
     let m = p.start();
     if p.at(T![-]) {
-        p.bump(T![-]);
+        p.bump_any();
     }
     expressions::literal(p);
     m.complete(p, LITERAL_PAT)
@@ -146,7 +146,7 @@ fn path_pat(p: &mut Parser) -> CompletedMarker {
 // }
 fn tuple_pat_fields(p: &mut Parser) {
     assert!(p.at(T!['(']));
-    p.bump(T!['(']);
+    p.bump_any();
     pat_list(p, T![')']);
     p.expect(T![')']);
 }
@@ -161,7 +161,7 @@ fn tuple_pat_fields(p: &mut Parser) {
 fn record_field_pat_list(p: &mut Parser) {
     assert!(p.at(T!['{']));
     let m = p.start();
-    p.bump(T!['{']);
+    p.bump_any();
     while !p.at(EOF) && !p.at(T!['}']) {
         match p.current() {
             // A trailing `..` is *not* treated as a DOT_DOT_PAT.
@@ -200,7 +200,7 @@ fn record_field_pat(p: &mut Parser) {
 fn placeholder_pat(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![_]));
     let m = p.start();
-    p.bump(T![_]);
+    p.bump_any();
     m.complete(p, PLACEHOLDER_PAT)
 }
 
@@ -245,7 +245,7 @@ fn dot_dot_pat(p: &mut Parser) -> CompletedMarker {
 fn ref_pat(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![&]));
     let m = p.start();
-    p.bump(T![&]);
+    p.bump_any();
     p.eat(T![mut]);
     pattern(p);
     m.complete(p, REF_PAT)
@@ -269,7 +269,7 @@ fn tuple_pat(p: &mut Parser) -> CompletedMarker {
 fn slice_pat(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T!['[']));
     let m = p.start();
-    p.bump(T!['[']);
+    p.bump_any();
     pat_list(p, T![']']);
     p.expect(T![']']);
     m.complete(p, SLICE_PAT)
@@ -318,7 +318,7 @@ fn bind_pat(p: &mut Parser, with_at: bool) -> CompletedMarker {
 fn box_pat(p: &mut Parser) -> CompletedMarker {
     assert!(p.at(T![box]));
     let m = p.start();
-    p.bump(T![box]);
+    p.bump_any();
     pattern(p);
     m.complete(p, BOX_PAT)
 }
diff --git a/crates/ra_parser/src/grammar/type_args.rs b/crates/ra_parser/src/grammar/type_args.rs
index 8e97fe03c0..edc7d4ff2b 100644
--- a/crates/ra_parser/src/grammar/type_args.rs
+++ b/crates/ra_parser/src/grammar/type_args.rs
@@ -29,7 +29,7 @@ fn type_arg(p: &mut Parser) {
     let m = p.start();
     match p.current() {
         LIFETIME => {
-            p.bump(LIFETIME);
+            p.bump_any();
             m.complete(p, LIFETIME_ARG);
         }
         // test associated_type_bounds
diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs
index 7071c70eaf..31d709d811 100644
--- a/crates/ra_parser/src/grammar/type_params.rs
+++ b/crates/ra_parser/src/grammar/type_params.rs
@@ -10,7 +10,7 @@ pub(super) fn opt_type_param_list(p: &mut Parser) {
 fn type_param_list(p: &mut Parser) {
     assert!(p.at(T![<]));
     let m = p.start();
-    p.bump(T![<]);
+    p.bump_any();
 
     while !p.at(EOF) && !p.at(T![>]) {
         let m = p.start();
@@ -38,7 +38,7 @@ fn type_param_list(p: &mut Parser) {
 
 fn lifetime_param(p: &mut Parser, m: Marker) {
     assert!(p.at(LIFETIME));
-    p.bump(LIFETIME);
+    p.bump_any();
     if p.at(T![:]) {
         lifetime_bounds(p);
     }
@@ -54,7 +54,7 @@ fn type_param(p: &mut Parser, m: Marker) {
     // test type_param_default
     // struct S<T = i32>;
     if p.at(T![=]) {
-        p.bump(T![=]);
+        p.bump_any();
         types::type_(p)
     }
     m.complete(p, TYPE_PARAM);
@@ -64,15 +64,15 @@ fn type_param(p: &mut Parser, m: Marker) {
 // struct S<T: 'a + ?Sized + (Copy)>;
 pub(super) fn bounds(p: &mut Parser) {
     assert!(p.at(T![:]));
-    p.bump(T![:]);
+    p.bump_any();
     bounds_without_colon(p);
 }
 
 fn lifetime_bounds(p: &mut Parser) {
     assert!(p.at(T![:]));
-    p.bump(T![:]);
+    p.bump_any();
     while p.at(LIFETIME) {
-        p.bump(LIFETIME);
+        p.bump_any();
         if !p.eat(T![+]) {
             break;
         }
@@ -99,7 +99,7 @@ fn type_bound(p: &mut Parser) -> bool {
     let has_paren = p.eat(T!['(']);
     p.eat(T![?]);
     match p.current() {
-        LIFETIME => p.bump(LIFETIME),
+        LIFETIME => p.bump_any(),
         T![for] => types::for_type(p),
         _ if paths::is_use_path_start(p) => types::path_type_(p, false),
         _ => {
@@ -128,7 +128,7 @@ pub(super) fn opt_where_clause(p: &mut Parser) {
         return;
     }
     let m = p.start();
-    p.bump(T![where]);
+    p.bump_any();
 
     while is_where_predicate(p) {
         where_predicate(p);
@@ -166,7 +166,7 @@ fn where_predicate(p: &mut Parser) {
     let m = p.start();
     match p.current() {
         LIFETIME => {
-            p.bump(LIFETIME);
+            p.bump_any();
             if p.at(T![:]) {
                 bounds(p);
             } else {
diff --git a/crates/ra_parser/src/grammar/types.rs b/crates/ra_parser/src/grammar/types.rs
index bd3829f418..a5a5b6d734 100644
--- a/crates/ra_parser/src/grammar/types.rs
+++ b/crates/ra_parser/src/grammar/types.rs
@@ -44,7 +44,7 @@ pub(super) fn ascription(p: &mut Parser) {
 fn paren_or_tuple_type(p: &mut Parser) {
     assert!(p.at(T!['(']));
     let m = p.start();
-    p.bump(T!['(']);
+    p.bump_any();
     let mut n_types: u32 = 0;
     let mut trailing_comma: bool = false;
     while !p.at(EOF) && !p.at(T![')']) {
@@ -79,14 +79,14 @@ fn paren_or_tuple_type(p: &mut Parser) {
 fn never_type(p: &mut Parser) {
     assert!(p.at(T![!]));
     let m = p.start();
-    p.bump(T![!]);
+    p.bump_any();
     m.complete(p, NEVER_TYPE);
 }
 
 fn pointer_type(p: &mut Parser) {
     assert!(p.at(T![*]));
     let m = p.start();
-    p.bump(T![*]);
+    p.bump_any();
 
     match p.current() {
         // test pointer_type_mut
@@ -110,21 +110,21 @@ fn pointer_type(p: &mut Parser) {
 fn array_or_slice_type(p: &mut Parser) {
     assert!(p.at(T!['[']));
     let m = p.start();
-    p.bump(T!['[']);
+    p.bump_any();
 
     type_(p);
     let kind = match p.current() {
         // test slice_type
         // type T = [()];
         T![']'] => {
-            p.bump(T![']']);
+            p.bump_any();
             SLICE_TYPE
         }
 
         // test array_type
         // type T = [(); 92];
         T![;] => {
-            p.bump(T![;]);
+            p.bump_any();
             expressions::expr(p);
             p.expect(T![']']);
             ARRAY_TYPE
@@ -146,7 +146,7 @@ fn array_or_slice_type(p: &mut Parser) {
 fn reference_type(p: &mut Parser) {
     assert!(p.at(T![&]));
     let m = p.start();
-    p.bump(T![&]);
+    p.bump_any();
     p.eat(LIFETIME);
     p.eat(T![mut]);
     type_no_bounds(p);
@@ -158,7 +158,7 @@ fn reference_type(p: &mut Parser) {
 fn placeholder_type(p: &mut Parser) {
     assert!(p.at(T![_]));
     let m = p.start();
-    p.bump(T![_]);
+    p.bump_any();
     m.complete(p, PLACEHOLDER_TYPE);
 }
 
@@ -193,7 +193,7 @@ fn fn_pointer_type(p: &mut Parser) {
 
 pub(super) fn for_binder(p: &mut Parser) {
     assert!(p.at(T![for]));
-    p.bump(T![for]);
+    p.bump_any();
     if p.at(T![<]) {
         type_params::opt_type_param_list(p);
     } else {
@@ -224,7 +224,7 @@ pub(super) fn for_type(p: &mut Parser) {
 fn impl_trait_type(p: &mut Parser) {
     assert!(p.at(T![impl]));
     let m = p.start();
-    p.bump(T![impl]);
+    p.bump_any();
     type_params::bounds_without_colon(p);
     m.complete(p, IMPL_TRAIT_TYPE);
 }
@@ -234,7 +234,7 @@ fn impl_trait_type(p: &mut Parser) {
 fn dyn_trait_type(p: &mut Parser) {
     assert!(p.at(T![dyn ]));
     let m = p.start();
-    p.bump(T![dyn ]);
+    p.bump_any();
     type_params::bounds_without_colon(p);
     m.complete(p, DYN_TRAIT_TYPE);
 }
@@ -256,7 +256,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
     let m = p.start();
     paths::type_path(p);
 
-    let kind = if p.at(T![!]) {
+    let kind = if p.at(T![!]) && !p.at(T![!=]) {
         items::macro_call_after_excl(p);
         MACRO_CALL
     } else {
diff --git a/docs/user/features.md b/docs/user/features.md
index 93e565315e..1034a51172 100644
--- a/docs/user/features.md
+++ b/docs/user/features.md
@@ -445,62 +445,6 @@ fn foo<T: u32, F: FnOnce(T) -> T>() {}
 fn foo<T, F>() where T: u32, F: FnOnce(T) -> T {}
 ```
 
-- Make raw string
-
-```rust
-// before:
-fn f() {
-    let s = <|>"abcd";
-}
-
-// after:
-fn f() {
-    let s = <|>r"abcd";
-}
-```
-
-- Make usual string
-
-```rust
-// before:
-fn f() {
-    let s = <|>r#"abcd"#;
-}
-
-// after:
-fn f() {
-    let s = <|>"abcd";
-}
-```
-
-- Add hash
-
-```rust
-// before:
-fn f() {
-    let s = <|>r"abcd";
-}
-
-// after:
-fn f() {
-    let s = <|>r#"abcd"#;
-}
-```
-
-- Remove hash
-
-```rust
-// before:
-fn f() {
-    let s = <|>r#"abcd"#;
-}
-
-// after:
-fn f() {
-    let s = <|>r"abcd";
-}
-```
-
 ### Magic Completions
 
 In addition to usual reference completion, rust-analyzer provides some ✨magic✨


Test patch:
diff --git a/crates/ra_hir/src/nameres/tests/incremental.rs b/crates/ra_hir/src/nameres/tests/incremental.rs
index c41862a0bd..bc721f6e0a 100644
--- a/crates/ra_hir/src/nameres/tests/incremental.rs
+++ b/crates/ra_hir/src/nameres/tests/incremental.rs
@@ -114,11 +114,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
     );
     {
         let events = db.log_executed(|| {
-            let src = crate::Source {
-                file_id: pos.file_id.into(),
-                ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
-            };
-            let module = crate::Module::from_definition(&db, src).unwrap();
+            let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
             let decls = module.declarations(&db);
             assert_eq!(decls.len(), 18);
         });
@@ -128,11 +124,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() {
 
     {
         let events = db.log_executed(|| {
-            let src = crate::Source {
-                file_id: pos.file_id.into(),
-                ast: crate::ModuleSource::new(&db, Some(pos.file_id), None),
-            };
-            let module = crate::Module::from_definition(&db, src).unwrap();
+            let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap();
             let decls = module.declarations(&db);
             assert_eq!(decls.len(), 18);
         });
diff --git a/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rs b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rs
new file mode 100644
index 0000000000..6210683cea
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.rs
@@ -0,0 +1,3 @@
+fn main() {
+    if 1.0f32.floor() as i64 != 1.0f32.floor() as i64 {}
+}
diff --git a/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.txt b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.txt
new file mode 100644
index 0000000000..4a4ad84cab
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0056_neq_in_type.txt
@@ -0,0 +1,66 @@
+SOURCE_FILE@[0; 71)
+  FN_DEF@[0; 70)
+    FN_KW@[0; 2) "fn"
+    WHITESPACE@[2; 3) " "
+    NAME@[3; 7)
+      IDENT@[3; 7) "main"
+    PARAM_LIST@[7; 9)
+      L_PAREN@[7; 8) "("
+      R_PAREN@[8; 9) ")"
+    WHITESPACE@[9; 10) " "
+    BLOCK_EXPR@[10; 70)
+      BLOCK@[10; 70)
+        L_CURLY@[10; 11) "{"
+        WHITESPACE@[11; 16) "\n    "
+        IF_EXPR@[16; 68)
+          IF_KW@[16; 18) "if"
+          WHITESPACE@[18; 19) " "
+          CONDITION@[19; 65)
+            BIN_EXPR@[19; 65)
+              CAST_EXPR@[19; 40)
+                METHOD_CALL_EXPR@[19; 33)
+                  LITERAL@[19; 25)
+                    FLOAT_NUMBER@[19; 25) "1.0f32"
+                  DOT@[25; 26) "."
+                  NAME_REF@[26; 31)
+                    IDENT@[26; 31) "floor"
+                  ARG_LIST@[31; 33)
+                    L_PAREN@[31; 32) "("
+                    R_PAREN@[32; 33) ")"
+                WHITESPACE@[33; 34) " "
+                AS_KW@[34; 36) "as"
+                WHITESPACE@[36; 37) " "
+                PATH_TYPE@[37; 40)
+                  PATH@[37; 40)
+                    PATH_SEGMENT@[37; 40)
+                      NAME_REF@[37; 40)
+                        IDENT@[37; 40) "i64"
+              WHITESPACE@[40; 41) " "
+              NEQ@[41; 43) "!="
+              WHITESPACE@[43; 44) " "
+              CAST_EXPR@[44; 65)
+                METHOD_CALL_EXPR@[44; 58)
+                  LITERAL@[44; 50)
+                    FLOAT_NUMBER@[44; 50) "1.0f32"
+                  DOT@[50; 51) "."
+                  NAME_REF@[51; 56)
+                    IDENT@[51; 56) "floor"
+                  ARG_LIST@[56; 58)
+                    L_PAREN@[56; 57) "("
+                    R_PAREN@[57; 58) ")"
+                WHITESPACE@[58; 59) " "
+                AS_KW@[59; 61) "as"
+                WHITESPACE@[61; 62) " "
+                PATH_TYPE@[62; 65)
+                  PATH@[62; 65)
+                    PATH_SEGMENT@[62; 65)
+                      NAME_REF@[62; 65)
+                        IDENT@[62; 65) "i64"
+          WHITESPACE@[65; 66) " "
+          BLOCK_EXPR@[66; 68)
+            BLOCK@[66; 68)
+              L_CURLY@[66; 67) "{"
+              R_CURLY@[67; 68) "}"
+        WHITESPACE@[68; 69) "\n"
+        R_CURLY@[69; 70) "}"
+  WHITESPACE@[70; 71) "\n"