From 89fbd0db02693eabb82f0b189a08fe0ebe924550 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 28 Nov 2019 13:41:58 +0800 Subject: [PATCH 001/312] Derive Hash for TokenTrees --- crates/ra_tt/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 20c251ff45..4c00b8f302 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -33,14 +33,14 @@ impl TokenId { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TokenTree { Leaf(Leaf), Subtree(Subtree), } impl_froms!(TokenTree: Leaf, Subtree); -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum Leaf { Literal(Literal), Punct(Punct), @@ -48,13 +48,13 @@ pub enum Leaf { } impl_froms!(Leaf: Literal, Punct, Ident); -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Subtree { pub delimiter: Delimiter, pub token_trees: Vec, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum Delimiter { Parenthesis, Brace, @@ -62,24 +62,24 @@ pub enum Delimiter { None, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Literal { pub text: SmolStr, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Punct { pub char: char, pub spacing: Spacing, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Spacing { Alone, Joint, } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Ident { pub text: SmolStr, pub id: TokenId, From ccd1b0800a5de5e046e6e9a4b6f49030c1ce3639 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 28 Nov 2019 12:50:26 +0300 Subject: [PATCH 002/312] Rename Source -> InFile --- crates/ra_assists/src/assist_ctx.rs | 4 +- crates/ra_assists/src/assists/add_new.rs | 6 +- crates/ra_hir/src/code_model.rs | 6 +- crates/ra_hir/src/code_model/src.rs | 36 +++++------ crates/ra_hir/src/from_source.rs | 62 +++++++++---------- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 28 ++++----- crates/ra_hir_def/src/adt.rs | 6 +- crates/ra_hir_def/src/attr.rs | 6 +- crates/ra_hir_def/src/body.rs | 14 ++--- crates/ra_hir_def/src/body/scope.rs | 6 +- crates/ra_hir_def/src/diagnostics.rs | 6 +- crates/ra_hir_def/src/lib.rs | 26 ++++---- crates/ra_hir_def/src/nameres.rs | 14 ++--- crates/ra_hir_def/src/nameres/raw.rs | 6 +- crates/ra_hir_def/src/path.rs | 4 +- crates/ra_hir_expand/src/diagnostics.rs | 4 +- crates/ra_hir_expand/src/lib.rs | 42 ++++++------- crates/ra_hir_ty/src/diagnostics.rs | 14 ++--- crates/ra_hir_ty/src/tests.rs | 4 +- crates/ra_ide/src/call_info.rs | 2 +- .../src/completion/completion_context.rs | 4 +- crates/ra_ide/src/diagnostics.rs | 2 +- .../ra_ide/src/display/navigation_target.rs | 4 +- crates/ra_ide/src/expand.rs | 8 +-- crates/ra_ide/src/expand_macro.rs | 8 +-- crates/ra_ide/src/goto_definition.rs | 8 +-- crates/ra_ide/src/hover.rs | 2 +- crates/ra_ide/src/impls.rs | 10 +-- crates/ra_ide/src/inlay_hints.rs | 2 +- crates/ra_ide/src/parent_module.rs | 4 +- crates/ra_ide/src/references.rs | 8 +-- crates/ra_ide/src/references/classify.rs | 6 +- crates/ra_ide/src/references/rename.rs | 2 +- crates/ra_ide/src/runnables.rs | 6 +- crates/ra_ide/src/syntax_highlighting.rs | 6 +- 36 files changed, 189 insertions(+), 189 deletions(-) diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 0ea84d5488..993aebc478 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -1,5 +1,5 @@ //! This module defines `AssistCtx` -- the API surface that is exposed to assists. -use hir::{db::HirDatabase, SourceAnalyzer}; +use hir::{db::HirDatabase, InFile, SourceAnalyzer}; use ra_db::FileRange; use ra_fmt::{leading_indent, reindent}; use ra_syntax::{ @@ -117,7 +117,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { node: &SyntaxNode, offset: Option, ) -> SourceAnalyzer { - SourceAnalyzer::new(self.db, hir::Source::new(self.frange.file_id.into(), node), offset) + SourceAnalyzer::new(self.db, InFile::new(self.frange.file_id.into(), node), offset) } pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index 8f68bd5fb1..f977547fb9 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -1,5 +1,5 @@ use format_buf::format; -use hir::{db::HirDatabase, FromSource}; +use hir::{db::HirDatabase, FromSource, InFile}; use join_to_string::join; use ra_syntax::{ ast::{ @@ -141,7 +141,7 @@ fn find_struct_impl( })?; let struct_ty = { - let src = hir::Source { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; + let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; hir::Struct::from_source(db, src).unwrap().ty(db) }; @@ -152,7 +152,7 @@ fn find_struct_impl( return false; } - let src = hir::Source { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; + let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; let blk = hir::ImplBlock::from_source(db, src).unwrap(); let same_ty = blk.target_ty(db) == struct_ty; diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 38d66c2a7c..dddac915bc 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -30,7 +30,7 @@ use crate::{ db::{DefDatabase, HirDatabase}, ty::display::HirFormatter, ty::{self, InEnvironment, InferenceResult, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk}, - CallableDef, Either, HirDisplay, Name, Source, + CallableDef, Either, HirDisplay, InFile, Name, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -118,7 +118,7 @@ impl ModuleSource { } } - pub fn from_child_node(db: &impl DefDatabase, child: Source<&SyntaxNode>) -> ModuleSource { + pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource { if let Some(m) = child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { @@ -901,7 +901,7 @@ impl Local { Type { krate, ty: InEnvironment { value: ty, environment } } } - pub fn source(self, db: &impl HirDatabase) -> Source> { + pub fn source(self, db: &impl HirDatabase) -> InFile> { let (_body, source_map) = db.body_with_source_map(self.parent.into()); let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... let root = src.file_syntax(db); diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index bf3ee08341..6fd4e79871 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -9,18 +9,18 @@ use crate::{ Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, }; -pub use hir_expand::Source; +pub use hir_expand::InFile; pub trait HasSource { type Ast; - fn source(self, db: &impl DefDatabase) -> Source; + fn source(self, db: &impl DefDatabase) -> InFile; } /// NB: Module is !HasSource, because it has two source nodes at the same time: /// definition and declaration. impl Module { /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. - pub fn definition_source(self, db: &impl DefDatabase) -> Source { + pub fn definition_source(self, db: &impl DefDatabase) -> InFile { let def_map = db.crate_def_map(self.id.krate); let src = def_map[self.id.local_id].definition_source(db); src.map(|it| match it { @@ -31,7 +31,7 @@ impl Module { /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. /// `None` for the crate root. - pub fn declaration_source(self, db: &impl DefDatabase) -> Option> { + pub fn declaration_source(self, db: &impl DefDatabase) -> Option> { let def_map = db.crate_def_map(self.id.krate); def_map[self.id.local_id].declaration_source(db) } @@ -39,7 +39,7 @@ impl Module { impl HasSource for StructField { type Ast = FieldSource; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { let var = VariantId::from(self.parent); let src = var.child_source(db); src.map(|it| match it[self.id].clone() { @@ -50,67 +50,67 @@ impl HasSource for StructField { } impl HasSource for Struct { type Ast = ast::StructDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.source(db) } } impl HasSource for Union { type Ast = ast::UnionDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.source(db) } } impl HasSource for Enum { type Ast = ast::EnumDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.source(db) } } impl HasSource for EnumVariant { type Ast = ast::EnumVariant; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.parent.id.child_source(db).map(|map| map[self.id].clone()) } } impl HasSource for Function { type Ast = ast::FnDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.lookup(db).source(db) } } impl HasSource for Const { type Ast = ast::ConstDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.lookup(db).source(db) } } impl HasSource for Static { type Ast = ast::StaticDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.lookup(db).source(db) } } impl HasSource for Trait { type Ast = ast::TraitDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.source(db) } } impl HasSource for TypeAlias { type Ast = ast::TypeAliasDef; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.lookup(db).source(db) } } impl HasSource for MacroDef { type Ast = ast::MacroCall; - fn source(self, db: &impl DefDatabase) -> Source { - Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } + fn source(self, db: &impl DefDatabase) -> InFile { + InFile { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } } } impl HasSource for ImplBlock { type Ast = ast::ImplBlock; - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { self.id.source(db) } } @@ -118,7 +118,7 @@ impl HasSource for Import { type Ast = Either; /// Returns the syntax of the last path segment corresponding to this import - fn source(self, db: &impl DefDatabase) -> Source { + fn source(self, db: &impl DefDatabase) -> InFile { let src = self.parent.definition_source(db); let (_, source_map) = db.raw_items_with_source_map(src.file_id); let root = db.parse_or_expand(src.file_id).unwrap(); diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 9f7c22b211..82bf641dca 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -10,46 +10,46 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, - Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct, StructField, Trait, + InFile, Local, MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef, }; pub trait FromSource: Sized { type Ast; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option; + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option; } impl FromSource for Struct { type Ast = ast::StructDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let id = from_source(db, src)?; Some(Struct { id }) } } impl FromSource for Union { type Ast = ast::UnionDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { 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) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { 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) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { 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) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { Container::Trait(it) => it.items(db), Container::ImplBlock(it) => it.items(db), @@ -76,7 +76,7 @@ impl FromSource for Function { impl FromSource for Const { type Ast = ast::ConstDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { Container::Trait(it) => it.items(db), Container::ImplBlock(it) => it.items(db), @@ -102,7 +102,7 @@ impl FromSource for Const { } impl FromSource for Static { type Ast = ast::StaticDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let module = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { Container::Module(it) => it, Container::Trait(_) | Container::ImplBlock(_) => return None, @@ -120,7 +120,7 @@ impl FromSource for Static { impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { Container::Trait(it) => it.items(db), Container::ImplBlock(it) => it.items(db), @@ -147,11 +147,11 @@ impl FromSource for TypeAlias { impl FromSource for MacroDef { type Ast = ast::MacroCall; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let kind = MacroDefKind::Declarative; let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; + let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; let krate = module.krate().crate_id(); let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value)); @@ -163,7 +163,7 @@ impl FromSource for MacroDef { impl FromSource for ImplBlock { type Ast = ast::ImplBlock; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let id = from_source(db, src)?; Some(ImplBlock { id }) } @@ -171,9 +171,9 @@ impl FromSource for ImplBlock { impl FromSource for EnumVariant { type Ast = ast::EnumVariant; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let parent_enum = src.value.parent_enum(); - let src_enum = Source { file_id: src.file_id, value: parent_enum }; + let src_enum = InFile { file_id: src.file_id, value: parent_enum }; let variants = Enum::from_source(db, src_enum)?.variants(db); variants.into_iter().find(|v| same_source(&v.source(db), &src)) } @@ -181,17 +181,17 @@ impl FromSource for EnumVariant { impl FromSource for StructField { type Ast = FieldSource; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option { + fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let variant_def: VariantDef = match src.value { FieldSource::Named(ref field) => { let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; - let src = Source { file_id: src.file_id, value }; + let src = InFile { file_id: src.file_id, value }; let def = Struct::from_source(db, src)?; VariantDef::from(def) } FieldSource::Pos(ref field) => { let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; - let src = Source { file_id: src.file_id, value }; + let src = InFile { file_id: src.file_id, value }; let def = EnumVariant::from_source(db, src)?; VariantDef::from(def) } @@ -206,14 +206,14 @@ impl FromSource for StructField { } impl Local { - pub fn from_source(db: &impl HirDatabase, src: Source) -> Option { + pub fn from_source(db: &impl HirDatabase, src: InFile) -> Option { let file_id = src.file_id; let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| { let res = match_ast! { match it { - ast::ConstDef(value) => { Const::from_source(db, Source { value, file_id})?.into() }, - ast::StaticDef(value) => { Static::from_source(db, Source { value, file_id})?.into() }, - ast::FnDef(value) => { Function::from_source(db, Source { value, file_id})?.into() }, + ast::ConstDef(value) => { Const::from_source(db, InFile { value, file_id})?.into() }, + ast::StaticDef(value) => { Static::from_source(db, InFile { value, file_id})?.into() }, + ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.into() }, _ => return None, } }; @@ -227,16 +227,16 @@ impl Local { } impl Module { - pub fn from_declaration(db: &impl DefDatabase, src: Source) -> Option { + pub fn from_declaration(db: &impl DefDatabase, src: InFile) -> Option { let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast); let parent_module = match parent_declaration { Some(parent_declaration) => { - let src_parent = Source { file_id: src.file_id, value: parent_declaration }; + let src_parent = InFile { file_id: src.file_id, value: parent_declaration }; Module::from_declaration(db, src_parent) } _ => { - let src_parent = Source { + let src_parent = InFile { file_id: src.file_id, value: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), }; @@ -248,13 +248,13 @@ impl Module { parent_module.child(db, &child_name.as_name()) } - pub fn from_definition(db: &impl DefDatabase, src: Source) -> Option { + pub fn from_definition(db: &impl DefDatabase, src: InFile) -> Option { match src.value { ModuleSource::Module(ref module) => { assert!(!module.has_semi()); return Module::from_declaration( db, - Source { file_id: src.file_id, value: module.clone() }, + InFile { file_id: src.file_id, value: module.clone() }, ); } ModuleSource::SourceFile(_) => (), @@ -271,13 +271,13 @@ impl Module { } } -fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source) -> Option +fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option where N: AstNode, DEF: AstItemDef, { let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; + let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; let ctx = LocationCtx::new(db, module.id, src.file_id); let items = db.ast_id_map(src.file_id); let item_id = items.ast_id(&src.value); @@ -291,7 +291,7 @@ enum Container { } impl Container { - fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option { + fn find(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { // FIXME: this doesn't try to handle nested declarations for container in src.value.ancestors() { let res = match_ast! { @@ -322,6 +322,6 @@ impl Container { /// In general, we do not guarantee that we have exactly one instance of a /// syntax tree for each file. We probably should add such guarantee, but, for /// the time being, we will use identity-less AstPtr comparison. -fn same_source(s1: &Source, s2: &Source) -> bool { +fn same_source(s1: &InFile, s2: &InFile) -> bool { s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3c12c61f03..88d2f6e02a 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -63,5 +63,5 @@ pub use hir_def::{ type_ref::Mutability, }; pub use hir_expand::{ - either::Either, name::Name, HirFileId, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Source, + either::Either, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 76c493f1a8..1661d92a2e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -18,7 +18,7 @@ use hir_def::{ AssocItemId, DefWithBodyId, }; use hir_expand::{ - hygiene::Hygiene, name::AsName, AstId, HirFileId, MacroCallId, MacroFileKind, Source, + hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroFileKind, }; use ra_syntax::{ ast::{self, AstNode}, @@ -37,7 +37,7 @@ use crate::{ GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, }; -fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option { +fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option { match_ast! { match (node.value) { ast::Module(it) => { @@ -71,7 +71,7 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) - fn def_with_body_from_child_node( db: &impl HirDatabase, - child: Source<&SyntaxNode>, + child: InFile<&SyntaxNode>, ) -> Option { child.value.ancestors().find_map(|node| { match_ast! { @@ -141,8 +141,8 @@ impl Expansion { pub fn map_token_down( &self, db: &impl HirDatabase, - token: Source<&SyntaxToken>, - ) -> Option> { + token: InFile<&SyntaxToken>, + ) -> Option> { let exp_info = self.file_id().expansion_info(db)?; exp_info.map_token_down(token) } @@ -155,7 +155,7 @@ impl Expansion { impl SourceAnalyzer { pub fn new( db: &impl HirDatabase, - node: Source<&SyntaxNode>, + node: InFile<&SyntaxNode>, offset: Option, ) -> SourceAnalyzer { let def_with_body = def_with_body_from_child_node(db, node); @@ -192,12 +192,12 @@ impl SourceAnalyzer { } fn expr_id(&self, expr: &ast::Expr) -> Option { - let src = Source { file_id: self.file_id, value: expr }; + let src = InFile { file_id: self.file_id, value: expr }; self.body_source_map.as_ref()?.node_expr(src) } fn pat_id(&self, pat: &ast::Pat) -> Option { - let src = Source { file_id: self.file_id, value: pat }; + let src = InFile { file_id: self.file_id, value: pat }; self.body_source_map.as_ref()?.node_pat(src) } @@ -243,7 +243,7 @@ impl SourceAnalyzer { pub fn resolve_macro_call( &self, db: &impl HirDatabase, - macro_call: Source<&ast::MacroCall>, + macro_call: InFile<&ast::MacroCall>, ) -> Option { let hygiene = Hygiene::new(db, macro_call.file_id); let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?; @@ -318,7 +318,7 @@ impl SourceAnalyzer { let name = name_ref.as_name(); let source_map = self.body_source_map.as_ref()?; let scopes = self.scopes.as_ref()?; - let scope = scope_for(scopes, source_map, Source::new(self.file_id, name_ref.syntax()))?; + let scope = scope_for(scopes, source_map, InFile::new(self.file_id, name_ref.syntax()))?; let entry = scopes.resolve_name_in_scope(scope, &name)?; Some(ScopeEntryWithSyntax { name: entry.name().clone(), @@ -446,7 +446,7 @@ impl SourceAnalyzer { pub fn expand( &self, db: &impl HirDatabase, - macro_call: Source<&ast::MacroCall>, + macro_call: InFile<&ast::MacroCall>, ) -> Option { let def = self.resolve_macro_call(db, macro_call)?.id; let ast_id = AstId::new( @@ -463,19 +463,19 @@ impl SourceAnalyzer { fn scope_for( scopes: &ExprScopes, source_map: &BodySourceMap, - node: Source<&SyntaxNode>, + node: InFile<&SyntaxNode>, ) -> Option { node.value .ancestors() .filter_map(ast::Expr::cast) - .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) + .filter_map(|it| source_map.node_expr(InFile::new(node.file_id, &it))) .find_map(|it| scopes.scope_for(it)) } fn scope_for_offset( scopes: &ExprScopes, source_map: &BodySourceMap, - offset: Source, + offset: InFile, ) -> Option { scopes .scope_by_expr() diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 3666529b0c..3d21dedeee 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use hir_expand::{ either::Either, name::{AsName, Name}, - Source, + InFile, }; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; @@ -88,7 +88,7 @@ impl EnumData { impl HasChildSource for EnumId { type ChildId = LocalEnumVariantId; type Value = ast::EnumVariant; - fn child_source(&self, db: &impl DefDatabase) -> Source> { + fn child_source(&self, db: &impl DefDatabase) -> InFile> { let src = self.source(db); let mut trace = Trace::new_for_map(); lower_enum(&mut trace, &src.value); @@ -145,7 +145,7 @@ impl HasChildSource for VariantId { type ChildId = LocalStructFieldId; type Value = Either; - fn child_source(&self, db: &impl DefDatabase) -> Source> { + fn child_source(&self, db: &impl DefDatabase) -> InFile> { let src = match self { VariantId::EnumVariantId(it) => { // I don't really like the fact that we call into parent source diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index fffb22201d..83783ac7ad 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -2,7 +2,7 @@ use std::{ops, sync::Arc}; -use hir_expand::{either::Either, hygiene::Hygiene, AstId, Source}; +use hir_expand::{either::Either, hygiene::Hygiene, AstId, InFile}; use mbe::ast_to_token_tree; use ra_syntax::{ ast::{self, AstNode, AttrsOwner}, @@ -68,7 +68,7 @@ impl Attrs { } } - fn from_attrs_owner(db: &impl DefDatabase, owner: Source<&dyn AttrsOwner>) -> Attrs { + fn from_attrs_owner(db: &impl DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { let hygiene = Hygiene::new(db, owner.file_id); Attrs::new(owner.value, &hygiene) } @@ -157,7 +157,7 @@ where N: ast::AttrsOwner, D: DefDatabase, { - let src = Source::new(src.file_id(), src.to_node(db)); + let src = InFile::new(src.file_id(), src.to_node(db)); Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index a57a0176d4..f21937f104 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -6,7 +6,7 @@ pub mod scope; use std::{ops::Index, sync::Arc}; use hir_expand::{ - either::Either, hygiene::Hygiene, AstId, HirFileId, MacroDefId, MacroFileKind, Source, + either::Either, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId, MacroFileKind, }; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; @@ -73,8 +73,8 @@ impl Expander { std::mem::forget(mark); } - fn to_source(&self, value: T) -> Source { - Source { file_id: self.current_file_id, value } + fn to_source(&self, value: T) -> InFile { + InFile { file_id: self.current_file_id, value } } fn parse_path(&mut self, path: ast::Path) -> Option { @@ -115,10 +115,10 @@ pub struct Body { } pub type ExprPtr = Either, AstPtr>; -pub type ExprSource = Source; +pub type ExprSource = InFile; pub type PatPtr = Either, AstPtr>; -pub type PatSource = Source; +pub type PatSource = InFile; /// An item body together with the mapping from syntax nodes to HIR expression /// IDs. This is needed to go from e.g. a position in a file to the HIR @@ -205,7 +205,7 @@ impl BodySourceMap { self.expr_map_back.get(expr).copied() } - pub fn node_expr(&self, node: Source<&ast::Expr>) -> Option { + pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option { let src = node.map(|it| Either::A(AstPtr::new(it))); self.expr_map.get(&src).cloned() } @@ -214,7 +214,7 @@ impl BodySourceMap { self.pat_map_back.get(pat).copied() } - pub fn node_pat(&self, node: Source<&ast::Pat>) -> Option { + pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { let src = node.map(|it| Either::A(AstPtr::new(it))); self.pat_map.get(&src).cloned() } diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 625aa39dd0..ab6599b23f 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -171,7 +171,7 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope #[cfg(test)] mod tests { - use hir_expand::{name::AsName, Source}; + use hir_expand::{name::AsName, InFile}; use ra_db::{fixture::WithFixture, FileId, SourceDatabase}; use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; use test_utils::{assert_eq_text, covers, extract_offset}; @@ -211,7 +211,7 @@ mod tests { let (_body, source_map) = db.body_with_source_map(function.into()); let expr_id = source_map - .node_expr(Source { file_id: file_id.into(), value: &marker.into() }) + .node_expr(InFile { file_id: file_id.into(), value: &marker.into() }) .unwrap(); let scope = scopes.scope_for(expr_id); @@ -318,7 +318,7 @@ mod tests { let expr_scope = { let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); let expr_id = - source_map.node_expr(Source { file_id: file_id.into(), value: &expr_ast }).unwrap(); + source_map.node_expr(InFile { file_id: file_id.into(), value: &expr_ast }).unwrap(); scopes.scope_for(expr_id).unwrap() }; diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs index eda9b2269a..0954984298 100644 --- a/crates/ra_hir_def/src/diagnostics.rs +++ b/crates/ra_hir_def/src/diagnostics.rs @@ -6,7 +6,7 @@ use hir_expand::diagnostics::Diagnostic; use ra_db::RelativePathBuf; use ra_syntax::{ast, AstPtr, SyntaxNodePtr}; -use hir_expand::{HirFileId, Source}; +use hir_expand::{HirFileId, InFile}; #[derive(Debug)] pub struct UnresolvedModule { @@ -19,8 +19,8 @@ impl Diagnostic for UnresolvedModule { fn message(&self) -> String { "unresolved module".to_string() } - fn source(&self) -> Source { - Source { file_id: self.file, value: self.decl.into() } + fn source(&self) -> InFile { + InFile { file_id: self.file, value: self.decl.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index bc55308969..9d89692bf3 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -36,7 +36,7 @@ mod marks; use std::hash::{Hash, Hasher}; -use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; +use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, InFile, MacroDefId}; use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; use ra_db::{impl_intern_key, salsa, CrateId}; use ra_syntax::{ast, AstNode}; @@ -105,10 +105,10 @@ pub trait AstItemDef: salsa::InternKey + Clone { let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; Self::intern(ctx.db, loc) } - fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source { + fn source(self, db: &(impl AstDatabase + InternDatabase)) -> InFile { let loc = self.lookup_intern(db); let value = loc.ast_id.to_node(db); - Source { file_id: loc.ast_id.file_id(), value } + InFile { file_id: loc.ast_id.file_id(), value } } fn module(self, db: &impl InternDatabase) -> ModuleId { let loc = self.lookup_intern(db); @@ -517,42 +517,42 @@ impl HasModule for StaticLoc { pub trait HasSource { type Value; - fn source(&self, db: &impl db::DefDatabase) -> Source; + fn source(&self, db: &impl db::DefDatabase) -> InFile; } impl HasSource for FunctionLoc { type Value = ast::FnDef; - fn source(&self, db: &impl db::DefDatabase) -> Source { + fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - Source::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id(), node) } } impl HasSource for TypeAliasLoc { type Value = ast::TypeAliasDef; - fn source(&self, db: &impl db::DefDatabase) -> Source { + fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - Source::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id(), node) } } impl HasSource for ConstLoc { type Value = ast::ConstDef; - fn source(&self, db: &impl db::DefDatabase) -> Source { + fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - Source::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id(), node) } } impl HasSource for StaticLoc { type Value = ast::StaticDef; - fn source(&self, db: &impl db::DefDatabase) -> Source { + fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - Source::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id(), node) } } @@ -562,5 +562,5 @@ pub trait HasChildSource { fn child_source( &self, db: &impl db::DefDatabase, - ) -> Source>; + ) -> InFile>; } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 2359386c28..1b369ea112 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -58,8 +58,8 @@ mod tests; use std::sync::Arc; use hir_expand::{ - ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId, - Source, + ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, InFile, + MacroDefId, }; use once_cell::sync::Lazy; use ra_arena::Arena; @@ -261,21 +261,21 @@ impl ModuleData { pub fn definition_source( &self, db: &impl DefDatabase, - ) -> Source> { + ) -> InFile> { if let Some(file_id) = self.definition { let sf = db.parse(file_id).tree(); - return Source::new(file_id.into(), Either::A(sf)); + return InFile::new(file_id.into(), Either::A(sf)); } let decl = self.declaration.unwrap(); - Source::new(decl.file_id(), Either::B(decl.to_node(db))) + InFile::new(decl.file_id(), Either::B(decl.to_node(db))) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. /// `None` for the crate root. - pub fn declaration_source(&self, db: &impl DefDatabase) -> Option> { + pub fn declaration_source(&self, db: &impl DefDatabase) -> Option> { let decl = self.declaration?; let value = decl.to_node(db); - Some(Source { file_id: decl.file_id(), value }) + Some(InFile { file_id: decl.file_id(), value }) } } diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 6eb106094c..5196b67cad 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -22,8 +22,8 @@ use ra_syntax::{ use test_utils::tested_by; use crate::{ - attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, LocalImportId, - Source, + attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, InFile, + LocalImportId, }; /// `RawItems` is a set of top-level items in a file (except for impls). @@ -313,7 +313,7 @@ impl RawItemsCollector { let mut buf = Vec::new(); Path::expand_use_item( - Source { value: use_item, file_id: self.file_id }, + InFile { value: use_item, file_id: self.file_id }, &self.hygiene, |path, use_tree, is_glob, alias| { let import_data = ImportData { diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 6810a26dbb..10688df4d7 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -13,7 +13,7 @@ use ra_syntax::{ AstNode, }; -use crate::{type_ref::TypeRef, Source}; +use crate::{type_ref::TypeRef, InFile}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { @@ -67,7 +67,7 @@ pub enum PathKind { impl Path { /// Calls `cb` with all paths, represented by this use item. pub(crate) fn expand_use_item( - item_src: Source, + item_src: InFile, hygiene: &Hygiene, mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), ) { diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs index 3d37e93358..108c1e38c6 100644 --- a/crates/ra_hir_expand/src/diagnostics.rs +++ b/crates/ra_hir_expand/src/diagnostics.rs @@ -18,11 +18,11 @@ use std::{any::Any, fmt}; use ra_syntax::{SyntaxNode, SyntaxNodePtr, TextRange}; -use crate::{db::AstDatabase, Source}; +use crate::{db::AstDatabase, InFile}; pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { fn message(&self) -> String; - fn source(&self) -> Source; + fn source(&self) -> InFile; fn highlight_range(&self) -> TextRange { self.source().value.range() } diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index b6a739cda5..2c5b6b2bb1 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -90,9 +90,9 @@ impl HirFileId { let macro_arg = db.macro_arg(macro_file.macro_call_id)?; Some(ExpansionInfo { - expanded: Source::new(self, parse.syntax_node()), - arg: Source::new(loc.ast_id.file_id, arg_tt), - def: Source::new(loc.ast_id.file_id, def_tt), + expanded: InFile::new(self, parse.syntax_node()), + arg: InFile::new(loc.ast_id.file_id, arg_tt), + def: InFile::new(loc.ast_id.file_id, def_tt), macro_arg, macro_def, exp_map, @@ -167,9 +167,9 @@ impl MacroCallId { /// ExpansionInfo mainly describes how to map text range between src and expanded macro #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExpansionInfo { - expanded: Source, - arg: Source, - def: Source, + expanded: InFile, + arg: InFile, + def: InFile, macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, macro_arg: Arc<(tt::Subtree, mbe::TokenMap)>, @@ -177,7 +177,7 @@ pub struct ExpansionInfo { } impl ExpansionInfo { - pub fn map_token_down(&self, token: Source<&SyntaxToken>) -> Option> { + pub fn map_token_down(&self, token: InFile<&SyntaxToken>) -> Option> { assert_eq!(token.file_id, self.arg.file_id); let range = token.value.text_range().checked_sub(self.arg.value.syntax().text_range().start())?; @@ -191,7 +191,7 @@ impl ExpansionInfo { Some(self.expanded.with_value(token)) } - pub fn map_token_up(&self, token: Source<&SyntaxToken>) -> Option> { + pub fn map_token_up(&self, token: InFile<&SyntaxToken>) -> Option> { let token_id = self.exp_map.token_by_range(token.value.text_range())?; let (token_id, origin) = self.macro_def.0.map_id_up(token_id); @@ -254,33 +254,33 @@ impl AstId { } } -/// `Source` stores a value of `T` inside a particular file/syntax tree. +/// `InFile` stores a value of `T` inside a particular file/syntax tree. /// /// Typical usages are: /// -/// * `Source` -- syntax node in a file -/// * `Source` -- ast node in a file -/// * `Source` -- offset in a file +/// * `InFile` -- syntax node in a file +/// * `InFile` -- ast node in a file +/// * `InFile` -- offset in a file #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -pub struct Source { +pub struct InFile { pub file_id: HirFileId, pub value: T, } -impl Source { - pub fn new(file_id: HirFileId, value: T) -> Source { - Source { file_id, value } +impl InFile { + pub fn new(file_id: HirFileId, value: T) -> InFile { + InFile { file_id, value } } // Similarly, naming here is stupid... - pub fn with_value(&self, value: U) -> Source { - Source::new(self.file_id, value) + pub fn with_value(&self, value: U) -> InFile { + InFile::new(self.file_id, value) } - pub fn map U, U>(self, f: F) -> Source { - Source::new(self.file_id, f(self.value)) + pub fn map U, U>(self, f: F) -> InFile { + InFile::new(self.file_id, f(self.value)) } - pub fn as_ref(&self) -> Source<&T> { + pub fn as_ref(&self) -> InFile<&T> { self.with_value(&self.value) } pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index 4a13fac239..5054189cc1 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs @@ -2,7 +2,7 @@ use std::any::Any; -use hir_expand::{db::AstDatabase, name::Name, HirFileId, Source}; +use hir_expand::{db::AstDatabase, name::Name, HirFileId, InFile}; use ra_syntax::{ast, AstNode, AstPtr, SyntaxNodePtr}; pub use hir_def::diagnostics::UnresolvedModule; @@ -19,8 +19,8 @@ impl Diagnostic for NoSuchField { "no such field".to_string() } - fn source(&self) -> Source { - Source { file_id: self.file, value: self.field.into() } + fn source(&self) -> InFile { + InFile { file_id: self.file, value: self.field.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { @@ -44,8 +44,8 @@ impl Diagnostic for MissingFields { } message } - fn source(&self) -> Source { - Source { file_id: self.file, value: self.field_list.into() } + fn source(&self) -> InFile { + InFile { file_id: self.file, value: self.field_list.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self @@ -72,8 +72,8 @@ impl Diagnostic for MissingOkInTailExpr { fn message(&self) -> String { "wrap return expression in Ok".to_string() } - fn source(&self) -> Source { - Source { file_id: self.file, value: self.expr.into() } + fn source(&self) -> InFile { + InFile { file_id: self.file, value: self.expr.into() } } fn as_any(&self) -> &(dyn Any + Send + 'static) { self diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index c8461b447a..abbc1546cb 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -8,7 +8,7 @@ use hir_def::{ body::BodySourceMap, db::DefDatabase, nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, }; -use hir_expand::Source; +use hir_expand::InFile; use insta::assert_snapshot; use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; use ra_syntax::{ @@ -4680,7 +4680,7 @@ fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { for decl in crate_def_map[module.local_id].scope.declarations() { if let ModuleDefId::FunctionId(func) = decl { let (_body, source_map) = db.body_with_source_map(func.into()); - if let Some(expr_id) = source_map.node_expr(Source::new(pos.file_id.into(), &expr)) { + if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { let infer = db.infer(func.into()); let ty = &infer[expr_id]; return ty.display(db).to_string(); diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index d559dc4d0e..b3c323d38c 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -18,7 +18,7 @@ pub(crate) fn call_info(db: &RootDatabase, 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(), value: src }, + hir::InFile { file_id: position.file_id.into(), value: src }, ); let token = original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; let analyzer = hir::SourceAnalyzer::new( db, - hir::Source::new(position.file_id.into(), &token.parent()), + hir::InFile::new(position.file_id.into(), &token.parent()), Some(position.offset), ); let mut ctx = CompletionContext { diff --git a/crates/ra_ide/src/diagnostics.rs b/crates/ra_ide/src/diagnostics.rs index cc1ccab4b5..c50a70d990 100644 --- a/crates/ra_ide/src/diagnostics.rs +++ b/crates/ra_ide/src/diagnostics.rs @@ -96,7 +96,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec }); let source_file = db.parse(file_id).tree(); let src = - hir::Source { file_id: file_id.into(), value: hir::ModuleSource::SourceFile(source_file) }; + hir::InFile { file_id: file_id.into(), value: hir::ModuleSource::SourceFile(source_file) }; if let Some(m) = hir::Module::from_definition(db, src) { m.diagnostics(db, &mut sink); }; diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6ac60722b9..61dca14ac5 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir::{AssocItem, Either, FieldSource, HasSource, ModuleSource, Source}; +use hir::{AssocItem, Either, FieldSource, HasSource, InFile, ModuleSource}; use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, @@ -141,7 +141,7 @@ impl NavigationTarget { /// Allows `NavigationTarget` to be created from a `NameOwner` pub(crate) fn from_named( db: &RootDatabase, - node: Source<&dyn ast::NameOwner>, + node: InFile<&dyn ast::NameOwner>, docs: Option, description: Option, ) -> NavigationTarget { diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 2f1abf509a..216d5cfec7 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -1,13 +1,13 @@ //! Utilities to work with files, produced by macros. use std::iter::successors; -use hir::Source; +use hir::InFile; use ra_db::FileId; use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken}; use crate::{db::RootDatabase, FileRange}; -pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> FileRange { +pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { let expansion = match node.file_id.expansion_info(db) { None => { return FileRange { @@ -44,8 +44,8 @@ pub(crate) fn descend_into_macros( db: &RootDatabase, file_id: FileId, token: SyntaxToken, -) -> Source { - let src = Source::new(file_id.into(), token); +) -> InFile { + let src = InFile::new(file_id.into(), token); successors(Some(src), |token| { let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs index abc602244c..862c03304a 100644 --- a/crates/ra_ide/src/expand_macro.rs +++ b/crates/ra_ide/src/expand_macro.rs @@ -22,7 +22,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< let name_ref = find_node_at_offset::(file.syntax(), position.offset)?; let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; - let source = hir::Source::new(position.file_id.into(), mac.syntax()); + let source = hir::InFile::new(position.file_id.into(), mac.syntax()); let expanded = expand_macro_recur(db, source, source.with_value(&mac))?; // FIXME: @@ -34,8 +34,8 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< fn expand_macro_recur( db: &RootDatabase, - source: hir::Source<&SyntaxNode>, - macro_call: hir::Source<&ast::MacroCall>, + source: hir::InFile<&SyntaxNode>, + macro_call: hir::InFile<&ast::MacroCall>, ) -> Option { let analyzer = hir::SourceAnalyzer::new(db, source, None); let expansion = analyzer.expand(db, macro_call)?; @@ -46,7 +46,7 @@ fn expand_macro_recur( let mut replaces = FxHashMap::default(); for child in children.into_iter() { - let node = hir::Source::new(macro_file_id, &child); + let node = hir::InFile::new(macro_file_id, &child); if let Some(new_node) = expand_macro_recur(db, source, node) { // Replace the whole node if it is root // `replace_descendants` will not replace the parent node diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index c10a6c8448..76a7412076 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir::{db::AstDatabase, Source}; +use hir::{db::AstDatabase, InFile}; use ra_syntax::{ ast::{self, DocCommentsOwner}, match_ast, AstNode, SyntaxNode, @@ -58,7 +58,7 @@ impl ReferenceResult { pub(crate) fn reference_definition( db: &RootDatabase, - name_ref: Source<&ast::NameRef>, + name_ref: InFile<&ast::NameRef>, ) -> ReferenceResult { use self::ReferenceResult::*; @@ -94,7 +94,7 @@ pub(crate) fn reference_definition( pub(crate) fn name_definition( db: &RootDatabase, - name: Source<&ast::Name>, + name: InFile<&ast::Name>, ) -> Option> { let parent = name.value.syntax().parent()?; @@ -115,7 +115,7 @@ pub(crate) fn name_definition( None } -fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option { +fn named_target(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Option { match_ast! { match (node.value) { ast::StructDef(it) => { diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 260a7b8694..d8185c6889 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -227,7 +227,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { .take_while(|it| it.text_range() == leaf_node.text_range()) .find(|it| ast::Expr::cast(it.clone()).is_some() || ast::Pat::cast(it.clone()).is_some())?; let analyzer = - hir::SourceAnalyzer::new(db, hir::Source::new(frange.file_id.into(), &node), None); + hir::SourceAnalyzer::new(db, hir::InFile::new(frange.file_id.into(), &node), None); let ty = if let Some(ty) = ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) { ty diff --git a/crates/ra_ide/src/impls.rs b/crates/ra_ide/src/impls.rs index aa480e399b..9b165ee2aa 100644 --- a/crates/ra_ide/src/impls.rs +++ b/crates/ra_ide/src/impls.rs @@ -16,7 +16,7 @@ pub(crate) fn goto_implementation( let src = hir::ModuleSource::from_position(db, position); let module = hir::Module::from_definition( db, - hir::Source { file_id: position.file_id.into(), value: src }, + hir::InFile { file_id: position.file_id.into(), value: src }, )?; if let Some(nominal_def) = find_node_at_offset::(&syntax, position.offset) { @@ -42,15 +42,15 @@ fn impls_for_def( ) -> Option> { let ty = match node { ast::NominalDef::StructDef(def) => { - let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; + let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; hir::Struct::from_source(db, src)?.ty(db) } ast::NominalDef::EnumDef(def) => { - let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; + let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; hir::Enum::from_source(db, src)?.ty(db) } ast::NominalDef::UnionDef(def) => { - let src = hir::Source { file_id: position.file_id.into(), value: def.clone() }; + let src = hir::InFile { file_id: position.file_id.into(), value: def.clone() }; hir::Union::from_source(db, src)?.ty(db) } }; @@ -73,7 +73,7 @@ fn impls_for_trait( node: &ast::TraitDef, module: hir::Module, ) -> Option> { - let src = hir::Source { file_id: position.file_id.into(), value: node.clone() }; + let src = hir::InFile { file_id: position.file_id.into(), value: node.clone() }; let tr = hir::Trait::from_source(db, src)?; let krate = module.krate(); diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 45149bf0cc..59eced9d73 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -38,7 +38,7 @@ fn get_inlay_hints( node: &SyntaxNode, max_inlay_hint_length: Option, ) -> Option> { - let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); + let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None); match_ast! { match node { ast::LetStmt(it) => { diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index 6027e7d54d..616d69fce2 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs @@ -10,7 +10,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec return Vec::new(), Some(it) => it, @@ -23,7 +23,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { 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(), value: src }) + match hir::Module::from_definition(db, hir::InFile { file_id: file_id.into(), value: src }) { Some(it) => it, None => return Vec::new(), diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 21a1ea69eb..3e7bfd872e 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -14,7 +14,7 @@ mod name_definition; mod rename; mod search_scope; -use hir::Source; +use hir::InFile; use once_cell::unsync::Lazy; use ra_db::{SourceDatabase, SourceDatabaseExt}; use ra_prof::profile; @@ -107,12 +107,12 @@ fn find_name<'a>( position: FilePosition, ) -> Option> { if let Some(name) = find_node_at_offset::(&syntax, position.offset) { - let def = classify_name(db, Source::new(position.file_id.into(), &name))?; + let def = classify_name(db, InFile::new(position.file_id.into(), &name))?; let range = name.syntax().text_range(); return Some(RangeInfo::new(range, (name.text().to_string(), def))); } let name_ref = find_node_at_offset::(&syntax, position.offset)?; - let def = classify_name_ref(db, Source::new(position.file_id.into(), &name_ref))?; + let def = classify_name_ref(db, InFile::new(position.file_id.into(), &name_ref))?; let range = name_ref.syntax().text_range(); Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) } @@ -144,7 +144,7 @@ fn process_definition( continue; } } - if let Some(d) = classify_name_ref(db, Source::new(file_id.into(), &name_ref)) { + if let Some(d) = classify_name_ref(db, InFile::new(file_id.into(), &name_ref)) { if d == def { refs.push(FileRange { file_id, range }); } diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 5cea805ec9..b716d32e59 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -1,6 +1,6 @@ //! Functions that are used to classify an element from its definition or reference. -use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer}; +use hir::{FromSource, InFile, Module, ModuleSource, PathResolution, SourceAnalyzer}; use ra_prof::profile; use ra_syntax::{ast, match_ast, AstNode}; use test_utils::tested_by; @@ -11,7 +11,7 @@ use super::{ }; use crate::db::RootDatabase; -pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option { +pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Option { let _p = profile("classify_name"); let parent = name.value.syntax().parent()?; @@ -117,7 +117,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti pub(crate) fn classify_name_ref( db: &RootDatabase, - name_ref: Source<&ast::NameRef>, + name_ref: InFile<&ast::NameRef>, ) -> Option { let _p = profile("classify_name_ref"); diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index d58496049e..ea6b354c20 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -55,7 +55,7 @@ fn rename_mod( ) -> Option { 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(), value: ast_module.clone() }; + let module_src = hir::InFile { file_id: position.file_id.into(), value: ast_module.clone() }; if let Some(module) = hir::Module::from_declaration(db, module_src) { let src = module.definition_source(db); let file_id = src.file_id.original_file(db); diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 8039a5164e..e213e1a06d 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir::Source; +use hir::InFile; use itertools::Itertools; use ra_db::SourceDatabase; use ra_syntax::{ @@ -66,8 +66,8 @@ 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, Source::new(file_id.into(), &module.syntax())); - let module = hir::Module::from_definition(db, Source::new(file_id.into(), src))?; + let src = hir::ModuleSource::from_child_node(db, InFile::new(file_id.into(), &module.syntax())); + let module = hir::Module::from_definition(db, InFile::new(file_id.into(), src))?; 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_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 9a3e4c82f6..e6a79541fe 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -2,7 +2,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; -use hir::{Name, Source}; +use hir::{InFile, Name}; use ra_db::SourceDatabase; use ra_prof::profile; use ra_syntax::{ast, AstNode, Direction, SyntaxElement, SyntaxKind, SyntaxKind::*, TextRange, T}; @@ -81,7 +81,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec Vec { let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); let name_kind = - classify_name(db, Source::new(file_id.into(), &name)).map(|d| d.kind); + classify_name(db, InFile::new(file_id.into(), &name)).map(|d| d.kind); if let Some(Local(local)) = &name_kind { if let Some(name) = local.name(db) { From e823c578c9f6886fe9db9767cb81e75a6c56bf15 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 28 Nov 2019 16:00:03 +0300 Subject: [PATCH 003/312] Use InFile for AstId --- crates/ra_hir/src/code_model/src.rs | 2 +- crates/ra_hir_def/src/attr.rs | 2 +- crates/ra_hir_def/src/lib.rs | 10 ++--- crates/ra_hir_def/src/nameres.rs | 6 +-- .../src/nameres/tests/mod_resolution.rs | 4 +- crates/ra_hir_expand/src/lib.rs | 39 ++----------------- 6 files changed, 16 insertions(+), 47 deletions(-) diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 6fd4e79871..9a755704f2 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -105,7 +105,7 @@ impl HasSource for TypeAlias { impl HasSource for MacroDef { type Ast = ast::MacroCall; fn source(self, db: &impl DefDatabase) -> InFile { - InFile { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) } + InFile { file_id: self.id.ast_id.file_id, value: self.id.ast_id.to_node(db) } } } impl HasSource for ImplBlock { diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 83783ac7ad..346019f884 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -157,7 +157,7 @@ where N: ast::AttrsOwner, D: DefDatabase, { - let src = InFile::new(src.file_id(), src.to_node(db)); + let src = InFile::new(src.file_id, src.to_node(db)); Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 9d89692bf3..6daf7d3a39 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -108,7 +108,7 @@ pub trait AstItemDef: salsa::InternKey + Clone { fn source(self, db: &(impl AstDatabase + InternDatabase)) -> InFile { let loc = self.lookup_intern(db); let value = loc.ast_id.to_node(db); - InFile { file_id: loc.ast_id.file_id(), value } + InFile { file_id: loc.ast_id.file_id, value } } fn module(self, db: &impl InternDatabase) -> ModuleId { let loc = self.lookup_intern(db); @@ -525,7 +525,7 @@ impl HasSource for FunctionLoc { fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id, node) } } @@ -534,7 +534,7 @@ impl HasSource for TypeAliasLoc { fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id, node) } } @@ -543,7 +543,7 @@ impl HasSource for ConstLoc { fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id, node) } } @@ -552,7 +552,7 @@ impl HasSource for StaticLoc { fn source(&self, db: &impl db::DefDatabase) -> InFile { let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id(), node) + InFile::new(self.ast_id.file_id, node) } } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 1b369ea112..df42ea84a2 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -267,7 +267,7 @@ impl ModuleData { return InFile::new(file_id.into(), Either::A(sf)); } let decl = self.declaration.unwrap(); - InFile::new(decl.file_id(), Either::B(decl.to_node(db))) + InFile::new(decl.file_id, Either::B(decl.to_node(db))) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. @@ -275,7 +275,7 @@ impl ModuleData { pub fn declaration_source(&self, db: &impl DefDatabase) -> Option> { let decl = self.declaration?; let value = decl.to_node(db); - Some(InFile { file_id: decl.file_id(), value }) + Some(InFile { file_id: decl.file_id, value }) } } @@ -309,7 +309,7 @@ mod diagnostics { } let decl = declaration.to_node(db); sink.push(UnresolvedModule { - file: declaration.file_id(), + file: declaration.file_id, decl: AstPtr::new(&decl), candidate: candidate.clone(), }) diff --git a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs index e11530062d..e800cc68e4 100644 --- a/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs +++ b/crates/ra_hir_def/src/nameres/tests/mod_resolution.rs @@ -668,7 +668,7 @@ fn unresolved_module_diagnostics() { module: LocalModuleId( 0, ), - declaration: AstId { + declaration: InFile { file_id: HirFileId( FileId( FileId( @@ -676,7 +676,7 @@ fn unresolved_module_diagnostics() { ), ), ), - file_ast_id: FileAstId { + value: FileAstId { raw: ErasedFileAstId( 1, ), diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 2c5b6b2bb1..fb88d2ac27 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -13,7 +13,7 @@ pub mod diagnostics; pub mod builtin_macro; pub mod quote; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::sync::Arc; use ra_db::{salsa, CrateId, FileId}; @@ -70,7 +70,7 @@ impl HirFileId { HirFileIdRepr::FileId(file_id) => file_id, HirFileIdRepr::MacroFile(macro_file) => { let loc = db.lookup_intern_macro(macro_file.macro_call_id); - loc.ast_id.file_id().original_file(db) + loc.ast_id.file_id.original_file(db) } } } @@ -214,43 +214,12 @@ impl ExpansionInfo { /// /// It is stable across reparses, and can be used as salsa key/value. // FIXME: isn't this just a `Source>` ? -#[derive(Debug)] -pub struct AstId { - file_id: HirFileId, - file_ast_id: FileAstId, -} - -impl Clone for AstId { - fn clone(&self) -> AstId { - *self - } -} -impl Copy for AstId {} - -impl PartialEq for AstId { - fn eq(&self, other: &Self) -> bool { - (self.file_id, self.file_ast_id) == (other.file_id, other.file_ast_id) - } -} -impl Eq for AstId {} -impl Hash for AstId { - fn hash(&self, hasher: &mut H) { - (self.file_id, self.file_ast_id).hash(hasher); - } -} +pub type AstId = InFile>; impl AstId { - pub fn new(file_id: HirFileId, file_ast_id: FileAstId) -> AstId { - AstId { file_id, file_ast_id } - } - - pub fn file_id(&self) -> HirFileId { - self.file_id - } - pub fn to_node(&self, db: &dyn db::AstDatabase) -> N { let root = db.parse_or_expand(self.file_id).unwrap(); - db.ast_id_map(self.file_id).get(self.file_ast_id).to_node(&root) + db.ast_id_map(self.file_id).get(self.value).to_node(&root) } } From 8f1f5a783a3ffd0afbf5b1fdf22ff9caf7fda928 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 28 Nov 2019 18:05:28 +0300 Subject: [PATCH 004/312] Move source-related traits to a separate module --- crates/ra_hir/src/code_model/src.rs | 5 ++- crates/ra_hir_def/src/adt.rs | 2 +- crates/ra_hir_def/src/attr.rs | 3 +- crates/ra_hir_def/src/body.rs | 3 +- crates/ra_hir_def/src/data.rs | 5 +-- crates/ra_hir_def/src/docs.rs | 6 +++- crates/ra_hir_def/src/generics.rs | 3 +- crates/ra_hir_def/src/lib.rs | 54 ++--------------------------- crates/ra_hir_def/src/src.rs | 54 +++++++++++++++++++++++++++++ crates/ra_hir_ty/src/infer.rs | 2 +- 10 files changed, 77 insertions(+), 60 deletions(-) create mode 100644 crates/ra_hir_def/src/src.rs diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 9a755704f2..2cf2103497 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -1,6 +1,9 @@ //! FIXME: write short doc here -use hir_def::{AstItemDef, HasChildSource, HasSource as _, Lookup, VariantId}; +use hir_def::{ + src::{HasChildSource, HasSource as _}, + AstItemDef, Lookup, VariantId, +}; use hir_expand::either::Either; use ra_syntax::ast; diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 3d21dedeee..9ab829aab2 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -11,7 +11,7 @@ use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ - db::DefDatabase, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, HasChildSource, + db::DefDatabase, src::HasChildSource, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId, }; diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 346019f884..bc7ade9212 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -11,7 +11,8 @@ use ra_syntax::{ use tt::Subtree; use crate::{ - db::DefDatabase, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup, + db::DefDatabase, path::Path, src::HasChildSource, src::HasSource, AdtId, AstItemDef, AttrDefId, + Lookup, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index f21937f104..69508dd8a5 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,8 @@ use crate::{ expr::{Expr, ExprId, Pat, PatId}, nameres::CrateDefMap, path::Path, - DefWithBodyId, HasModule, HasSource, Lookup, ModuleId, + src::HasSource, + DefWithBodyId, HasModule, Lookup, ModuleId, }; struct Expander { diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index fee10b2375..095d7064a0 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -10,9 +10,10 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ db::DefDatabase, + src::HasSource, type_ref::{Mutability, TypeRef}, - AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, HasSource, - ImplId, Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, + AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, ImplId, + Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 34ed9b7a5e..ec944373da 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -8,7 +8,11 @@ use std::sync::Arc; use hir_expand::either::Either; use ra_syntax::ast; -use crate::{db::DefDatabase, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup}; +use crate::{ + db::DefDatabase, + src::{HasChildSource, HasSource}, + AdtId, AstItemDef, AttrDefId, Lookup, +}; /// Holds documentation #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 3f94e40e4f..5f648ffc35 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -9,8 +9,9 @@ use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::DefDatabase, + src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup, + AdtId, AstItemDef, ContainerId, GenericDefId, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 6daf7d3a39..cfeacfded9 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -29,6 +29,8 @@ pub mod resolver; mod trace; pub mod nameres; +pub mod src; + #[cfg(test)] mod test_db; #[cfg(test)] @@ -37,7 +39,7 @@ mod marks; use std::hash::{Hash, Hasher}; use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, InFile, MacroDefId}; -use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; +use ra_arena::{impl_arena_id, RawId}; use ra_db::{impl_intern_key, salsa, CrateId}; use ra_syntax::{ast, AstNode}; @@ -514,53 +516,3 @@ impl HasModule for StaticLoc { self.container } } - -pub trait HasSource { - type Value; - fn source(&self, db: &impl db::DefDatabase) -> InFile; -} - -impl HasSource for FunctionLoc { - type Value = ast::FnDef; - - fn source(&self, db: &impl db::DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for TypeAliasLoc { - type Value = ast::TypeAliasDef; - - fn source(&self, db: &impl db::DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for ConstLoc { - type Value = ast::ConstDef; - - fn source(&self, db: &impl db::DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for StaticLoc { - type Value = ast::StaticDef; - - fn source(&self, db: &impl db::DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -pub trait HasChildSource { - type ChildId; - type Value; - fn child_source( - &self, - db: &impl db::DefDatabase, - ) -> InFile>; -} diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs new file mode 100644 index 0000000000..27caa02cc4 --- /dev/null +++ b/crates/ra_hir_def/src/src.rs @@ -0,0 +1,54 @@ +//! Utilities for mapping between hir IDs and the surface syntax. + +use hir_expand::InFile; +use ra_arena::map::ArenaMap; +use ra_syntax::ast; + +use crate::{db::DefDatabase, ConstLoc, FunctionLoc, StaticLoc, TypeAliasLoc}; + +pub trait HasSource { + type Value; + fn source(&self, db: &impl DefDatabase) -> InFile; +} + +impl HasSource for FunctionLoc { + type Value = ast::FnDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + +impl HasSource for TypeAliasLoc { + type Value = ast::TypeAliasDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + +impl HasSource for ConstLoc { + type Value = ast::ConstDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + +impl HasSource for StaticLoc { + type Value = ast::StaticDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + +pub trait HasChildSource { + type ChildId; + type Value; + fn child_source(&self, db: &impl DefDatabase) -> InFile>; +} diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 1e9f4b208d..f6283ab6db 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -693,7 +693,7 @@ impl Expectation { } mod diagnostics { - use hir_def::{expr::ExprId, FunctionId, HasSource, Lookup}; + use hir_def::{expr::ExprId, src::HasSource, FunctionId, Lookup}; use hir_expand::diagnostics::DiagnosticSink; use crate::{db::HirDatabase, diagnostics::NoSuchField}; From 4992d2bf79e9da6db759eb8e1715f90f31ec7eb9 Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 29 Nov 2019 03:10:16 +0800 Subject: [PATCH 005/312] Infer range types --- crates/ra_hir_def/src/body/lower.rs | 22 +++++++++++-- crates/ra_hir_def/src/expr.rs | 28 ++++++++++++++-- crates/ra_hir_def/src/path.rs | 30 +++++++++++++++++ crates/ra_hir_expand/src/name.rs | 6 ++++ crates/ra_hir_ty/src/infer.rs | 36 +++++++++++++++++++++ crates/ra_hir_ty/src/infer/expr.rs | 41 +++++++++++++++++++++++ crates/ra_hir_ty/src/tests.rs | 50 +++++++++++++++++++++++++++++ 7 files changed, 209 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 331736cb23..d18964d54b 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -8,7 +8,7 @@ use hir_expand::{ use ra_arena::Arena; use ra_syntax::{ ast::{ - self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, + self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, RangeOp, TypeAscriptionOwner, }, AstNode, AstPtr, @@ -429,10 +429,28 @@ where let index = self.collect_expr_opt(e.index()); self.alloc_expr(Expr::Index { base, index }, syntax_ptr) } + ast::Expr::RangeExpr(e) => { + let lhs = e.start().map(|lhs| self.collect_expr(lhs)); + let rhs = e.end().map(|rhs| self.collect_expr(rhs)); + match (lhs, e.op_kind(), rhs) { + (None, _, None) => self.alloc_expr(Expr::RangeFull, syntax_ptr), + (Some(lhs), _, None) => self.alloc_expr(Expr::RangeFrom { lhs }, syntax_ptr), + (None, Some(RangeOp::Inclusive), Some(rhs)) => { + self.alloc_expr(Expr::RangeToInclusive { rhs }, syntax_ptr) + } + (Some(lhs), Some(RangeOp::Inclusive), Some(rhs)) => { + self.alloc_expr(Expr::RangeInclusive { lhs, rhs }, syntax_ptr) + } + // If RangeOp is missing, fallback to exclusive range. + (None, _, Some(rhs)) => self.alloc_expr(Expr::RangeTo { rhs }, syntax_ptr), + (Some(lhs), _, Some(rhs)) => { + self.alloc_expr(Expr::Range { lhs, rhs }, syntax_ptr) + } + } + } // FIXME implement HIR for these: ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), - ast::Expr::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { Some((mark, expansion)) => { let id = self.collect_expr(expansion); diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index 04c1d8f69b..115090218c 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -130,6 +130,24 @@ pub enum Expr { rhs: ExprId, op: Option, }, + RangeFull, + RangeFrom { + lhs: ExprId, + }, + RangeTo { + rhs: ExprId, + }, + Range { + lhs: ExprId, + rhs: ExprId, + }, + RangeToInclusive { + rhs: ExprId, + }, + RangeInclusive { + lhs: ExprId, + rhs: ExprId, + }, Index { base: ExprId, index: ExprId, @@ -284,7 +302,9 @@ impl Expr { Expr::Lambda { body, .. } => { f(*body); } - Expr::BinaryOp { lhs, rhs, .. } => { + Expr::BinaryOp { lhs, rhs, .. } + | Expr::Range { lhs, rhs } + | Expr::RangeInclusive { lhs, rhs } => { f(*lhs); f(*rhs); } @@ -292,7 +312,11 @@ impl Expr { f(*base); f(*index); } - Expr::Field { expr, .. } + Expr::RangeFull => {} + Expr::RangeFrom { lhs: expr } + | Expr::RangeTo { rhs: expr } + | Expr::RangeToInclusive { rhs: expr } + | Expr::Field { expr, .. } | Expr::Await { expr } | Expr::Try { expr } | Expr::Cast { expr, .. } diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 10688df4d7..ff252fe442 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -409,6 +409,36 @@ pub mod known { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) } + pub fn std_ops_range() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE]) + } + + pub fn std_ops_range_from() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE]) + } + + pub fn std_ops_range_full() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE]) + } + + pub fn std_ops_range_inclusive() -> Path { + Path::from_simple_segments( + PathKind::Abs, + vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE], + ) + } + + pub fn std_ops_range_to() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE]) + } + + pub fn std_ops_range_to_inclusive() -> Path { + Path::from_simple_segments( + PathKind::Abs, + vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE], + ) + } + pub fn std_result_result() -> Path { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) } diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 7824489d7f..05ba370706 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -140,6 +140,12 @@ pub const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result"); pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output"); pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target"); pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); +pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(9, b"RangeFrom"); +pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(9, b"RangeFull"); +pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(14, b"RangeInclusive"); +pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(16, b"RangeToInclusive"); +pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(7, b"RangeTo"); +pub const RANGE_TYPE: Name = Name::new_inline_ascii(5, b"Range"); // Builtin Macros pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index f6283ab6db..fe259371f5 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -577,6 +577,42 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } + + fn resolve_range_full(&self) -> Option { + let path = known::std_ops_range_full(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } + + fn resolve_range(&self) -> Option { + let path = known::std_ops_range(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } + + fn resolve_range_inclusive(&self) -> Option { + let path = known::std_ops_range_inclusive(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } + + fn resolve_range_from(&self) -> Option { + let path = known::std_ops_range_from(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } + + fn resolve_range_to(&self) -> Option { + let path = known::std_ops_range_to(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } + + fn resolve_range_to_inclusive(&self) -> Option { + let path = known::std_ops_range_to_inclusive(); + let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; + Some(struct_.into()) + } } /// The ID of a type variable. diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 2f9ca4bbbf..a00aa426a2 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -415,6 +415,47 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } _ => Ty::Unknown, }, + Expr::RangeFull => match self.resolve_range_full() { + Some(adt) => Ty::simple(TypeCtor::Adt(adt)), + None => Ty::Unknown, + }, + Expr::Range { lhs, rhs } => { + let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); + let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); + match self.resolve_range() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), + None => Ty::Unknown, + } + } + Expr::RangeInclusive { lhs, rhs } => { + let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); + let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); + match self.resolve_range_inclusive() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), + None => Ty::Unknown, + } + } + Expr::RangeFrom { lhs } => { + let ty = self.infer_expr(*lhs, &Expectation::none()); + match self.resolve_range_from() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + } + } + Expr::RangeTo { rhs } => { + let ty = self.infer_expr(*rhs, &Expectation::none()); + match self.resolve_range_to() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + } + } + Expr::RangeToInclusive { rhs } => { + let ty = self.infer_expr(*rhs, &Expectation::none()); + match self.resolve_range_to_inclusive() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + } + } Expr::Index { base, index } => { let _base_ty = self.infer_expr(*base, &Expectation::none()); let _index_ty = self.infer_expr(*index, &Expectation::none()); diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index abbc1546cb..4ba87e667a 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -221,6 +221,56 @@ mod collections { assert_eq!("&str", type_at_pos(&db, pos)); } +#[test] +fn infer_ranges() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std +fn test() { + let a = ..; + let b = 1..; + let c = ..2u32; + let d = 1..2usize; + let e = ..=10; + let f = 'a'..='z'; + + let t = (a, b, c, d, e, f); + t<|>; +} + +//- /std.rs crate:std +#[prelude_import] use prelude::*; +mod prelude {} + +pub mod ops { + pub struct Range { + pub start: Idx, + pub end: Idx, + } + pub struct RangeFrom { + pub start: Idx, + } + struct RangeFull; + pub struct RangeInclusive { + start: Idx, + end: Idx, + is_empty: u8, + } + pub struct RangeTo { + pub end: Idx, + } + pub struct RangeToInclusive { + pub end: Idx, + } +} +"#, + ); + assert_eq!( + "(RangeFull, RangeFrom, RangeTo, Range, RangeToInclusive, RangeInclusive)", + type_at_pos(&db, pos), + ); +} + #[test] fn infer_while_let() { let (db, pos) = TestDB::with_position( From 439080f0274cf4def3f393f466ceb05c8cb8bcd2 Mon Sep 17 00:00:00 2001 From: Paulo Lieuthier Date: Tue, 15 Oct 2019 15:29:20 -0300 Subject: [PATCH 006/312] assists: add assist for custom implementation for derived trait --- .../ra_assists/src/assists/add_custom_impl.rs | 189 ++++++++++++++++++ crates/ra_assists/src/lib.rs | 2 + 2 files changed, 191 insertions(+) create mode 100644 crates/ra_assists/src/assists/add_custom_impl.rs diff --git a/crates/ra_assists/src/assists/add_custom_impl.rs b/crates/ra_assists/src/assists/add_custom_impl.rs new file mode 100644 index 0000000000..7e64cd9023 --- /dev/null +++ b/crates/ra_assists/src/assists/add_custom_impl.rs @@ -0,0 +1,189 @@ +//! FIXME: write short doc here + +use crate::{Assist, AssistCtx, AssistId}; +use hir::db::HirDatabase; +use join_to_string::join; +use ra_syntax::{ + ast::{self, AstNode}, + Direction, SmolStr, + SyntaxKind::{IDENT, WHITESPACE}, + TextRange, TextUnit, +}; + +const DERIVE_TRAIT: &'static str = "derive"; + +pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option { + let input = ctx.find_node_at_offset::()?; + let attr = input.syntax().parent().and_then(ast::Attr::cast)?; + + let attr_name = attr + .syntax() + .descendants_with_tokens() + .filter(|t| t.kind() == IDENT) + .find_map(|i| i.into_token()) + .filter(|t| *t.text() == DERIVE_TRAIT)? + .text() + .clone(); + + let trait_token = + ctx.token_at_offset().filter(|t| t.kind() == IDENT && *t.text() != attr_name).next()?; + + let annotated = attr.syntax().siblings(Direction::Next).find_map(|s| ast::Name::cast(s))?; + let annotated_name = annotated.syntax().text().to_string(); + let start_offset = annotated.syntax().parent()?.text_range().end(); + + ctx.add_assist(AssistId("add_custom_impl"), "add custom impl", |edit| { + edit.target(attr.syntax().text_range()); + + let new_attr_input = input + .syntax() + .descendants_with_tokens() + .filter(|t| t.kind() == IDENT) + .filter_map(|t| t.into_token().map(|t| t.text().clone())) + .filter(|t| t != trait_token.text()) + .collect::>(); + let has_more_derives = new_attr_input.len() > 0; + let new_attr_input = + join(new_attr_input.iter()).separator(", ").surround_with("(", ")").to_string(); + let new_attr_input_len = new_attr_input.len(); + + let mut buf = String::new(); + buf.push_str("\n\nimpl "); + buf.push_str(trait_token.text().as_str()); + buf.push_str(" for "); + buf.push_str(annotated_name.as_str()); + buf.push_str(" {\n"); + + let cursor_delta = if has_more_derives { + edit.replace(input.syntax().text_range(), new_attr_input); + input.syntax().text_range().len() - TextUnit::from_usize(new_attr_input_len) + } else { + let attr_range = attr.syntax().text_range(); + edit.delete(attr_range); + + let line_break_range = attr + .syntax() + .next_sibling_or_token() + .filter(|t| t.kind() == WHITESPACE) + .map(|t| t.text_range()) + .unwrap_or(TextRange::from_to(TextUnit::from(0), TextUnit::from(0))); + edit.delete(line_break_range); + + attr_range.len() + line_break_range.len() + }; + + edit.set_cursor(start_offset + TextUnit::of_str(&buf) - cursor_delta); + buf.push_str("\n}"); + edit.insert(start_offset, buf); + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::helpers::{check_assist, check_assist_not_applicable}; + + #[test] + fn add_custom_impl_for_unique_input() { + check_assist( + add_custom_impl, + " +#[derive(Debu<|>g)] +struct Foo { + bar: String, +} + ", + " +struct Foo { + bar: String, +} + +impl Debug for Foo { +<|> +} + ", + ) + } + + #[test] + fn add_custom_impl_for_with_visibility_modifier() { + check_assist( + add_custom_impl, + " +#[derive(Debug<|>)] +pub struct Foo { + bar: String, +} + ", + " +pub struct Foo { + bar: String, +} + +impl Debug for Foo { +<|> +} + ", + ) + } + + #[test] + fn add_custom_impl_when_multiple_inputs() { + check_assist( + add_custom_impl, + " +#[derive(Display, Debug<|>, Serialize)] +struct Foo {} + ", + " +#[derive(Display, Serialize)] +struct Foo {} + +impl Debug for Foo { +<|> +} + ", + ) + } + + #[test] + fn test_ignore_derive_macro_without_input() { + check_assist_not_applicable( + add_custom_impl, + " +#[derive(<|>)] +struct Foo {} + ", + ) + } + + #[test] + fn test_ignore_if_cursor_on_param() { + check_assist_not_applicable( + add_custom_impl, + " +#[derive<|>(Debug)] +struct Foo {} + ", + ); + + check_assist_not_applicable( + add_custom_impl, + " +#[derive(Debug)<|>] +struct Foo {} + ", + ) + } + + #[test] + fn test_ignore_if_not_derive() { + check_assist_not_applicable( + add_custom_impl, + " +#[allow(non_camel_<|>case_types)] +struct Foo {} + ", + ) + } +} diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index a372bd8b9d..98fb20b227 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -95,6 +95,7 @@ mod assists { mod add_derive; mod add_explicit_type; mod add_impl; + mod add_custom_impl; mod add_new; mod apply_demorgan; mod invert_if; @@ -121,6 +122,7 @@ mod assists { add_derive::add_derive, add_explicit_type::add_explicit_type, add_impl::add_impl, + add_custom_impl::add_custom_impl, add_new::add_new, apply_demorgan::apply_demorgan, invert_if::invert_if, From 5b2d52c8df5235fce9d2ae78adc3182a9659b268 Mon Sep 17 00:00:00 2001 From: Paulo Lieuthier Date: Sat, 19 Oct 2019 08:19:06 -0300 Subject: [PATCH 007/312] docs: describe new feature 'add custom impl for derived trait' --- .../ra_assists/src/assists/add_custom_impl.rs | 17 +++++++++++++++++ crates/ra_assists/src/doc_tests/generated.rs | 19 +++++++++++++++++++ docs/user/assists.md | 18 ++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/crates/ra_assists/src/assists/add_custom_impl.rs b/crates/ra_assists/src/assists/add_custom_impl.rs index 7e64cd9023..037306fd67 100644 --- a/crates/ra_assists/src/assists/add_custom_impl.rs +++ b/crates/ra_assists/src/assists/add_custom_impl.rs @@ -12,6 +12,23 @@ use ra_syntax::{ const DERIVE_TRAIT: &'static str = "derive"; +// Assist: add_custom_impl +// +// Adds impl block for derived trait. +// +// ``` +// #[derive(Deb<|>ug, Display)] +// struct S; +// ``` +// -> +// ``` +// #[derive(Display)] +// struct S; +// +// impl Debug for S { +// +// } +// ``` pub(crate) fn add_custom_impl(ctx: AssistCtx) -> Option { let input = ctx.find_node_at_offset::()?; let attr = input.syntax().parent().and_then(ast::Attr::cast)?; diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 3c716c2d12..4586eeb592 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -2,6 +2,25 @@ use super::check; +#[test] +fn doctest_add_custom_impl() { + check( + "add_custom_impl", + r#####" +#[derive(Deb<|>ug, Display)] +struct S; +"#####, + r#####" +#[derive(Display)] +struct S; + +impl Debug for S { + +} +"#####, + ) +} + #[test] fn doctest_add_derive() { check( diff --git a/docs/user/assists.md b/docs/user/assists.md index 6f4c30bee3..334ba450f5 100644 --- a/docs/user/assists.md +++ b/docs/user/assists.md @@ -3,6 +3,24 @@ Cursor position or selection is signified by `┃` character. +## `add_custom_impl` + +Adds impl block for derived trait. + +```rust +// BEFORE +#[derive(Deb┃ug, Display)] +struct S; + +// AFTER +#[derive(Display)] +struct S; + +impl Debug for S { + +} +``` + ## `add_derive` Adds a new `#[derive()]` clause to a struct or enum. From 2cb684bbce1c487b2efb5a8154afe66e4907ceac Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 29 Nov 2019 14:49:12 +0800 Subject: [PATCH 008/312] Reduce variants of Expr --- crates/ra_hir_def/src/body/lower.rs | 19 ++------ crates/ra_hir_def/src/expr.rs | 38 ++++++--------- crates/ra_hir_ty/src/infer/expr.rs | 76 ++++++++++++++--------------- 3 files changed, 56 insertions(+), 77 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index d18964d54b..be1eaa5234 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -8,7 +8,7 @@ use hir_expand::{ use ra_arena::Arena; use ra_syntax::{ ast::{ - self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, RangeOp, + self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, TypeAscriptionOwner, }, AstNode, AstPtr, @@ -432,20 +432,11 @@ where ast::Expr::RangeExpr(e) => { let lhs = e.start().map(|lhs| self.collect_expr(lhs)); let rhs = e.end().map(|rhs| self.collect_expr(rhs)); - match (lhs, e.op_kind(), rhs) { - (None, _, None) => self.alloc_expr(Expr::RangeFull, syntax_ptr), - (Some(lhs), _, None) => self.alloc_expr(Expr::RangeFrom { lhs }, syntax_ptr), - (None, Some(RangeOp::Inclusive), Some(rhs)) => { - self.alloc_expr(Expr::RangeToInclusive { rhs }, syntax_ptr) - } - (Some(lhs), Some(RangeOp::Inclusive), Some(rhs)) => { - self.alloc_expr(Expr::RangeInclusive { lhs, rhs }, syntax_ptr) - } - // If RangeOp is missing, fallback to exclusive range. - (None, _, Some(rhs)) => self.alloc_expr(Expr::RangeTo { rhs }, syntax_ptr), - (Some(lhs), _, Some(rhs)) => { - self.alloc_expr(Expr::Range { lhs, rhs }, syntax_ptr) + match e.op_kind() { + Some(range_type) => { + self.alloc_expr(Expr::Range { lhs, rhs, range_type }, syntax_ptr) } + None => self.alloc_expr(Expr::Missing, syntax_ptr), } } diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index 115090218c..6fad80a8d4 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -14,6 +14,7 @@ use hir_expand::name::Name; use ra_arena::{impl_arena_id, RawId}; +use ra_syntax::ast::RangeOp; use crate::{ builtin_type::{BuiltinFloat, BuiltinInt}, @@ -130,23 +131,10 @@ pub enum Expr { rhs: ExprId, op: Option, }, - RangeFull, - RangeFrom { - lhs: ExprId, - }, - RangeTo { - rhs: ExprId, - }, Range { - lhs: ExprId, - rhs: ExprId, - }, - RangeToInclusive { - rhs: ExprId, - }, - RangeInclusive { - lhs: ExprId, - rhs: ExprId, + lhs: Option, + rhs: Option, + range_type: RangeOp, }, Index { base: ExprId, @@ -302,21 +290,23 @@ impl Expr { Expr::Lambda { body, .. } => { f(*body); } - Expr::BinaryOp { lhs, rhs, .. } - | Expr::Range { lhs, rhs } - | Expr::RangeInclusive { lhs, rhs } => { + Expr::BinaryOp { lhs, rhs, .. } => { f(*lhs); f(*rhs); } + Expr::Range { lhs, rhs, .. } => { + if let Some(lhs) = rhs { + f(*lhs); + } + if let Some(rhs) = lhs { + f(*rhs); + } + } Expr::Index { base, index } => { f(*base); f(*index); } - Expr::RangeFull => {} - Expr::RangeFrom { lhs: expr } - | Expr::RangeTo { rhs: expr } - | Expr::RangeToInclusive { rhs: expr } - | Expr::Field { expr, .. } + Expr::Field { expr, .. } | Expr::Await { expr } | Expr::Try { expr } | Expr::Cast { expr, .. } diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index a00aa426a2..4014f4732d 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -12,6 +12,7 @@ use hir_def::{ AdtId, ContainerId, Lookup, StructFieldId, }; use hir_expand::name::{self, Name}; +use ra_syntax::ast::RangeOp; use crate::{ autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, @@ -415,45 +416,42 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } _ => Ty::Unknown, }, - Expr::RangeFull => match self.resolve_range_full() { - Some(adt) => Ty::simple(TypeCtor::Adt(adt)), - None => Ty::Unknown, - }, - Expr::Range { lhs, rhs } => { - let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); - let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); - match self.resolve_range() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), - None => Ty::Unknown, - } - } - Expr::RangeInclusive { lhs, rhs } => { - let lhs_ty = self.infer_expr(*lhs, &Expectation::none()); - let rhs_ty = self.infer_expr(*rhs, &Expectation::has_type(lhs_ty)); - match self.resolve_range_inclusive() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), rhs_ty), - None => Ty::Unknown, - } - } - Expr::RangeFrom { lhs } => { - let ty = self.infer_expr(*lhs, &Expectation::none()); - match self.resolve_range_from() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), - None => Ty::Unknown, - } - } - Expr::RangeTo { rhs } => { - let ty = self.infer_expr(*rhs, &Expectation::none()); - match self.resolve_range_to() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), - None => Ty::Unknown, - } - } - Expr::RangeToInclusive { rhs } => { - let ty = self.infer_expr(*rhs, &Expectation::none()); - match self.resolve_range_to_inclusive() { - Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), - None => Ty::Unknown, + Expr::Range { lhs, rhs, range_type } => { + let lhs_ty = lhs.map(|e| self.infer_expr(e, &Expectation::none())); + let rhs_expect = lhs_ty + .as_ref() + .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); + let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); + match (range_type, lhs_ty, rhs_ty) { + (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { + Some(adt) => Ty::simple(TypeCtor::Adt(adt)), + None => Ty::Unknown, + }, + (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + }, + (RangeOp::Inclusive, None, Some(ty)) => { + match self.resolve_range_to_inclusive() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + } + } + (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + }, + (RangeOp::Inclusive, Some(_), Some(ty)) => { + match self.resolve_range_inclusive() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + } + } + (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { + Some(adt) => Ty::apply_one(TypeCtor::Adt(adt), ty), + None => Ty::Unknown, + }, + (RangeOp::Inclusive, _, None) => Ty::Unknown, } } Expr::Index { base, index } => { From 9c764cb966cd62d8eaa83fbb7d91646a850dc256 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 29 Nov 2019 15:14:42 +0100 Subject: [PATCH 009/312] Only allow renames to valid identifiers --- crates/ra_lsp_server/src/main_loop/handlers.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index c81fa7f679..137f263027 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -13,7 +13,7 @@ use ra_ide::{ AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, }; use ra_prof::profile; -use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; +use ra_syntax::{tokenize, AstNode, SyntaxKind, TextRange, TextUnit}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use serde_json::to_value; @@ -506,6 +506,12 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result return Ok(None), From f081c9d94dcc7a06e9c224e6b113a563d474ad18 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 29 Nov 2019 15:27:22 +0100 Subject: [PATCH 010/312] Also allow renaming to underscore --- crates/ra_lsp_server/src/main_loop/handlers.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 137f263027..0380788acd 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -508,7 +508,9 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result Date: Fri, 29 Nov 2019 15:52:12 +0100 Subject: [PATCH 011/312] Move identifier check to analysis --- crates/ra_ide/src/lib.rs | 9 ++++++++- crates/ra_lsp_server/src/main_loop/handlers.rs | 12 +----------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index d1bff4a761..1f88791d77 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -56,7 +56,7 @@ use ra_db::{ salsa::{self, ParallelDatabase}, CheckCanceled, Env, FileLoader, SourceDatabase, }; -use ra_syntax::{SourceFile, TextRange, TextUnit}; +use ra_syntax::{tokenize, SourceFile, SyntaxKind, TextRange, TextUnit}; use crate::{db::LineIndexDatabase, display::ToNav, symbol_index::FileSymbol}; @@ -470,6 +470,13 @@ impl Analysis { position: FilePosition, new_name: &str, ) -> Cancelable>> { + let tokens = tokenize(new_name); + if tokens.len() != 1 + || (tokens[0].kind != SyntaxKind::IDENT && tokens[0].kind != SyntaxKind::UNDERSCORE) + { + return Ok(None); + } + self.with_db(|db| references::rename(db, position, new_name)) } diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 0380788acd..ca47ff5e16 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -13,7 +13,7 @@ use ra_ide::{ AssistId, FileId, FilePosition, FileRange, Query, Runnable, RunnableKind, SearchScope, }; use ra_prof::profile; -use ra_syntax::{tokenize, AstNode, SyntaxKind, TextRange, TextUnit}; +use ra_syntax::{AstNode, SyntaxKind, TextRange, TextUnit}; use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use serde_json::to_value; @@ -480,8 +480,6 @@ pub fn handle_prepare_rename( let _p = profile("handle_prepare_rename"); let position = params.try_conv_with(&world)?; - // We support renaming references like handle_rename does. - // In the future we may want to reject the renaming of things like keywords here too. let optional_change = world.analysis().rename(position, "dummy")?; let range = match optional_change { None => return Ok(None), @@ -506,14 +504,6 @@ pub fn handle_rename(world: WorldSnapshot, params: RenameParams) -> Result return Ok(None), From 645df2b5f5664b7730293d8f7441364799aacbf9 Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 29 Nov 2019 16:03:39 +0100 Subject: [PATCH 012/312] Test rename for various identifiers --- crates/ra_ide/src/references/rename.rs | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index ea6b354c20..c1771edf89 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -123,6 +123,49 @@ mod tests { mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, }; + #[test] + fn test_rename_to_underscore() { + test_rename( + r#" + fn main() { + let i<|> = 1; + }"#, + "_", + r#" + fn main() { + let _ = 1; + }"#, + ); + } + + #[test] + fn test_rename_to_raw_identifier() { + test_rename( + r#" + fn main() { + let i<|> = 1; + }"#, + "r#fn", + r#" + fn main() { + let r#fn = 1; + }"#, + ); + } + + #[test] + fn test_rename_to_invalid_identifier() { + let (analysis, position) = single_file_with_position( + " + fn main() { + let i<|> = 1; + }", + ); + let new_name = "invalid!"; + let source_change = analysis.rename(position, new_name).unwrap(); + assert!(source_change.is_none()); + } + #[test] fn test_rename_for_local() { test_rename( From b3856568af3a21bfd13584e06fce852f84811fdb Mon Sep 17 00:00:00 2001 From: Wilco Kusee Date: Fri, 29 Nov 2019 16:06:20 +0100 Subject: [PATCH 013/312] Push identifier check to rename function --- crates/ra_ide/src/lib.rs | 9 +-------- crates/ra_ide/src/references/rename.rs | 9 ++++++++- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 1f88791d77..d1bff4a761 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -56,7 +56,7 @@ use ra_db::{ salsa::{self, ParallelDatabase}, CheckCanceled, Env, FileLoader, SourceDatabase, }; -use ra_syntax::{tokenize, SourceFile, SyntaxKind, TextRange, TextUnit}; +use ra_syntax::{SourceFile, TextRange, TextUnit}; use crate::{db::LineIndexDatabase, display::ToNav, symbol_index::FileSymbol}; @@ -470,13 +470,6 @@ impl Analysis { position: FilePosition, new_name: &str, ) -> Cancelable>> { - let tokens = tokenize(new_name); - if tokens.len() != 1 - || (tokens[0].kind != SyntaxKind::IDENT && tokens[0].kind != SyntaxKind::UNDERSCORE) - { - return Ok(None); - } - self.with_db(|db| references::rename(db, position, new_name)) } diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index c1771edf89..b804d5f6da 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -2,7 +2,7 @@ use hir::ModuleSource; use ra_db::{RelativePath, RelativePathBuf, SourceDatabase, SourceDatabaseExt}; -use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SyntaxNode}; +use ra_syntax::{algo::find_node_at_offset, ast, tokenize, AstNode, SyntaxKind, SyntaxNode}; use ra_text_edit::TextEdit; use crate::{ @@ -17,6 +17,13 @@ pub(crate) fn rename( position: FilePosition, new_name: &str, ) -> Option> { + let tokens = tokenize(new_name); + if tokens.len() != 1 + || (tokens[0].kind != SyntaxKind::IDENT && tokens[0].kind != SyntaxKind::UNDERSCORE) + { + return None; + } + let parse = db.parse(position.file_id); if let Some((ast_name, ast_module)) = find_name_and_module_at_offset(parse.tree().syntax(), position) From 9c01c0dcb5308d8d50ddf2d3fad6599fbff7d3dd Mon Sep 17 00:00:00 2001 From: Alexander Ekdahl Date: Fri, 29 Nov 2019 19:20:48 -0500 Subject: [PATCH 014/312] Use env_logger in ra_cli --- Cargo.lock | 22 +++++++++++++++++++++- crates/ra_cli/Cargo.toml | 7 ++++++- crates/ra_cli/src/main.rs | 3 +-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2557b5e59d..d418f2d96a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -323,6 +323,15 @@ name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.2.8" @@ -453,6 +462,14 @@ dependencies = [ "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.2.0" @@ -928,7 +945,8 @@ dependencies = [ name = "ra_cli" version = "0.1.0" dependencies = [ - "flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_batch 0.1.0", "ra_db 0.1.0", @@ -1843,6 +1861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8944dc8fa28ce4a38f778bd46bf7d923fe73eed5a439398507246c8e017e6f36" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" "checksum flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a13ea6b8a4debecf47bf3966d56db0e21366bc3a3649ba159e1a9e6fdd36a4f4" @@ -1860,6 +1879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index c7e0d0f0f3..9718b4b544 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml @@ -7,7 +7,7 @@ publish = false [dependencies] pico-args = "0.3.0" -flexi_logger = "0.14.0" +log = "0.4" ra_syntax = { path = "../ra_syntax" } ra_ide = { path = "../ra_ide" } @@ -19,3 +19,8 @@ ra_db = { path = "../ra_db" } path = "../ra_prof" # features = [ "cpu_profiler" ] # features = [ "jemalloc" ] + +[dependencies.env_logger] +version = "0.7.1" +default-features = false +features = ["humantime"] diff --git a/crates/ra_cli/src/main.rs b/crates/ra_cli/src/main.rs index fe847e6112..3808590abe 100644 --- a/crates/ra_cli/src/main.rs +++ b/crates/ra_cli/src/main.rs @@ -7,7 +7,6 @@ mod progress_report; use std::{error::Error, fmt::Write, io::Read}; -use flexi_logger::Logger; use pico_args::Arguments; use ra_ide::{file_structure, Analysis}; use ra_prof::profile; @@ -32,7 +31,7 @@ impl Verbosity { } fn main() -> Result<()> { - Logger::with_env_or_str("error").start()?; + env_logger::try_init()?; let subcommand = match std::env::args_os().nth(1) { None => { From eb4e70fc676a97a7b411f372be1727df51a8906a Mon Sep 17 00:00:00 2001 From: Alexander Ekdahl Date: Fri, 29 Nov 2019 19:35:03 -0500 Subject: [PATCH 015/312] Remove flexi_logger from ra_lsp_server --- Cargo.lock | 59 +------------------ crates/ra_cli/Cargo.toml | 6 +- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/main.rs | 7 +-- .../ra_lsp_server/tests/heavy_tests/main.rs | 1 - .../tests/heavy_tests/support.rs | 3 +- 6 files changed, 5 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d418f2d96a..6d4d80a9dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -186,16 +186,6 @@ dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "chrono" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "clicolors-control" version = "1.0.1" @@ -348,18 +338,6 @@ name = "fixedbitset" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "flexi_logger" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fnv" version = "1.0.6" @@ -429,11 +407,6 @@ dependencies = [ "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "globset" version = "0.4.4" @@ -739,15 +712,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-traits" version = "0.2.10" @@ -1078,7 +1042,7 @@ name = "ra_lsp_server" version = "0.1.0" dependencies = [ "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1665,16 +1629,6 @@ dependencies = [ "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "time" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unicase" version = "2.6.0" @@ -1816,11 +1770,6 @@ dependencies = [ "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "yansi" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum anyhow 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b412394828b7ca486b362f300b762d8e43dafd6f0d727b63f1cd2ade207c6cef" @@ -1845,7 +1794,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" "checksum chalk-rust-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" "checksum chalk-solve 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" @@ -1864,7 +1812,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flexi_logger 0.14.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a13ea6b8a4debecf47bf3966d56db0e21366bc3a3649ba159e1a9e6fdd36a4f4" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f7aea5a5909a74969507051a3b17adc84737e31a5f910559892aedce026f4d53" "checksum fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f2a4a2034423744d2cc7ca2068453168dcdb82c438419e639a26bd87839c674" @@ -1875,7 +1822,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" -"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" @@ -1911,7 +1857,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891f486f630e5c5a4916c7e16c4b24a53e78c860b646e9f8e005e4f16847bfed" @@ -1984,7 +1929,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thin-dst 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c52fd98a9e4913c466d83381a59245691875d2f3e04611fca57f964bd8aa96e1" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" @@ -2003,4 +1947,3 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" -"checksum yansi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9fc79f4a1e39857fc00c3f662cbf2651c771f00e9c15fe2abc341806bd46bd71" diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index 9718b4b544..f63f40c990 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] pico-args = "0.3.0" log = "0.4" +env_logger = { version = "0.7.1", default-features = false, features = ["humantime"] } ra_syntax = { path = "../ra_syntax" } ra_ide = { path = "../ra_ide" } @@ -19,8 +20,3 @@ ra_db = { path = "../ra_db" } path = "../ra_prof" # features = [ "cpu_profiler" ] # features = [ "jemalloc" ] - -[dependencies.env_logger] -version = "0.7.1" -default-features = false -features = ["humantime"] diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 21aef842ce..41672eaffe 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -13,7 +13,6 @@ relative-path = "1.0.0" serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" -flexi_logger = "0.14.0" log = "0.4.3" lsp-types = { version = "0.61.0", features = ["proposed"] } rustc-hash = "1.0" @@ -27,6 +26,7 @@ lsp-server = "0.3.0" ra_project_model = { path = "../ra_project_model" } ra_prof = { path = "../ra_prof" } ra_vfs_glob = { path = "../ra_vfs_glob" } +env_logger = { version = "0.7.1", default-features = false, features = ["humantime"] } [dev-dependencies] tempfile = "3" diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index e13c8ca144..8076a7fa5c 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs @@ -1,6 +1,5 @@ //! `ra_lsp_server` binary -use flexi_logger::{Duplicate, Logger}; use lsp_server::Connection; use ra_lsp_server::{show_message, Result, ServerConfig}; use ra_prof; @@ -14,11 +13,7 @@ fn main() -> Result<()> { fn setup_logging() -> Result<()> { std::env::set_var("RUST_BACKTRACE", "short"); - let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); - match std::env::var("RA_LOG_DIR") { - Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, - _ => logger.start()?, - }; + env_logger::try_init()?; ra_prof::set_filter(match std::env::var("RA_PROFILE") { Ok(spec) => ra_prof::Filter::from_spec(&spec), diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index 2ba82ab051..29224cbe8e 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -15,7 +15,6 @@ use tempfile::TempDir; use crate::support::{project, Project}; -const LOG: &'static str = ""; const PROFILE: &'static str = ""; // const PROFILE: &'static str = "*@3>100"; diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index 86073b57df..d5ea52fa95 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs @@ -7,7 +7,6 @@ use std::{ }; use crossbeam_channel::{after, select, Receiver}; -use flexi_logger::Logger; use lsp_server::{Connection, Message, Notification, Request}; use lsp_types::{ notification::{DidOpenTextDocument, Exit}, @@ -53,7 +52,7 @@ impl<'a> Project<'a> { let tmp_dir = self.tmp_dir.unwrap_or_else(|| TempDir::new().unwrap()); static INIT: Once = Once::new(); INIT.call_once(|| { - let _ = Logger::with_env_or_str(crate::LOG).start().unwrap(); + let _ = env_logger::builder().is_test(true).try_init().unwrap(); ra_prof::set_filter(if crate::PROFILE.is_empty() { ra_prof::Filter::disabled() } else { From 1793abf4fd1382a8b9bae798139aaebdc33b673e Mon Sep 17 00:00:00 2001 From: Alexander Ekdahl Date: Fri, 29 Nov 2019 19:36:48 -0500 Subject: [PATCH 016/312] Update README --- docs/dev/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/dev/README.md b/docs/dev/README.md index 0f64d7e5f8..2f6215d6bb 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md @@ -124,9 +124,8 @@ Logging is done by both rust-analyzer and VS Code, so it might be tricky to figure out where logs go. Inside rust-analyzer, we use the standard `log` crate for logging, and -`flexi_logger` for logging frotend. By default, log goes to stderr (the same as -with `env_logger`), but the stderr itself is processed by VS Code. To mirror -logs to a `./log` directory, set `RA_LOG_DIR=1` environmental variable. +`env_logger` for logging frontend. By default, log goes to stderr, but the +stderr itself is processed by VS Code. To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`. This shows `eprintln!` as well. Note that From 3fe539ce51f417605a6da6bc3c6d135053b1ee67 Mon Sep 17 00:00:00 2001 From: Alexander Ekdahl Date: Fri, 29 Nov 2019 19:40:59 -0500 Subject: [PATCH 017/312] Remove log dependency from ra_cli --- Cargo.lock | 1 - crates/ra_cli/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6d4d80a9dc..83e41940bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -910,7 +910,6 @@ name = "ra_cli" version = "0.1.0" dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_batch 0.1.0", "ra_db 0.1.0", diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index f63f40c990..21a37c7bf4 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml @@ -7,7 +7,6 @@ publish = false [dependencies] pico-args = "0.3.0" -log = "0.4" env_logger = { version = "0.7.1", default-features = false, features = ["humantime"] } ra_syntax = { path = "../ra_syntax" } From cf6809645e2327e20edd30eb535d4f06fa116b5c Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 30 Nov 2019 12:35:37 +0100 Subject: [PATCH 018/312] Handle cycles in impl types better - impl Trait for S is allowed - impl Trait for S is an invalid cycle, but we can add cycle recovery for it in Salsa now --- crates/ra_hir_ty/src/db.rs | 10 ++++-- crates/ra_hir_ty/src/infer/coerce.rs | 7 ++-- crates/ra_hir_ty/src/infer/path.rs | 2 +- crates/ra_hir_ty/src/lib.rs | 15 -------- crates/ra_hir_ty/src/lower.rs | 35 +++++++++++-------- crates/ra_hir_ty/src/method_resolution.rs | 9 ++--- crates/ra_hir_ty/src/tests.rs | 42 +++++++++++++++++++++++ crates/ra_hir_ty/src/traits/chalk.rs | 15 +++----- 8 files changed, 82 insertions(+), 53 deletions(-) diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 9ce1545939..6ecc0b0966 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -11,7 +11,7 @@ use ra_db::{salsa, CrateId}; use crate::{ method_resolution::CrateImplBlocks, traits::{AssocTyValue, Impl}, - CallableDef, FnSig, GenericPredicate, ImplTy, InferenceResult, Substs, Ty, TyDefId, TypeCtor, + CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, }; @@ -27,8 +27,12 @@ pub trait HirDatabase: DefDatabase { #[salsa::invoke(crate::lower::value_ty_query)] fn value_ty(&self, def: ValueTyDefId) -> Ty; - #[salsa::invoke(crate::lower::impl_ty_query)] - fn impl_ty(&self, def: ImplId) -> ImplTy; + #[salsa::invoke(crate::lower::impl_self_ty_query)] + #[salsa::cycle(crate::lower::impl_self_ty_recover)] + fn impl_self_ty(&self, def: ImplId) -> Ty; + + #[salsa::invoke(crate::lower::impl_trait_query)] + fn impl_trait(&self, def: ImplId) -> Option; #[salsa::invoke(crate::lower::field_types_query)] fn field_types(&self, var: VariantId) -> Arc>; diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 719a0f3957..064993d34f 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -8,7 +8,7 @@ use hir_def::{lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutabilit use rustc_hash::FxHashMap; use test_utils::tested_by; -use crate::{autoderef, db::HirDatabase, ImplTy, Substs, Ty, TypeCtor, TypeWalk}; +use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; @@ -54,10 +54,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { impls .iter() .filter_map(|&impl_id| { - let trait_ref = match db.impl_ty(impl_id) { - ImplTy::TraitRef(it) => it, - ImplTy::Inherent(_) => return None, - }; + let trait_ref = db.impl_trait(impl_id)?; // `CoerseUnsized` has one generic parameter for the target type. let cur_from_ty = trait_ref.substs.0.get(0)?; diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 14be668365..bbf146418e 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -244,7 +244,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ContainerId::ImplId(it) => it, _ => return None, }; - let self_ty = self.db.impl_ty(impl_id).self_type().clone(); + let self_ty = self.db.impl_self_ty(impl_id).clone(); let self_ty_substs = self_ty.substs()?; let actual_substs = actual_def_ty.substs()?; diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index b45c8f82f4..3c1f738dfc 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -486,21 +486,6 @@ impl TypeWalk for TraitRef { } } -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum ImplTy { - Inherent(Ty), - TraitRef(TraitRef), -} - -impl ImplTy { - pub(crate) fn self_type(&self) -> &Ty { - match self { - ImplTy::Inherent(it) => it, - ImplTy::TraitRef(tr) => &tr.substs[0], - } - } -} - /// Like `generics::WherePredicate`, but with resolved types: A condition on the /// parameters of a generic item. #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 091c60f4fe..a646406f18 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -27,8 +27,8 @@ use crate::{ all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, variant_data, }, - FnSig, GenericPredicate, ImplTy, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, - TraitRef, Ty, TypeCtor, TypeWalk, + FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, + Ty, TypeCtor, TypeWalk, }; impl Ty { @@ -179,7 +179,7 @@ impl Ty { let name = resolved_segment.name.clone(); Ty::Param { idx, name } } - TypeNs::SelfType(impl_id) => db.impl_ty(impl_id).self_type().clone(), + TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), TypeNs::AdtSelfType(adt) => db.ty(adt.into()), TypeNs::AdtId(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()), @@ -743,17 +743,24 @@ pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { } } -pub(crate) fn impl_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> ImplTy { +pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Ty { let impl_data = db.impl_data(impl_id); let resolver = impl_id.resolver(db); - let self_ty = Ty::from_hir(db, &resolver, &impl_data.target_type); - match impl_data.target_trait.as_ref() { - Some(trait_ref) => { - match TraitRef::from_hir(db, &resolver, trait_ref, Some(self_ty.clone())) { - Some(it) => ImplTy::TraitRef(it), - None => ImplTy::Inherent(self_ty), - } - } - None => ImplTy::Inherent(self_ty), - } + Ty::from_hir(db, &resolver, &impl_data.target_type) +} + +pub(crate) fn impl_self_ty_recover( + _db: &impl HirDatabase, + _cycle: &[String], + _impl_id: &ImplId, +) -> Ty { + Ty::Unknown +} + +pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option { + let impl_data = db.impl_data(impl_id); + let resolver = impl_id.resolver(db); + let self_ty = db.impl_self_ty(impl_id); + let target_trait = impl_data.target_trait.as_ref()?; + TraitRef::from_hir(db, &resolver, target_trait, Some(self_ty.clone())) } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index ee1936b0e5..2bded3dbdc 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -19,7 +19,7 @@ use crate::{ db::HirDatabase, primitive::{FloatBitness, Uncertain}, utils::all_super_traits, - Canonical, ImplTy, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, + Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, }; /// This is used as a key for indexing impls. @@ -58,11 +58,12 @@ impl CrateImplBlocks { let crate_def_map = db.crate_def_map(krate); for (_module_id, module_data) in crate_def_map.modules.iter() { for &impl_id in module_data.impls.iter() { - match db.impl_ty(impl_id) { - ImplTy::TraitRef(tr) => { + match db.impl_trait(impl_id) { + Some(tr) => { res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); } - ImplTy::Inherent(self_ty) => { + None => { + let self_ty = db.impl_self_ty(impl_id); if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty) { res.impls.entry(self_ty_fp).or_default().push(impl_id); } diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 4ba87e667a..b72f0f2797 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -4675,6 +4675,48 @@ fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { assert_eq!(t, "u32"); } +#[test] +fn trait_impl_self_ty() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo()<|>; +} +"#, + ); + assert_eq!(t, "()"); +} + +#[test] +fn trait_impl_self_ty_cycle() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo()<|>; +} +"#, + ); + assert_eq!(t, "{unknown}"); +} + #[test] // FIXME this is currently a Salsa panic; it would be nicer if it just returned // in Unknown, and we should be able to do that once Salsa allows us to handle diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 35de37e6b6..104346ada5 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -20,8 +20,8 @@ use ra_db::salsa::{InternId, InternKey}; use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ - db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ImplTy, ProjectionTy, - Substs, TraitRef, Ty, TypeCtor, TypeWalk, + db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, + TraitRef, Ty, TypeCtor, TypeWalk, }; /// This represents a trait whose name we could not resolve. @@ -630,10 +630,7 @@ fn impl_block_datum( chalk_id: chalk_ir::ImplId, impl_id: ImplId, ) -> Option>> { - let trait_ref = match db.impl_ty(impl_id) { - ImplTy::TraitRef(it) => it, - ImplTy::Inherent(_) => return None, - }; + let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); let generic_params = db.generic_params(impl_id.into()); @@ -787,11 +784,7 @@ fn type_alias_associated_ty_value( _ => panic!("assoc ty value should be in impl"), }; - let trait_ref = match db.impl_ty(impl_id) { - ImplTy::TraitRef(it) => it, - // we don't return any assoc ty values if the impl'd trait can't be resolved - ImplTy::Inherent(_) => panic!("assoc ty value should not exist"), - }; + let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist"); // we don't return any assoc ty values if the impl'd trait can't be resolved let assoc_ty = db .trait_data(trait_ref.trait_) From 3ca40f7c08718a44c6d08d2cbe060244340e7157 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 30 Nov 2019 12:39:21 +0100 Subject: [PATCH 019/312] Add cycle recovery for generic predicates --- crates/ra_hir_ty/src/db.rs | 1 + crates/ra_hir_ty/src/lower.rs | 9 +++++++++ crates/ra_hir_ty/src/tests.rs | 8 -------- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 6ecc0b0966..8e461e3592 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -41,6 +41,7 @@ pub trait HirDatabase: DefDatabase { fn callable_item_signature(&self, def: CallableDef) -> FnSig; #[salsa::invoke(crate::lower::generic_predicates_for_param_query)] + #[salsa::cycle(crate::lower::generic_predicates_for_param_recover)] fn generic_predicates_for_param( &self, def: GenericDefId, diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index a646406f18..c6ee75c7ae 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -532,6 +532,15 @@ pub(crate) fn generic_predicates_for_param_query( .collect() } +pub(crate) fn generic_predicates_for_param_recover( + _db: &impl HirDatabase, + _cycle: &[String], + _def: &GenericDefId, + _param_idx: &u32, +) -> Arc<[GenericPredicate]> { + Arc::new([]) +} + impl TraitEnvironment { pub fn lower(db: &impl HirDatabase, resolver: &Resolver) -> Arc { let predicates = resolver diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index b72f0f2797..552eb8f75a 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -4718,10 +4718,6 @@ fn test() { } #[test] -// FIXME this is currently a Salsa panic; it would be nicer if it just returned -// in Unknown, and we should be able to do that once Salsa allows us to handle -// the cycle. But at least it doesn't overflow for now. -#[should_panic] fn unselected_projection_in_trait_env_cycle_1() { let t = type_at( r#" @@ -4742,10 +4738,6 @@ fn test() where T: Trait2 { } #[test] -// FIXME this is currently a Salsa panic; it would be nicer if it just returned -// in Unknown, and we should be able to do that once Salsa allows us to handle -// the cycle. But at least it doesn't overflow for now. -#[should_panic] fn unselected_projection_in_trait_env_cycle_2() { let t = type_at( r#" From 1c622e9fed97de7711da7b5bffec0fa4b19d7500 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 30 Nov 2019 12:48:51 +0100 Subject: [PATCH 020/312] Add cycle recovery for type aliases --- crates/ra_hir_ty/src/db.rs | 1 + crates/ra_hir_ty/src/lower.rs | 5 +++++ crates/ra_hir_ty/src/tests.rs | 6 ++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 8e461e3592..222a36a9f8 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -22,6 +22,7 @@ pub trait HirDatabase: DefDatabase { fn infer(&self, def: DefWithBodyId) -> Arc; #[salsa::invoke(crate::lower::ty_query)] + #[salsa::cycle(crate::lower::ty_recover)] fn ty(&self, def: TyDefId) -> Ty; #[salsa::invoke(crate::lower::value_ty_query)] diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index c6ee75c7ae..32569ac66f 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -742,6 +742,11 @@ pub(crate) fn ty_query(db: &impl HirDatabase, def: TyDefId) -> Ty { TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), } } + +pub(crate) fn ty_recover(_db: &impl HirDatabase, _cycle: &[String], _def: &TyDefId) -> Ty { + Ty::Unknown +} + pub(crate) fn value_ty_query(db: &impl HirDatabase, def: ValueTyDefId) -> Ty { match def { ValueTyDefId::FunctionId(it) => type_for_fn(db, it), diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 552eb8f75a..c856d6afdb 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -2154,7 +2154,6 @@ fn test(x: Foo, y: Bar<&str>, z: Baz) { } #[test] -#[should_panic] // we currently can't handle this fn recursive_type_alias() { assert_snapshot!( infer(r#" @@ -2163,7 +2162,10 @@ type Foo = Foo; type Bar = A; fn test(x: Foo) {} "#), - @"" + @r###" + [59; 60) 'x': {unknown} + [67; 69) '{}': () + "### ) } From bb601e7eafa00e471a5306ac920f0be6c809aab0 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 30 Nov 2019 23:29:21 +0800 Subject: [PATCH 021/312] Add BuiltinShadowMode --- crates/ra_hir/src/source_binder.rs | 2 +- crates/ra_hir_def/src/body.rs | 7 +- crates/ra_hir_def/src/nameres.rs | 30 +++++++- crates/ra_hir_def/src/nameres/collector.rs | 4 +- .../ra_hir_def/src/nameres/path_resolution.rs | 71 +++++++++++++++---- crates/ra_hir_def/src/resolver.rs | 38 +++++++--- crates/ra_hir_ty/src/tests.rs | 36 ++++++++++ 7 files changed, 157 insertions(+), 31 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 1661d92a2e..0df7a7cb49 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -286,7 +286,7 @@ impl SourceAnalyzer { let items = self .resolver - .resolve_module_path(db, &path) + .resolve_module_path_in_items(db, &path) .take_types() .map(|it| PathResolution::Def(it.into())); types.or(values).or(items).or_else(|| { diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 69508dd8a5..239f35229a 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -15,7 +15,7 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, - nameres::CrateDefMap, + nameres::{BuiltinShadowMode, CrateDefMap}, path::Path, src::HasSource, DefWithBodyId, HasModule, Lookup, ModuleId, @@ -83,7 +83,10 @@ impl Expander { } fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option { - self.crate_def_map.resolve_path(db, self.module.local_id, path).0.take_macros() + self.crate_def_map + .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) + .0 + .take_macros() } } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index df42ea84a2..9aaf7736bd 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -149,6 +149,16 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { .collect() }); +/// Shadow mode for builtin type +/// Builtin type can be shadowed by same name mode +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum BuiltinShadowMode { + // Prefer Module + Module, + // Prefer Other Types + Other, +} + /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ModuleScope { @@ -178,8 +188,20 @@ impl ModuleScope { } /// Get a name from current module scope, legacy macros are not included - pub fn get(&self, name: &Name) -> Option<&Resolution> { - self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)) + pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + match shadow { + BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Other => { + let item = self.items.get(name); + if let Some(res) = item { + if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { + return BUILTIN_SCOPE.get(name).or(item); + } + } + + item.or_else(|| BUILTIN_SCOPE.get(name)) + } + } } pub fn traits<'a>(&'a self) -> impl Iterator + 'a { @@ -250,8 +272,10 @@ impl CrateDefMap { db: &impl DefDatabase, original_module: LocalModuleId, path: &Path, + shadow: BuiltinShadowMode, ) -> (PerNs, Option) { - let res = self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path); + let res = + self.resolve_path_fp_with_macro(db, ResolveMode::Other, original_module, path, shadow); (res.resolved_def, res.segment_index) } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index fd82451131..d4bfcae1d2 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -19,7 +19,7 @@ use crate::{ db::DefDatabase, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, - raw, CrateDefMap, ModuleData, Resolution, ResolveMode, + raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode, }, path::{Path, PathKind}, per_ns::PerNs, @@ -299,6 +299,7 @@ where ResolveMode::Import, module_id, &import.path, + BuiltinShadowMode::Module, ); (res.resolved_def, res.reached_fixedpoint) @@ -477,6 +478,7 @@ where ResolveMode::Other, *module_id, path, + BuiltinShadowMode::Module, ); if let Some(def) = resolved_res.resolved_def.take_macros() { diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index b72c55bd10..174ae9d384 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -16,7 +16,7 @@ use test_utils::tested_by; use crate::{ db::DefDatabase, - nameres::CrateDefMap, + nameres::{BuiltinShadowMode, CrateDefMap}, path::{Path, PathKind}, per_ns::PerNs, AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, @@ -68,8 +68,10 @@ impl CrateDefMap { mode: ResolveMode, original_module: LocalModuleId, path: &Path, + shadow: BuiltinShadowMode, ) -> ResolvePathResult { - let mut segments = path.segments.iter().enumerate(); + let mut segments = path.segments.iter().enumerate().peekable(); + let mut curr_per_ns: PerNs = match path.kind { PathKind::DollarCrate(krate) => { if krate == self.krate { @@ -101,7 +103,11 @@ impl CrateDefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude(&segment.name) + + self.resolve_name_in_crate_root_or_extern_prelude( + &segment.name, + prefer_module(&mut segments, shadow), + ) } PathKind::Plain => { let segment = match segments.next() { @@ -109,7 +115,12 @@ impl CrateDefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in module", segment); - self.resolve_name_in_module(db, original_module, &segment.name) + self.resolve_name_in_module( + db, + original_module, + &segment.name, + prefer_module(&mut segments, shadow), + ) } PathKind::Super => { if let Some(p) = self.modules[original_module].parent { @@ -139,7 +150,7 @@ impl CrateDefMap { } }; - for (i, segment) in segments { + while let Some((i, segment)) = segments.next() { let curr = match curr_per_ns.take_types() { Some(r) => r, None => { @@ -160,7 +171,7 @@ impl CrateDefMap { Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; log::debug!("resolving {:?} in other crate", path); let defp_map = db.crate_def_map(module.krate); - let (def, s) = defp_map.resolve_path(db, module.local_id, &path); + let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); return ResolvePathResult::with( def, ReachedFixedPoint::Yes, @@ -169,7 +180,10 @@ impl CrateDefMap { } // Since it is a qualified path here, it should not contains legacy macros - match self[module.local_id].scope.get(&segment.name) { + match self[module.local_id] + .scope + .get(&segment.name, prefer_module(&mut segments, shadow)) + { Some(res) => res.def, _ => { log::debug!("path segment {:?} not found", segment.name); @@ -212,7 +226,22 @@ impl CrateDefMap { } }; } - ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) + return ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None); + + // if it is not the last segment, we prefer builtin as module + fn prefer_module( + segments: &mut std::iter::Peekable, + shadow: BuiltinShadowMode, + ) -> BuiltinShadowMode + where + I: Iterator, + { + if segments.peek().is_some() { + BuiltinShadowMode::Module + } else { + shadow + } + } } fn resolve_name_in_module( @@ -220,6 +249,7 @@ impl CrateDefMap { db: &impl DefDatabase, module: LocalModuleId, name: &Name, + shadow: BuiltinShadowMode, ) -> PerNs { // Resolve in: // - legacy scope of macro @@ -228,23 +258,33 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = self[module].scope.get(name).map_or_else(PerNs::none, |res| res.def); + let from_scope = + self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); - let from_prelude = self.resolve_in_prelude(db, name); + let from_prelude = self.resolve_in_prelude(db, name, shadow); from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude) } - fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> PerNs { + fn resolve_name_in_crate_root_or_extern_prelude( + &self, + name: &Name, + shadow: BuiltinShadowMode, + ) -> PerNs { let from_crate_root = - self[self.root].scope.get(name).map_or_else(PerNs::none, |res| res.def); + self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) } - fn resolve_in_prelude(&self, db: &impl DefDatabase, name: &Name) -> PerNs { + fn resolve_in_prelude( + &self, + db: &impl DefDatabase, + name: &Name, + shadow: BuiltinShadowMode, + ) -> PerNs { if let Some(prelude) = self.prelude { let keep; let def_map = if prelude.krate == self.krate { @@ -254,7 +294,10 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id].scope.get(name).map_or_else(PerNs::none, |res| res.def) + def_map[prelude.local_id] + .scope + .get(name, shadow) + .map_or_else(PerNs::none, |res| res.def) } else { PerNs::none() } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 0847f6dcf4..7d4df222e3 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -14,7 +14,7 @@ use crate::{ db::DefDatabase, expr::{ExprId, PatId}, generics::GenericParams, - nameres::CrateDefMap, + nameres::{BuiltinShadowMode, CrateDefMap}, path::{Path, PathKind}, per_ns::PerNs, AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, @@ -91,7 +91,7 @@ pub enum ValueNs { impl Resolver { /// Resolve known trait from std, like `std::futures::Future` pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; + let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::TraitId(it) => Some(it), _ => None, @@ -100,7 +100,7 @@ impl Resolver { /// Resolve known struct from std, like `std::boxed::Box` pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; + let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), _ => None, @@ -109,26 +109,34 @@ impl Resolver { /// Resolve known enum from std, like `std::result::Result` pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option { - let res = self.resolve_module_path(db, path).take_types()?; + let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), _ => None, } } - /// pub only for source-binder - pub fn resolve_module_path(&self, db: &impl DefDatabase, path: &Path) -> PerNs { + fn resolve_module_path( + &self, + db: &impl DefDatabase, + path: &Path, + shadow: BuiltinShadowMode, + ) -> PerNs { let (item_map, module) = match self.module() { Some(it) => it, None => return PerNs::none(), }; - let (module_res, segment_index) = item_map.resolve_path(db, module, path); + let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); if segment_index.is_some() { return PerNs::none(); } module_res } + pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &Path) -> PerNs { + self.resolve_module_path(db, path, BuiltinShadowMode::Module) + } + pub fn resolve_path_in_type_ns( &self, db: &impl DefDatabase, @@ -163,7 +171,12 @@ impl Resolver { } } Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); + let (module_def, idx) = m.crate_def_map.resolve_path( + db, + m.module_id, + path, + BuiltinShadowMode::Other, + ); let res = match module_def.take_types()? { ModuleDefId::AdtId(it) => TypeNs::AdtId(it), ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), @@ -256,7 +269,12 @@ impl Resolver { Scope::ImplBlockScope(_) | Scope::AdtScope(_) => continue, Scope::ModuleScope(m) => { - let (module_def, idx) = m.crate_def_map.resolve_path(db, m.module_id, path); + let (module_def, idx) = m.crate_def_map.resolve_path( + db, + m.module_id, + path, + BuiltinShadowMode::Other, + ); return match idx { None => { let value = match module_def.take_values()? { @@ -310,7 +328,7 @@ impl Resolver { pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option { let (item_map, module) = self.module()?; - item_map.resolve_path(db, module, path).0.take_macros() + item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() } pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index abbc1546cb..3766ab9813 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -3641,6 +3641,42 @@ fn main() { assert_eq!(t, "Foo"); } +#[test] +fn not_shadowing_primitive_by_module() { + let t = type_at( + r#" +//- /str.rs +fn foo() {} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + foo()<|>; +}"#, + ); + assert_eq!(t, "&str"); +} + +#[test] +fn not_shadowing_module_by_primitive() { + let t = type_at( + r#" +//- /str.rs +fn foo() -> u32 {0} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + str::foo()<|>; +}"#, + ); + assert_eq!(t, "u32"); +} + #[test] fn deref_trait() { let t = type_at( From c69ed9bd1f83e172def2678550ab4dd7c1b1dc1a Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sat, 30 Nov 2019 21:20:54 -0500 Subject: [PATCH 022/312] Clarify installation instructions In particular it is necessary to clone the repository before running the other commands. I also removed the `cargo install` side note because it didn't actually work (running the command just produces an error that --package isn't a recognized flag) and added a tldr code block with the list of commands to run. --- docs/user/README.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/docs/user/README.md b/docs/user/README.md index 913ecea18d..35c40164ba 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -1,14 +1,19 @@ The main interface to rust-analyzer is the -[LSP](https://microsoft.github.io/language-server-protocol/) implementation. To -install lsp server, use `cargo xtask install --server`, which is a shorthand for `cargo -install --package ra_lsp_server`. The binary is named `ra_lsp_server`, you -should be able to use it with any LSP-compatible editor. We use custom -extensions to LSP, so special client-side support is required to take full -advantage of rust-analyzer. This repository contains support code for VS Code -and Emacs. +[LSP](https://microsoft.github.io/language-server-protocol/) +implementation. To install lsp server, clone the repository and +then run `cargo xtask install --server`. This will produce a +binary named `ra_lsp_server` which you should be able to use it +with any LSP-compatible editor. We use custom extensions to LSP, +so special client-side support is required to take full advantage +of rust-analyzer. This repository contains support code for VS +Code and Emacs. -Rust Analyzer needs sources of rust standard library to work, so you might need -to execute +``` +$ git clone git@github.com:rust-analyzer/rust-analyzer && cd rust-analyzer +$ cargo xtask install --server +``` +Rust Analyzer needs sources of rust standard library to work, so +you might also need to execute ``` $ rustup component add rust-src From 5f1111773301a084ec8d0b6a2c81be5a756241ab Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 1 Dec 2019 12:14:12 +0800 Subject: [PATCH 023/312] Fix comment --- crates/ra_hir_def/src/nameres.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 9aaf7736bd..3e15218704 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -149,8 +149,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { .collect() }); -/// Shadow mode for builtin type -/// Builtin type can be shadowed by same name mode +/// Shadow mode for builtin type which can be shadowed by module. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum BuiltinShadowMode { // Prefer Module From 13c54685ffbc153d4d675f13222dfb02b0f30926 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 1 Dec 2019 12:14:35 +0800 Subject: [PATCH 024/312] Use index instead of peekable --- .../ra_hir_def/src/nameres/path_resolution.rs | 54 +++++++------------ 1 file changed, 19 insertions(+), 35 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 174ae9d384..19d57baae4 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -70,7 +70,16 @@ impl CrateDefMap { path: &Path, shadow: BuiltinShadowMode, ) -> ResolvePathResult { - let mut segments = path.segments.iter().enumerate().peekable(); + // if it is not the last segment, we prefer the module to the builtin + let prefer_module = |index| { + if index == path.segments.len() - 1 { + shadow + } else { + BuiltinShadowMode::Module + } + }; + + let mut segments = path.segments.iter().enumerate(); let mut curr_per_ns: PerNs = match path.kind { PathKind::DollarCrate(krate) => { @@ -98,29 +107,21 @@ impl CrateDefMap { if self.edition == Edition::Edition2015 && (path.kind == PathKind::Abs || mode == ResolveMode::Import) => { - let segment = match segments.next() { - Some((_, segment)) => segment, + let (idx, segment) = match segments.next() { + Some((idx, segment)) => (idx, segment), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude( - &segment.name, - prefer_module(&mut segments, shadow), - ) + self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx)) } PathKind::Plain => { - let segment = match segments.next() { - Some((_, segment)) => segment, + let (idx, segment) = match segments.next() { + Some((idx, segment)) => (idx, segment), None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in module", segment); - self.resolve_name_in_module( - db, - original_module, - &segment.name, - prefer_module(&mut segments, shadow), - ) + self.resolve_name_in_module(db, original_module, &segment.name, prefer_module(idx)) } PathKind::Super => { if let Some(p) = self.modules[original_module].parent { @@ -150,7 +151,7 @@ impl CrateDefMap { } }; - while let Some((i, segment)) = segments.next() { + for (i, segment) in segments { let curr = match curr_per_ns.take_types() { Some(r) => r, None => { @@ -180,10 +181,7 @@ impl CrateDefMap { } // Since it is a qualified path here, it should not contains legacy macros - match self[module.local_id] - .scope - .get(&segment.name, prefer_module(&mut segments, shadow)) - { + match self[module.local_id].scope.get(&segment.name, prefer_module(i)) { Some(res) => res.def, _ => { log::debug!("path segment {:?} not found", segment.name); @@ -226,22 +224,8 @@ impl CrateDefMap { } }; } - return ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None); - // if it is not the last segment, we prefer builtin as module - fn prefer_module( - segments: &mut std::iter::Peekable, - shadow: BuiltinShadowMode, - ) -> BuiltinShadowMode - where - I: Iterator, - { - if segments.peek().is_some() { - BuiltinShadowMode::Module - } else { - shadow - } - } + ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) } fn resolve_name_in_module( From cfc6e9e36646aa3b961018be875a7c3474aa7577 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 1 Dec 2019 12:17:52 +0800 Subject: [PATCH 025/312] Remove some empty lines --- crates/ra_hir_def/src/nameres/path_resolution.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 19d57baae4..42a75226ba 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -80,7 +80,6 @@ impl CrateDefMap { }; let mut segments = path.segments.iter().enumerate(); - let mut curr_per_ns: PerNs = match path.kind { PathKind::DollarCrate(krate) => { if krate == self.krate { @@ -112,7 +111,6 @@ impl CrateDefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx)) } PathKind::Plain => { From 75be6553fef0256bc57d438dac4b2f66473156f4 Mon Sep 17 00:00:00 2001 From: Jonathan Behrens Date: Sun, 1 Dec 2019 13:29:01 -0500 Subject: [PATCH 026/312] Add back corrected `cargo install` command --- docs/user/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/user/README.md b/docs/user/README.md index 35c40164ba..adacead52c 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -1,12 +1,12 @@ The main interface to rust-analyzer is the -[LSP](https://microsoft.github.io/language-server-protocol/) -implementation. To install lsp server, clone the repository and -then run `cargo xtask install --server`. This will produce a -binary named `ra_lsp_server` which you should be able to use it -with any LSP-compatible editor. We use custom extensions to LSP, -so special client-side support is required to take full advantage -of rust-analyzer. This repository contains support code for VS -Code and Emacs. +[LSP](https://microsoft.github.io/language-server-protocol/) implementation. To +install lsp server, clone the repository and then run `cargo xtask install +--server` (which is shorthand for `cargo install --path +./crates/ra_lsp_server`). This will produce a binary named `ra_lsp_server` which +you should be able to use it with any LSP-compatible editor. We use custom +extensions to LSP, so special client-side support is required to take full +advantage of rust-analyzer. This repository contains support code for VS Code +and Emacs. ``` $ git clone git@github.com:rust-analyzer/rust-analyzer && cd rust-analyzer From e6c0ad0d0a5ef904e431b03c0062b64f8172121d Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sun, 1 Dec 2019 15:00:34 -0500 Subject: [PATCH 027/312] Just update some things --- Cargo.lock | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83e41940bd..57cfde9781 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -23,7 +23,7 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -39,7 +39,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -49,7 +49,7 @@ version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -101,7 +101,7 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,7 +127,7 @@ source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487 dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -193,7 +193,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -213,7 +213,7 @@ dependencies = [ "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -328,7 +328,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -367,7 +367,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -403,7 +403,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -432,7 +432,7 @@ name = "hermit-abi" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -468,7 +468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -476,7 +476,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -498,7 +498,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -520,7 +520,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -531,7 +531,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -540,7 +540,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "jemalloc-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -579,7 +579,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.65" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -654,7 +654,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -690,7 +690,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -705,7 +705,7 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -726,7 +726,7 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -755,7 +755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -778,7 +778,7 @@ dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -812,7 +812,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1098,7 +1098,7 @@ dependencies = [ name = "ra_project_model" version = "0.1.0" dependencies = [ - "cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "ra_arena 0.1.0", "ra_cfg 0.1.0", @@ -1170,7 +1170,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1188,7 +1188,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1263,7 +1263,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1275,7 +1275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1448,7 +1448,7 @@ dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1493,7 +1493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1513,7 +1513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1552,7 +1552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "psm 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1564,7 +1564,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1578,7 +1578,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1590,7 +1590,7 @@ name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1752,7 +1752,7 @@ dependencies = [ name = "xtask" version = "0.1.0" dependencies = [ - "anyhow 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", "pico-args 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1771,7 +1771,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" -"checksum anyhow 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b412394828b7ca486b362f300b762d8e43dafd6f0d727b63f1cd2ade207c6cef" +"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" @@ -1784,7 +1784,7 @@ dependencies = [ "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum cargo_metadata 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8d2d1617e838936c0d2323a65cc151e03ae19a7678dd24f72bccf27119b90a5d" +"checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" "checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chalk-derive 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" @@ -1842,7 +1842,7 @@ dependencies = [ "checksum lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4fd87be4a815fd373e02773983940f0d75fb26fde8c098e9e45f7af03154c0" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" @@ -1921,7 +1921,7 @@ dependencies = [ "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" "checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" -"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e08bbcb7a3adbda0eb23431206b653bdad3d8dea311e72d36bf2215e27a42579" From 1836671d53213e5a1f3cab47fe95e8f6333f2e0f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 2 Dec 2019 15:17:55 +0100 Subject: [PATCH 028/312] Switch back to npm install Locks like it honors package.lock nowdays --- xtask/src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c97bfec977..c52902bb56 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -182,7 +182,8 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") } - Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm ci", work_dir: "./editors/code" }.run()?; + Cmd { unix: r"npm install", windows: r"cmd.exe /c npm install", work_dir: "./editors/code" } + .run()?; Cmd { unix: r"npm run package --scripts-prepend-node-path", windows: r"cmd.exe /c npm run package", From cbf262a1bc72f10dc93a4993da0012d3b0abb56f Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 2 Nov 2019 15:18:26 +0100 Subject: [PATCH 029/312] Change order of calls to get method candidate order correct --- crates/ra_hir_ty/src/method_resolution.rs | 154 ++++++++++++++++------ crates/ra_hir_ty/src/tests.rs | 2 - 2 files changed, 116 insertions(+), 40 deletions(-) diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 2bded3dbdc..fbb932a3e5 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -176,7 +176,6 @@ pub fn iterate_method_candidates( mode: LookupMode, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { - let krate = resolver.krate()?; match mode { LookupMode::MethodCall => { // For method calls, rust first does any number of autoderef, and then one @@ -189,57 +188,125 @@ pub fn iterate_method_candidates( // rustc does an autoderef and then autoref again). let environment = TraitEnvironment::lower(db, resolver); let ty = InEnvironment { value: ty.clone(), environment }; - for derefed_ty in autoderef::autoderef(db, resolver.krate(), ty) { - if let Some(result) = - iterate_inherent_methods(&derefed_ty, db, name, mode, krate, &mut callback) - { - return Some(result); - } - if let Some(result) = iterate_trait_method_candidates( - &derefed_ty, + let krate = resolver.krate()?; + + // We have to be careful about the order of operations here. + // Consider the case where we're resolving `x.clone()` where `x: + // &Vec<_>`. This resolves to the clone method with self type + // `Vec<_>`, *not* `&_`. I.e. we need to consider methods where the + // receiver type exactly matches before cases where we have to do + // autoref. But in the autoderef steps, the `&_` self type comes up + // *before* the `Vec<_>` self type. + // + // On the other hand, we don't want to just pick any by-value method + // before any by-autoref method; it's just that we need to consider + // the methods by autoderef order of *receiver types*, not *self + // types*. + + let deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty.clone()).collect(); + for i in 0..deref_chain.len() { + if let Some(result) = iterate_method_candidates_autoref( + &deref_chain[i..], db, resolver, name, - mode, &mut callback, ) { return Some(result); } } + None } LookupMode::Path => { // No autoderef for path lookups - if let Some(result) = - iterate_inherent_methods(&ty, db, name, mode, krate.into(), &mut callback) - { - return Some(result); - } - if let Some(result) = - iterate_trait_method_candidates(&ty, db, resolver, name, mode, &mut callback) - { - return Some(result); - } + iterate_method_candidates_inner(&ty, db, resolver, name, None, &mut callback) + } + } +} + +fn iterate_method_candidates_autoref( + deref_chain: &[Canonical], + db: &impl HirDatabase, + resolver: &Resolver, + name: Option<&Name>, + mut callback: impl FnMut(&Ty, AssocItemId) -> Option, +) -> Option { + if let Some(result) = iterate_method_candidates_by_receiver(&deref_chain[0], &deref_chain[1..], db, resolver, name, &mut callback) { + return Some(result); + } + let refed = Canonical { + num_vars: deref_chain[0].num_vars, + value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), + }; + if let Some(result) = iterate_method_candidates_by_receiver(&refed, deref_chain, db, resolver, name, &mut callback) { + return Some(result); + } + let ref_muted = Canonical { + num_vars: deref_chain[0].num_vars, + value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), + }; + if let Some(result) = iterate_method_candidates_by_receiver(&ref_muted, deref_chain, db, resolver, name, &mut callback) { + return Some(result); + } + None +} + +fn iterate_method_candidates_by_receiver( + receiver_ty: &Canonical, + deref_chain: &[Canonical], + db: &impl HirDatabase, + resolver: &Resolver, + name: Option<&Name>, + mut callback: impl FnMut(&Ty, AssocItemId) -> Option, +) -> Option { + // TODO: do we need to do the whole loop for inherents before traits? + // We're looking for methods with *receiver* type receiver_ty. These could + // be found in any of the derefs of receiver_ty, so we have to go through + // that. + for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { + if let Some(result) = iterate_method_candidates_inner(self_ty, db, resolver, name, Some(receiver_ty), &mut callback) { + return Some(result); } } None } -fn iterate_trait_method_candidates( - ty: &Canonical, +fn iterate_method_candidates_inner( + self_ty: &Canonical, db: &impl HirDatabase, resolver: &Resolver, name: Option<&Name>, - mode: LookupMode, + receiver_ty: Option<&Canonical>, + mut callback: impl FnMut(&Ty, AssocItemId) -> Option, +) -> Option { + let krate = resolver.krate()?; + if let Some(result) = iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) { + return Some(result); + } + if let Some(result) = + iterate_trait_method_candidates(self_ty, db, resolver, name, receiver_ty, &mut callback) + { + return Some(result); + } + None +} + +fn iterate_trait_method_candidates( + self_ty: &Canonical, + db: &impl HirDatabase, + resolver: &Resolver, + name: Option<&Name>, + receiver_ty: Option<&Canonical>, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { let krate = resolver.krate()?; // FIXME: maybe put the trait_env behind a query (need to figure out good input parameters for that) let env = TraitEnvironment::lower(db, resolver); // if ty is `impl Trait` or `dyn Trait`, the trait doesn't need to be in scope - let inherent_trait = ty.value.inherent_trait().into_iter(); + let inherent_trait = self_ty.value.inherent_trait().into_iter(); // if we have `T: Trait` in the param env, the trait doesn't need to be in scope let traits_from_env = env - .trait_predicates_for_self_ty(&ty.value) + .trait_predicates_for_self_ty(&self_ty.value) .map(|tr| tr.trait_) .flat_map(|t| all_super_traits(db, t)); let traits = @@ -252,17 +319,17 @@ fn iterate_trait_method_candidates( // iteration let mut known_implemented = false; for (_name, item) in data.items.iter() { - if !is_valid_candidate(db, name, mode, (*item).into()) { + if !is_valid_candidate(db, name, receiver_ty, (*item).into(), self_ty) { continue; } if !known_implemented { - let goal = generic_implements_goal(db, env.clone(), t, ty.clone()); + let goal = generic_implements_goal(db, env.clone(), t, self_ty.clone()); if db.trait_solve(krate.into(), goal).is_none() { continue 'traits; } } known_implemented = true; - if let Some(result) = callback(&ty.value, (*item).into()) { + if let Some(result) = callback(&self_ty.value, (*item).into()) { return Some(result); } } @@ -271,22 +338,22 @@ fn iterate_trait_method_candidates( } fn iterate_inherent_methods( - ty: &Canonical, + self_ty: &Canonical, db: &impl HirDatabase, name: Option<&Name>, - mode: LookupMode, + receiver_ty: Option<&Canonical>, krate: CrateId, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { - for krate in ty.value.def_crates(db, krate)? { + for krate in self_ty.value.def_crates(db, krate)? { let impls = db.impls_in_crate(krate); - for impl_block in impls.lookup_impl_blocks(&ty.value) { + for impl_block in impls.lookup_impl_blocks(&self_ty.value) { for &item in db.impl_data(impl_block).items.iter() { - if !is_valid_candidate(db, name, mode, item) { + if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { continue; } - if let Some(result) = callback(&ty.value, item.into()) { + if let Some(result) = callback(&self_ty.value, item) { return Some(result); } } @@ -298,18 +365,29 @@ fn iterate_inherent_methods( fn is_valid_candidate( db: &impl HirDatabase, name: Option<&Name>, - mode: LookupMode, + receiver_ty: Option<&Canonical>, item: AssocItemId, + self_ty: &Canonical, ) -> bool { match item { AssocItemId::FunctionId(m) => { let data = db.function_data(m); - name.map_or(true, |name| &data.name == name) - && (data.has_self_param || mode == LookupMode::Path) + if let Some(name) = name { + if &data.name != name { + return false; + } + } + if let Some(receiver_ty) = receiver_ty { + if !data.has_self_param { + return false; + } + // TODO compare receiver ty + } + true } AssocItemId::ConstId(c) => { let data = db.const_data(c); - name.map_or(true, |name| data.name.as_ref() == Some(name)) && (mode == LookupMode::Path) + name.map_or(true, |name| data.name.as_ref() == Some(name)) && receiver_ty.is_none() } _ => false, } diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index a3cc5cf957..be8768c622 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -3433,7 +3433,6 @@ pub fn baz() -> usize { 31usize } assert_eq!("(i32, usize)", type_at_pos(&db, pos)); } -#[ignore] #[test] fn method_resolution_trait_before_autoref() { let t = type_at( @@ -3449,7 +3448,6 @@ fn test() { S.foo()<|>; } assert_eq!(t, "u128"); } -#[ignore] #[test] fn method_resolution_by_value_before_autoref() { let t = type_at( From 599dab59824b164b1c24e2e51adeae1ac1307964 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 1 Dec 2019 20:30:28 +0100 Subject: [PATCH 030/312] Extract unification code to unify module --- crates/ra_hir_ty/src/infer.rs | 255 +++---------------------- crates/ra_hir_ty/src/infer/coerce.rs | 10 +- crates/ra_hir_ty/src/infer/expr.rs | 30 +-- crates/ra_hir_ty/src/infer/pat.rs | 4 +- crates/ra_hir_ty/src/infer/path.rs | 4 +- crates/ra_hir_ty/src/infer/unify.rs | 272 ++++++++++++++++++++++++++- 6 files changed, 312 insertions(+), 263 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index fe259371f5..81afbd2b47 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -18,7 +18,6 @@ use std::mem; use std::ops::Index; use std::sync::Arc; -use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; use rustc_hash::FxHashMap; use hir_def::{ @@ -33,12 +32,11 @@ use hir_def::{ use hir_expand::{diagnostics::DiagnosticSink, name}; use ra_arena::map::ArenaMap; use ra_prof::profile; -use test_utils::tested_by; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, + ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, }; use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; @@ -191,7 +189,7 @@ struct InferenceContext<'a, D: HirDatabase> { owner: DefWithBodyId, body: Arc, resolver: Resolver, - var_unification_table: InPlaceUnificationTable, + table: unify::InferenceTable, trait_env: Arc, obligations: Vec, result: InferenceResult, @@ -209,7 +207,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn new(db: &'a D, owner: DefWithBodyId, resolver: Resolver) -> Self { InferenceContext { result: InferenceResult::default(), - var_unification_table: InPlaceUnificationTable::new(), + table: unify::InferenceTable::new(), obligations: Vec::default(), return_ty: Ty::Unknown, // set in collect_fn_signature trait_env: TraitEnvironment::lower(db, &resolver), @@ -224,13 +222,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn resolve_all(mut self) -> InferenceResult { // FIXME resolve obligations as well (use Guidance if necessary) let mut result = mem::replace(&mut self.result, InferenceResult::default()); - let mut tv_stack = Vec::new(); for ty in result.type_of_expr.values_mut() { - let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); + let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); *ty = resolved; } for ty in result.type_of_pat.values_mut() { - let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown)); + let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown)); *ty = resolved; } result @@ -275,96 +272,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.normalize_associated_types_in(ty) } - fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { - substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) - } - - fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { - self.unify_inner(ty1, ty2, 0) - } - - fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { - if depth > 1000 { - // prevent stackoverflows - panic!("infinite recursion in unification"); - } - if ty1 == ty2 { - return true; - } - // try to resolve type vars first - let ty1 = self.resolve_ty_shallow(ty1); - let ty2 = self.resolve_ty_shallow(ty2); - match (&*ty1, &*ty2) { - (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { - self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) - } - _ => self.unify_inner_trivial(&ty1, &ty2), - } - } - - fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { - match (ty1, ty2) { - (Ty::Unknown, _) | (_, Ty::Unknown) => true, - - (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) - | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) - | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) - | ( - Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), - Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), - ) => { - // both type vars are unknown since we tried to resolve them - self.var_unification_table.union(*tv1, *tv2); - true - } - - // The order of MaybeNeverTypeVar matters here. - // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. - // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. - (Ty::Infer(InferTy::TypeVar(tv)), other) - | (other, Ty::Infer(InferTy::TypeVar(tv))) - | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) - | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) - | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) - | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) - | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) - | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { - // the type var is unknown since we tried to resolve it - self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); - true - } - - _ => false, - } - } - - fn new_type_var(&mut self) -> Ty { - Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) - } - - fn new_integer_var(&mut self) -> Ty { - Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) - } - - fn new_float_var(&mut self) -> Ty { - Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) - } - - fn new_maybe_never_type_var(&mut self) -> Ty { - Ty::Infer(InferTy::MaybeNeverTypeVar( - self.var_unification_table.new_key(TypeVarValue::Unknown), - )) - } - /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty { - Ty::Unknown => self.new_type_var(), + Ty::Unknown => self.table.new_type_var(), Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => { - self.new_integer_var() + self.table.new_integer_var() } Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => { - self.new_float_var() + self.table.new_float_var() } _ => ty, } @@ -402,64 +318,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } + fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { + self.table.unify(ty1, ty2) + } + /// Resolves the type as far as currently possible, replacing type variables /// by their known types. All types returned by the infer_* functions should /// be resolved as far as possible, i.e. contain no type variables with /// known type. - fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { + fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { self.resolve_obligations_as_possible(); - ty.fold(&mut |ty| match ty { - Ty::Infer(tv) => { - let inner = tv.to_inner(); - if tv_stack.contains(&inner) { - tested_by!(type_var_cycles_resolve_as_possible); - // recursive type - return tv.fallback_value(); - } - if let Some(known_ty) = - self.var_unification_table.inlined_probe_value(inner).known() - { - // known_ty may contain other variables that are known by now - tv_stack.push(inner); - let result = self.resolve_ty_as_possible(tv_stack, known_ty.clone()); - tv_stack.pop(); - result - } else { - ty - } - } - _ => ty, - }) + self.table.resolve_ty_as_possible(ty) } - /// If `ty` is a type variable with known type, returns that type; - /// otherwise, return ty. fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { - let mut ty = Cow::Borrowed(ty); - // The type variable could resolve to a int/float variable. Hence try - // resolving up to three times; each type of variable shouldn't occur - // more than once - for i in 0..3 { - if i > 0 { - tested_by!(type_var_resolves_to_int_var); - } - match &*ty { - Ty::Infer(tv) => { - let inner = tv.to_inner(); - match self.var_unification_table.inlined_probe_value(inner).known() { - Some(known_ty) => { - // The known_ty can't be a type var itself - ty = Cow::Owned(known_ty.clone()); - } - _ => return ty, - } - } - _ => return ty, - } - } - log::error!("Inference variable still not resolved: {:?}", ty); - ty + self.table.resolve_ty_shallow(ty) } /// Recurses through the given type, normalizing associated types mentioned @@ -469,7 +343,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// call). `make_ty` handles this already, but e.g. for field types we need /// to do it as well. fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); ty.fold(&mut |ty| match ty { Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty), _ => ty, @@ -477,40 +351,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { - let var = self.new_type_var(); + let var = self.table.new_type_var(); let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() }; let obligation = Obligation::Projection(predicate); self.obligations.push(obligation); var } - /// Resolves the type completely; type variables without known type are - /// replaced by Ty::Unknown. - fn resolve_ty_completely(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { - ty.fold(&mut |ty| match ty { - Ty::Infer(tv) => { - let inner = tv.to_inner(); - if tv_stack.contains(&inner) { - tested_by!(type_var_cycles_resolve_completely); - // recursive type - return tv.fallback_value(); - } - if let Some(known_ty) = - self.var_unification_table.inlined_probe_value(inner).known() - { - // known_ty may contain other variables that are known by now - tv_stack.push(inner); - let result = self.resolve_ty_completely(tv_stack, known_ty.clone()); - tv_stack.pop(); - result - } else { - tv.fallback_value() - } - } - _ => ty, - }) - } - fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option) { let path = match path { Some(path) => path, @@ -615,78 +462,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } -/// The ID of a type variable. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -pub struct TypeVarId(pub(super) u32); - -impl UnifyKey for TypeVarId { - type Value = TypeVarValue; - - fn index(&self) -> u32 { - self.0 - } - - fn from_index(i: u32) -> Self { - TypeVarId(i) - } - - fn tag() -> &'static str { - "TypeVarId" - } -} - -/// The value of a type variable: either we already know the type, or we don't -/// know it yet. -#[derive(Clone, PartialEq, Eq, Debug)] -pub enum TypeVarValue { - Known(Ty), - Unknown, -} - -impl TypeVarValue { - fn known(&self) -> Option<&Ty> { - match self { - TypeVarValue::Known(ty) => Some(ty), - TypeVarValue::Unknown => None, - } - } -} - -impl UnifyValue for TypeVarValue { - type Error = NoError; - - fn unify_values(value1: &Self, value2: &Self) -> Result { - match (value1, value2) { - // We should never equate two type variables, both of which have - // known types. Instead, we recursively equate those types. - (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!( - "equating two type variables, both of which have known types: {:?} and {:?}", - t1, t2 - ), - - // If one side is known, prefer that one. - (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), - (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()), - - (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown), - } - } -} - /// The kinds of placeholders we need during type inference. There's separate /// values for general types, and for integer and float variables. The latter /// two are used for inference of literal values (e.g. `100` could be one of /// several integer types). #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] pub enum InferTy { - TypeVar(TypeVarId), - IntVar(TypeVarId), - FloatVar(TypeVarId), - MaybeNeverTypeVar(TypeVarId), + TypeVar(unify::TypeVarId), + IntVar(unify::TypeVarId), + FloatVar(unify::TypeVarId), + MaybeNeverTypeVar(unify::TypeVarId), } impl InferTy { - fn to_inner(self) -> TypeVarId { + fn to_inner(self) -> unify::TypeVarId { match self { InferTy::TypeVar(ty) | InferTy::IntVar(ty) diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 064993d34f..9bfc701cd5 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -10,7 +10,7 @@ use test_utils::tested_by; use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; -use super::{InEnvironment, InferTy, InferenceContext, TypeVarValue}; +use super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue}; impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// Unify two types, but may coerce the first one to the second one @@ -85,8 +85,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match (&from_ty, to_ty) { // Never type will make type variable to fallback to Never Type instead of Unknown. (ty_app!(TypeCtor::Never), Ty::Infer(InferTy::TypeVar(tv))) => { - let var = self.new_maybe_never_type_var(); - self.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); + let var = self.table.new_maybe_never_type_var(); + self.table.var_unification_table.union_value(*tv, TypeVarValue::Known(var)); return true; } (ty_app!(TypeCtor::Never), _) => return true, @@ -94,7 +94,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Trivial cases, this should go after `never` check to // avoid infer result type to be never _ => { - if self.unify_inner_trivial(&from_ty, &to_ty) { + if self.table.unify_inner_trivial(&from_ty, &to_ty) { return true; } } @@ -330,7 +330,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Stop when constructor matches. (ty_app!(from_ctor, st1), ty_app!(to_ctor, st2)) if from_ctor == to_ctor => { // It will not recurse to `coerce`. - return self.unify_substs(st1, st2, 0); + return self.table.unify_substs(st1, st2, 0); } _ => {} } diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 4014f4732d..1e78f6efd4 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -32,7 +32,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { TypeMismatch { expected: expected.ty.clone(), actual: ty.clone() }, ); } - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); ty } @@ -53,7 +53,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { expected.ty.clone() }; - self.resolve_ty_as_possible(&mut vec![], ty) + self.resolve_ty_as_possible(ty) } fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { @@ -94,7 +94,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let pat_ty = match self.resolve_into_iter_item() { Some(into_iter_item_alias) => { - let pat_ty = self.new_type_var(); + let pat_ty = self.table.new_type_var(); let projection = ProjectionPredicate { ty: pat_ty.clone(), projection_ty: ProjectionTy { @@ -103,7 +103,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }, }; self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(&mut vec![], pat_ty) + self.resolve_ty_as_possible(pat_ty) } None => Ty::Unknown, }; @@ -128,7 +128,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } // add return type - let ret_ty = self.new_type_var(); + let ret_ty = self.table.new_type_var(); sig_tys.push(ret_ty.clone()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, @@ -167,7 +167,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Match { expr, arms } => { let input_ty = self.infer_expr(*expr, &Expectation::none()); - let mut result_ty = self.new_maybe_never_type_var(); + let mut result_ty = self.table.new_maybe_never_type_var(); for arm in arms { for &pat in &arm.pats { @@ -283,7 +283,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let inner_ty = self.infer_expr(*expr, &Expectation::none()); let ty = match self.resolve_future_future_output() { Some(future_future_output_alias) => { - let ty = self.new_type_var(); + let ty = self.table.new_type_var(); let projection = ProjectionPredicate { ty: ty.clone(), projection_ty: ProjectionTy { @@ -292,7 +292,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }, }; self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(&mut vec![], ty) + self.resolve_ty_as_possible(ty) } None => Ty::Unknown, }; @@ -302,7 +302,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let inner_ty = self.infer_expr(*expr, &Expectation::none()); let ty = match self.resolve_ops_try_ok() { Some(ops_try_ok_alias) => { - let ty = self.new_type_var(); + let ty = self.table.new_type_var(); let projection = ProjectionPredicate { ty: ty.clone(), projection_ty: ProjectionTy { @@ -311,7 +311,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }, }; self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(&mut vec![], ty) + self.resolve_ty_as_possible(ty) } None => Ty::Unknown, }; @@ -465,10 +465,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_app!(TypeCtor::Tuple { .. }, st) => st .iter() .cloned() - .chain(repeat_with(|| self.new_type_var())) + .chain(repeat_with(|| self.table.new_type_var())) .take(exprs.len()) .collect::>(), - _ => (0..exprs.len()).map(|_| self.new_type_var()).collect(), + _ => (0..exprs.len()).map(|_| self.table.new_type_var()).collect(), }; for (expr, ty) in exprs.iter().zip(tys.iter_mut()) { @@ -482,7 +482,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty_app!(TypeCtor::Array, st) | ty_app!(TypeCtor::Slice, st) => { st.as_single().clone() } - _ => self.new_type_var(), + _ => self.table.new_type_var(), }; match array { @@ -524,7 +524,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; // use a new type variable if we got Ty::Unknown here let ty = self.insert_type_vars_shallow(ty); - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); self.write_expr_ty(tgt_expr, ty.clone()); ty } @@ -553,7 +553,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); self.infer_pat(*pat, &ty, BindingMode::default()); } Statement::Expr(expr) => { diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 1ebb362399..a146628844 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs @@ -170,7 +170,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } BindingMode::Move => inner_ty.clone(), }; - let bound_ty = self.resolve_ty_as_possible(&mut vec![], bound_ty); + let bound_ty = self.resolve_ty_as_possible(bound_ty); self.write_pat_ty(pat, bound_ty); return inner_ty; } @@ -179,7 +179,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // use a new type variable if we got Ty::Unknown here let ty = self.insert_type_vars_shallow(ty); self.unify(&ty, expected); - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); self.write_pat_ty(pat, ty.clone()); ty } diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index bbf146418e..d0d7646a49 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -57,7 +57,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let typable: ValueTyDefId = match value { ValueNs::LocalBinding(pat) => { let ty = self.result.type_of_pat.get(pat)?.clone(); - let ty = self.resolve_ty_as_possible(&mut vec![], ty); + let ty = self.resolve_ty_as_possible(ty); return Some(ty); } ValueNs::FunctionId(it) => it.into(), @@ -211,7 +211,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // we're picking this method let trait_substs = Substs::build_for_def(self.db, trait_) .push(ty.clone()) - .fill(std::iter::repeat_with(|| self.new_type_var())) + .fill(std::iter::repeat_with(|| self.table.new_type_var())) .build(); let substs = Substs::build_for_def(self.db, item) .use_parent_substs(&trait_substs) diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index f3a8756785..ff50138f5d 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs @@ -1,9 +1,15 @@ //! Unification and canonicalization logic. +use std::borrow::Cow; + +use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; + +use test_utils::tested_by; + use super::{InferenceContext, Obligation}; use crate::{ db::HirDatabase, utils::make_mut_slice, Canonical, InEnvironment, InferTy, ProjectionPredicate, - ProjectionTy, Substs, TraitRef, Ty, TypeWalk, + ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; impl<'a, D: HirDatabase> InferenceContext<'a, D> { @@ -24,7 +30,7 @@ where /// A stack of type variables that is used to detect recursive types (which /// are an error, but we need to protect against them to avoid stack /// overflows). - var_stack: Vec, + var_stack: Vec, } pub(super) struct Canonicalized { @@ -53,14 +59,14 @@ where return tv.fallback_value(); } if let Some(known_ty) = - self.ctx.var_unification_table.inlined_probe_value(inner).known() + self.ctx.table.var_unification_table.inlined_probe_value(inner).known() { self.var_stack.push(inner); let result = self.do_canonicalize_ty(known_ty.clone()); self.var_stack.pop(); result } else { - let root = self.ctx.var_unification_table.find(inner); + let root = self.ctx.table.var_unification_table.find(inner); let free_var = match tv { InferTy::TypeVar(_) => InferTy::TypeVar(root), InferTy::IntVar(_) => InferTy::IntVar(root), @@ -153,10 +159,264 @@ impl Canonicalized { solution: Canonical>, ) { // the solution may contain new variables, which we need to convert to new inference vars - let new_vars = Substs((0..solution.num_vars).map(|_| ctx.new_type_var()).collect()); + let new_vars = Substs((0..solution.num_vars).map(|_| ctx.table.new_type_var()).collect()); for (i, ty) in solution.value.into_iter().enumerate() { let var = self.free_vars[i]; - ctx.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); + ctx.table.unify(&Ty::Infer(var), &ty.subst_bound_vars(&new_vars)); + } + } +} + +pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Substs { + let mut table = InferenceTable::new(); + let vars = Substs::builder(ty1.num_vars) + .fill(std::iter::repeat_with(|| table.new_type_var())).build(); + let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); + table.unify(&ty_with_vars, ty2); + Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build() +} + +#[derive(Clone, Debug)] +pub(crate) struct InferenceTable { + pub(super) var_unification_table: InPlaceUnificationTable, +} + +impl InferenceTable { + pub fn new() -> Self { + InferenceTable { + var_unification_table: InPlaceUnificationTable::new(), + } + } + + pub fn new_type_var(&mut self) -> Ty { + Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) + } + + pub fn new_integer_var(&mut self) -> Ty { + Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) + } + + pub fn new_float_var(&mut self) -> Ty { + Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown))) + } + + pub fn new_maybe_never_type_var(&mut self) -> Ty { + Ty::Infer(InferTy::MaybeNeverTypeVar( + self.var_unification_table.new_key(TypeVarValue::Unknown), + )) + } + + pub fn resolve_ty_completely(&mut self, ty: Ty) -> Ty { + self.resolve_ty_completely_inner(&mut Vec::new(), ty) + } + + pub fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty { + self.resolve_ty_as_possible_inner(&mut Vec::new(), ty) + } + + pub fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { + self.unify_inner(ty1, ty2, 0) + } + + pub fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool { + substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth)) + } + + fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { + if depth > 1000 { + // prevent stackoverflows + panic!("infinite recursion in unification"); + } + if ty1 == ty2 { + return true; + } + // try to resolve type vars first + let ty1 = self.resolve_ty_shallow(ty1); + let ty2 = self.resolve_ty_shallow(ty2); + match (&*ty1, &*ty2) { + (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { + self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) + } + _ => self.unify_inner_trivial(&ty1, &ty2), + } + } + + pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool { + match (ty1, ty2) { + (Ty::Unknown, _) | (_, Ty::Unknown) => true, + + (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) + | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) + | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) + | ( + Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)), + Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)), + ) => { + // both type vars are unknown since we tried to resolve them + self.var_unification_table.union(*tv1, *tv2); + true + } + + // The order of MaybeNeverTypeVar matters here. + // Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar. + // Unifying MaybeNeverTypeVar and other concrete type will let the former become it. + (Ty::Infer(InferTy::TypeVar(tv)), other) + | (other, Ty::Infer(InferTy::TypeVar(tv))) + | (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other) + | (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv))) + | (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_))) + | (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv))) + | (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_))) + | (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => { + // the type var is unknown since we tried to resolve it + self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone())); + true + } + + _ => false, + } + } + + /// If `ty` is a type variable with known type, returns that type; + /// otherwise, return ty. + pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { + let mut ty = Cow::Borrowed(ty); + // The type variable could resolve to a int/float variable. Hence try + // resolving up to three times; each type of variable shouldn't occur + // more than once + for i in 0..3 { + if i > 0 { + tested_by!(type_var_resolves_to_int_var); + } + match &*ty { + Ty::Infer(tv) => { + let inner = tv.to_inner(); + match self.var_unification_table.inlined_probe_value(inner).known() { + Some(known_ty) => { + // The known_ty can't be a type var itself + ty = Cow::Owned(known_ty.clone()); + } + _ => return ty, + } + } + _ => return ty, + } + } + log::error!("Inference variable still not resolved: {:?}", ty); + ty + } + + /// Resolves the type as far as currently possible, replacing type variables + /// by their known types. All types returned by the infer_* functions should + /// be resolved as far as possible, i.e. contain no type variables with + /// known type. + fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { + ty.fold(&mut |ty| match ty { + Ty::Infer(tv) => { + let inner = tv.to_inner(); + if tv_stack.contains(&inner) { + tested_by!(type_var_cycles_resolve_as_possible); + // recursive type + return tv.fallback_value(); + } + if let Some(known_ty) = + self.var_unification_table.inlined_probe_value(inner).known() + { + // known_ty may contain other variables that are known by now + tv_stack.push(inner); + let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); + tv_stack.pop(); + result + } else { + ty + } + } + _ => ty, + }) + } + + /// Resolves the type completely; type variables without known type are + /// replaced by Ty::Unknown. + fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec, ty: Ty) -> Ty { + ty.fold(&mut |ty| match ty { + Ty::Infer(tv) => { + let inner = tv.to_inner(); + if tv_stack.contains(&inner) { + tested_by!(type_var_cycles_resolve_completely); + // recursive type + return tv.fallback_value(); + } + if let Some(known_ty) = + self.var_unification_table.inlined_probe_value(inner).known() + { + // known_ty may contain other variables that are known by now + tv_stack.push(inner); + let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); + tv_stack.pop(); + result + } else { + tv.fallback_value() + } + } + _ => ty, + }) + } +} + +/// The ID of a type variable. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +pub struct TypeVarId(pub(super) u32); + +impl UnifyKey for TypeVarId { + type Value = TypeVarValue; + + fn index(&self) -> u32 { + self.0 + } + + fn from_index(i: u32) -> Self { + TypeVarId(i) + } + + fn tag() -> &'static str { + "TypeVarId" + } +} + +/// The value of a type variable: either we already know the type, or we don't +/// know it yet. +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum TypeVarValue { + Known(Ty), + Unknown, +} + +impl TypeVarValue { + fn known(&self) -> Option<&Ty> { + match self { + TypeVarValue::Known(ty) => Some(ty), + TypeVarValue::Unknown => None, + } + } +} + +impl UnifyValue for TypeVarValue { + type Error = NoError; + + fn unify_values(value1: &Self, value2: &Self) -> Result { + match (value1, value2) { + // We should never equate two type variables, both of which have + // known types. Instead, we recursively equate those types. + (TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!( + "equating two type variables, both of which have known types: {:?} and {:?}", + t1, t2 + ), + + // If one side is known, prefer that one. + (TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()), + (TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()), + + (TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown), } } } From 456d52fdfa8525af2a54e76ee5300f0a40ef582a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 1 Dec 2019 22:14:28 +0100 Subject: [PATCH 031/312] Check receiver type properly --- crates/ra_hir_ty/src/infer.rs | 6 +- crates/ra_hir_ty/src/infer/coerce.rs | 2 +- crates/ra_hir_ty/src/infer/unify.rs | 20 ++++--- crates/ra_hir_ty/src/method_resolution.rs | 71 ++++++++++++++++++++--- 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 81afbd2b47..0889a6bf9e 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -36,11 +36,13 @@ use ra_prof::profile; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, - TypeWalk, Uncertain, + ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, + Uncertain, }; use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; +pub use unify::unify; + macro_rules! ty_app { ($ctor:pat, $param:pat) => { crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 9bfc701cd5..9daa77cfa9 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -10,7 +10,7 @@ use test_utils::tested_by; use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; -use super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue}; +use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext}; impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// Unify two types, but may coerce the first one to the second one diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index ff50138f5d..8ed2a6090a 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs @@ -167,13 +167,19 @@ impl Canonicalized { } } -pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Substs { +pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option { let mut table = InferenceTable::new(); - let vars = Substs::builder(ty1.num_vars) - .fill(std::iter::repeat_with(|| table.new_type_var())).build(); + let vars = + Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); - table.unify(&ty_with_vars, ty2); - Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build() + if !table.unify(&ty_with_vars, ty2) { + return None; + } + Some( + Substs::builder(ty1.num_vars) + .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) + .build(), + ) } #[derive(Clone, Debug)] @@ -183,9 +189,7 @@ pub(crate) struct InferenceTable { impl InferenceTable { pub fn new() -> Self { - InferenceTable { - var_unification_table: InPlaceUnificationTable::new(), - } + InferenceTable { var_unification_table: InPlaceUnificationTable::new() } } pub fn new_type_var(&mut self) -> Ty { diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index fbb932a3e5..97281cf15c 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -7,19 +7,20 @@ use std::sync::Arc; use arrayvec::ArrayVec; use hir_def::{ lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, - FunctionId, HasModule, ImplId, TraitId, + FunctionId, HasModule, ImplId, Lookup, TraitId, }; use hir_expand::name::Name; use ra_db::CrateId; use ra_prof::profile; use rustc_hash::FxHashMap; +use super::Substs; use crate::{ autoderef, db::HirDatabase, primitive::{FloatBitness, Uncertain}, utils::all_super_traits, - Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, + Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, }; /// This is used as a key for indexing impls. @@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref( name: Option<&Name>, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { - if let Some(result) = iterate_method_candidates_by_receiver(&deref_chain[0], &deref_chain[1..], db, resolver, name, &mut callback) { + if let Some(result) = iterate_method_candidates_by_receiver( + &deref_chain[0], + &deref_chain[1..], + db, + resolver, + name, + &mut callback, + ) { return Some(result); } let refed = Canonical { num_vars: deref_chain[0].num_vars, value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), }; - if let Some(result) = iterate_method_candidates_by_receiver(&refed, deref_chain, db, resolver, name, &mut callback) { + if let Some(result) = iterate_method_candidates_by_receiver( + &refed, + deref_chain, + db, + resolver, + name, + &mut callback, + ) { return Some(result); } let ref_muted = Canonical { num_vars: deref_chain[0].num_vars, value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), }; - if let Some(result) = iterate_method_candidates_by_receiver(&ref_muted, deref_chain, db, resolver, name, &mut callback) { + if let Some(result) = iterate_method_candidates_by_receiver( + &ref_muted, + deref_chain, + db, + resolver, + name, + &mut callback, + ) { return Some(result); } None @@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver( // be found in any of the derefs of receiver_ty, so we have to go through // that. for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { - if let Some(result) = iterate_method_candidates_inner(self_ty, db, resolver, name, Some(receiver_ty), &mut callback) { + if let Some(result) = iterate_method_candidates_inner( + self_ty, + db, + resolver, + name, + Some(receiver_ty), + &mut callback, + ) { return Some(result); } } @@ -280,7 +309,9 @@ fn iterate_method_candidates_inner( mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { let krate = resolver.krate()?; - if let Some(result) = iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) { + if let Some(result) = + iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) + { return Some(result); } if let Some(result) = @@ -381,7 +412,31 @@ fn is_valid_candidate( if !data.has_self_param { return false; } - // TODO compare receiver ty + let substs = match m.lookup(db).container { + hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, item) + .push(self_ty.value.clone()) + .fill_with_unknown() + .build(), + hir_def::ContainerId::ImplId(impl_id) => { + let vars = + Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); + let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); + let self_ty_with_vars = + Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; + if let Some(substs) = super::infer::unify(self_ty_with_vars, &self_ty.value) + { + substs + } else { + return false; + } + } + hir_def::ContainerId::ModuleId(_) => unreachable!(), + }; + let sig = db.callable_item_signature(m.into()); + let receiver = sig.params()[0].clone().subst(&substs); + if receiver != receiver_ty.value { + return false; + } } true } From cfa50df33e1ebfa89f7fbdece7454699f858de92 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Mon, 2 Dec 2019 18:12:49 +0100 Subject: [PATCH 032/312] Refactor a bit --- crates/ra_hir_ty/src/infer/path.rs | 38 +-------- crates/ra_hir_ty/src/method_resolution.rs | 98 +++++++++++++---------- crates/ra_hir_ty/src/tests.rs | 15 ++++ 3 files changed, 74 insertions(+), 77 deletions(-) diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index d0d7646a49..b0024c6e1c 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -206,7 +206,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { AssocItemId::TypeAliasId(_) => unreachable!(), }; let substs = match container { - ContainerId::ImplId(_) => self.find_self_types(&def, ty.clone()), + ContainerId::ImplId(impl_id) => { + method_resolution::inherent_impl_substs(self.db, impl_id, &ty) + } ContainerId::TraitId(trait_) => { // we're picking this method let trait_substs = Substs::build_for_def(self.db, trait_) @@ -231,38 +233,4 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }, ) } - - fn find_self_types(&self, def: &ValueNs, actual_def_ty: Ty) -> Option { - if let ValueNs::FunctionId(func) = *def { - // We only do the infer if parent has generic params - let gen = self.db.generic_params(func.into()); - if gen.count_parent_params() == 0 { - return None; - } - - let impl_id = match func.lookup(self.db).container { - ContainerId::ImplId(it) => it, - _ => return None, - }; - let self_ty = self.db.impl_self_ty(impl_id).clone(); - let self_ty_substs = self_ty.substs()?; - let actual_substs = actual_def_ty.substs()?; - - let mut new_substs = vec![Ty::Unknown; gen.count_parent_params()]; - - // The following code *link up* the function actual parma type - // and impl_block type param index - self_ty_substs.iter().zip(actual_substs.iter()).for_each(|(param, pty)| { - if let Ty::Param { idx, .. } = param { - if let Some(s) = new_substs.get_mut(*idx as usize) { - *s = pty.clone(); - } - } - }); - - Some(Substs(new_substs.into())) - } else { - None - } - } } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 97281cf15c..21efb196af 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -191,13 +191,13 @@ pub fn iterate_method_candidates( let ty = InEnvironment { value: ty.clone(), environment }; let krate = resolver.krate()?; - // We have to be careful about the order of operations here. - // Consider the case where we're resolving `x.clone()` where `x: - // &Vec<_>`. This resolves to the clone method with self type - // `Vec<_>`, *not* `&_`. I.e. we need to consider methods where the - // receiver type exactly matches before cases where we have to do - // autoref. But in the autoderef steps, the `&_` self type comes up - // *before* the `Vec<_>` self type. + // We have to be careful about the order we're looking at candidates + // in here. Consider the case where we're resolving `x.clone()` + // where `x: &Vec<_>`. This resolves to the clone method with self + // type `Vec<_>`, *not* `&_`. I.e. we need to consider methods where + // the receiver type exactly matches before cases where we have to + // do autoref. But in the autoderef steps, the `&_` self type comes + // up *before* the `Vec<_>` self type. // // On the other hand, we don't want to just pick any by-value method // before any by-autoref method; it's just that we need to consider @@ -206,7 +206,7 @@ pub fn iterate_method_candidates( let deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty.clone()).collect(); for i in 0..deref_chain.len() { - if let Some(result) = iterate_method_candidates_autoref( + if let Some(result) = iterate_method_candidates_with_autoref( &deref_chain[i..], db, resolver, @@ -220,12 +220,12 @@ pub fn iterate_method_candidates( } LookupMode::Path => { // No autoderef for path lookups - iterate_method_candidates_inner(&ty, db, resolver, name, None, &mut callback) + iterate_method_candidates_for_self_ty(&ty, db, resolver, name, &mut callback) } } } -fn iterate_method_candidates_autoref( +fn iterate_method_candidates_with_autoref( deref_chain: &[Canonical], db: &impl HirDatabase, resolver: &Resolver, @@ -275,18 +275,25 @@ fn iterate_method_candidates_autoref( fn iterate_method_candidates_by_receiver( receiver_ty: &Canonical, - deref_chain: &[Canonical], + rest_of_deref_chain: &[Canonical], db: &impl HirDatabase, resolver: &Resolver, name: Option<&Name>, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { - // TODO: do we need to do the whole loop for inherents before traits? // We're looking for methods with *receiver* type receiver_ty. These could // be found in any of the derefs of receiver_ty, so we have to go through // that. - for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { - if let Some(result) = iterate_method_candidates_inner( + let krate = resolver.krate()?; + for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { + if let Some(result) = + iterate_inherent_methods(self_ty, db, name, Some(receiver_ty), krate, &mut callback) + { + return Some(result); + } + } + for self_ty in std::iter::once(receiver_ty).chain(rest_of_deref_chain) { + if let Some(result) = iterate_trait_method_candidates( self_ty, db, resolver, @@ -300,22 +307,19 @@ fn iterate_method_candidates_by_receiver( None } -fn iterate_method_candidates_inner( +fn iterate_method_candidates_for_self_ty( self_ty: &Canonical, db: &impl HirDatabase, resolver: &Resolver, name: Option<&Name>, - receiver_ty: Option<&Canonical>, mut callback: impl FnMut(&Ty, AssocItemId) -> Option, ) -> Option { let krate = resolver.krate()?; - if let Some(result) = - iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) - { + if let Some(result) = iterate_inherent_methods(self_ty, db, name, None, krate, &mut callback) { return Some(result); } if let Some(result) = - iterate_trait_method_candidates(self_ty, db, resolver, name, receiver_ty, &mut callback) + iterate_trait_method_candidates(self_ty, db, resolver, name, None, &mut callback) { return Some(result); } @@ -412,29 +416,11 @@ fn is_valid_candidate( if !data.has_self_param { return false; } - let substs = match m.lookup(db).container { - hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, item) - .push(self_ty.value.clone()) - .fill_with_unknown() - .build(), - hir_def::ContainerId::ImplId(impl_id) => { - let vars = - Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); - let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); - let self_ty_with_vars = - Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; - if let Some(substs) = super::infer::unify(self_ty_with_vars, &self_ty.value) - { - substs - } else { - return false; - } - } - hir_def::ContainerId::ModuleId(_) => unreachable!(), + let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { + Some(ty) => ty, + None => return false, }; - let sig = db.callable_item_signature(m.into()); - let receiver = sig.params()[0].clone().subst(&substs); - if receiver != receiver_ty.value { + if transformed_receiver_ty != receiver_ty.value { return false; } } @@ -448,6 +434,34 @@ fn is_valid_candidate( } } +pub(crate) fn inherent_impl_substs( + db: &impl HirDatabase, + impl_id: ImplId, + self_ty: &Ty, +) -> Option { + let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); + let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); + let self_ty_with_vars = Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; + super::infer::unify(self_ty_with_vars, self_ty) +} + +fn transform_receiver_ty( + db: &impl HirDatabase, + function_id: FunctionId, + self_ty: &Canonical, +) -> Option { + let substs = match function_id.lookup(db).container { + hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, function_id) + .push(self_ty.value.clone()) + .fill_with_unknown() + .build(), + hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty.value)?, + hir_def::ContainerId::ModuleId(_) => unreachable!(), + }; + let sig = db.callable_item_signature(function_id.into()); + Some(sig.params()[0].clone().subst(&substs)) +} + pub fn implements_trait( ty: &Canonical, db: &impl HirDatabase, diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index be8768c622..d28e835c72 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -3493,6 +3493,21 @@ fn test() { S.foo()<|>; } assert_eq!(t, "i8"); } +#[test] +fn method_resolution_impl_ref_before_trait() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl S { fn foo(&self) -> i8 { 0 } } +impl Trait for &S { fn foo(self) -> u128 { 0 } } +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "i8"); +} + #[test] fn method_resolution_trait_autoderef() { let t = type_at( From a5a07bde049c59059bc4a68b16a49a174d22cf65 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Mon, 2 Dec 2019 19:27:31 +0100 Subject: [PATCH 033/312] Add tests for checking the impl self type --- crates/ra_hir_ty/src/tests.rs | 14 +++++++++ crates/ra_ide/src/completion/complete_dot.rs | 33 ++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index d28e835c72..d5b8d10e2a 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -3433,6 +3433,20 @@ pub fn baz() -> usize { 31usize } assert_eq!("(i32, usize)", type_at_pos(&db, pos)); } +#[test] +fn method_resolution_unify_impl_self_type() { + let t = type_at( + r#" +//- /main.rs +struct S; +impl S { fn foo(&self) -> u8 {} } +impl S { fn foo(&self) -> i8 {} } +fn test() { (S::.foo(), S::.foo())<|>; } +"#, + ); + assert_eq!(t, "(u8, i8)"); +} + #[test] fn method_resolution_trait_before_autoref() { let t = type_at( diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index b6fe486270..a52eb0ee4a 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs @@ -216,6 +216,39 @@ mod tests { ); } + #[test] + fn test_method_completion_only_fitting_impls() { + assert_debug_snapshot!( + do_ref_completion( + r" + struct A {} + impl A { + fn the_method(&self) {} + } + impl A { + fn the_other_method(&self) {} + } + fn foo(a: A) { + a.<|> + } + ", + ), + @r###" + [ + CompletionItem { + label: "the_method()", + source_range: [243; 243), + delete: [243; 243), + insert: "the_method()$0", + kind: Method, + lookup: "the_method", + detail: "fn the_method(&self)", + }, + ] + "### + ); + } + #[test] fn test_trait_method_completion() { assert_debug_snapshot!( From 176207f1e87bb1f2c70529cdbc66ae8c96584b03 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 3 Dec 2019 12:16:39 +0100 Subject: [PATCH 034/312] Extract built-in trait implementations to separate module This untangles the builtin logic from the Chalk translation. --- crates/ra_hir_ty/src/traits.rs | 1 + crates/ra_hir_ty/src/traits/builtin.rs | 161 ++++++++++++++++++++++ crates/ra_hir_ty/src/traits/chalk.rs | 184 ++++++++----------------- 3 files changed, 219 insertions(+), 127 deletions(-) create mode 100644 crates/ra_hir_ty/src/traits/builtin.rs diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 76189a60b1..d49f8fb4b1 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs @@ -15,6 +15,7 @@ use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, use self::chalk::{from_chalk, ToChalk}; pub(crate) mod chalk; +mod builtin; #[derive(Debug, Clone)] pub struct TraitSolver { diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs new file mode 100644 index 0000000000..598fd81e31 --- /dev/null +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -0,0 +1,161 @@ +//! This module provides the built-in trait implementations, e.g. to make +//! closures implement `Fn`. +use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; +use hir_expand::name; +use ra_db::CrateId; + +use super::{AssocTyValue, Impl}; +use crate::{db::HirDatabase, ApplicationTy, Substs, TraitRef, Ty, TypeCtor}; + +pub(super) struct BuiltinImplData { + pub num_vars: usize, + pub trait_ref: TraitRef, + pub where_clauses: Vec, + pub assoc_ty_values: Vec, +} + +pub(super) struct BuiltinImplAssocTyValueData { + pub impl_: Impl, + pub assoc_ty_id: TypeAliasId, + pub num_vars: usize, + pub value: Ty, +} + +pub(super) fn get_builtin_impls( + db: &impl HirDatabase, + krate: CrateId, + ty: &Ty, + trait_: TraitId, + mut callback: impl FnMut(Impl), +) { + if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { + for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() + { + if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { + if trait_ == actual_trait { + let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; + callback(Impl::ClosureFnTraitImpl(impl_)); + } + } + } + } +} + +pub(super) fn impl_datum( + db: &impl HirDatabase, + krate: CrateId, + impl_: Impl, +) -> Option { + match impl_ { + Impl::ImplBlock(_) => unreachable!(), + Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), + } +} + +pub(super) fn associated_ty_value( + db: &impl HirDatabase, + krate: CrateId, + data: AssocTyValue, +) -> BuiltinImplAssocTyValueData { + match data { + AssocTyValue::TypeAlias(_) => unreachable!(), + AssocTyValue::ClosureFnTraitImplOutput(data) => { + closure_fn_trait_output_assoc_ty_value(db, krate, data) + } + } +} + +fn closure_fn_trait_impl_datum( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> Option { + // for some closure |X, Y| -> Z: + // impl Fn<(T, U)> for closure V> { Output = V } + + let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait + + // validate FnOnce trait, since we need it in the assoc ty value definition + // and don't want to return a valid value only to find out later that FnOnce + // is broken + let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; + + let num_args: u16 = match &db.body(data.def.into())[data.expr] { + Expr::Lambda { args, .. } => args.len() as u16, + _ => { + log::warn!("closure for closure type {:?} not found", data); + 0 + } + }; + + let arg_ty = Ty::apply( + TypeCtor::Tuple { cardinality: num_args }, + Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), + ); + let sig_ty = Ty::apply( + TypeCtor::FnPtr { num_args }, + Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), + ); + + let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); + + let trait_ref = TraitRef { + trait_: trait_.into(), + substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), + }; + + let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); + + Some(BuiltinImplData { + num_vars: num_args as usize + 1, + trait_ref, + where_clauses: Vec::new(), + assoc_ty_values: vec![output_ty_id], + }) +} + +fn closure_fn_trait_output_assoc_ty_value( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> BuiltinImplAssocTyValueData { + let impl_ = Impl::ClosureFnTraitImpl(data.clone()); + + let num_args: u16 = match &db.body(data.def.into())[data.expr] { + Expr::Lambda { args, .. } => args.len() as u16, + _ => { + log::warn!("closure for closure type {:?} not found", data); + 0 + } + }; + + let output_ty = Ty::Bound(num_args.into()); + + let fn_once_trait = + get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); + + let output_ty_id = db + .trait_data(fn_once_trait) + .associated_type_by_name(&name::OUTPUT_TYPE) + .expect("assoc ty value should not exist"); + + BuiltinImplAssocTyValueData { + impl_, + assoc_ty_id: output_ty_id, + num_vars: num_args as usize + 1, + value: output_ty, + } +} + +fn get_fn_trait( + db: &impl HirDatabase, + krate: CrateId, + fn_trait: super::FnTrait, +) -> Option { + let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; + match target { + LangItemTarget::TraitId(t) => Some(t), + _ => None, + } +} diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 104346ada5..e3f02fa156 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -8,17 +8,16 @@ use chalk_ir::{ TypeName, UniverseIndex, }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use ra_db::CrateId; use hir_def::{ - expr::Expr, lang_item::LangItemTarget, AssocItemId, AstItemDef, ContainerId, GenericDefId, - ImplId, Lookup, TraitId, TypeAliasId, + AssocItemId, AstItemDef, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, +}; +use ra_db::{ + salsa::{InternId, InternKey}, + CrateId, }; -use hir_expand::name; -use ra_db::salsa::{InternId, InternKey}; - -use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; +use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, @@ -395,6 +394,51 @@ where } } +impl ToChalk for builtin::BuiltinImplData { + type Chalk = chalk_rust_ir::ImplDatum; + + fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum { + let impl_type = chalk_rust_ir::ImplType::External; + let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); + + let impl_datum_bound = + chalk_rust_ir::ImplDatumBound { trait_ref: self.trait_ref.to_chalk(db), where_clauses }; + let associated_ty_value_ids = + self.assoc_ty_values.into_iter().map(|v| v.to_chalk(db)).collect(); + chalk_rust_ir::ImplDatum { + binders: make_binders(impl_datum_bound, self.num_vars), + impl_type, + polarity: chalk_rust_ir::Polarity::Positive, + associated_ty_value_ids, + } + } + + fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum) -> Self { + unimplemented!() + } +} + +impl ToChalk for builtin::BuiltinImplAssocTyValueData { + type Chalk = chalk_rust_ir::AssociatedTyValue; + + fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue { + let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; + + chalk_rust_ir::AssociatedTyValue { + associated_ty_id: self.assoc_ty_id.to_chalk(db), + impl_id: self.impl_.to_chalk(db), + value: make_binders(value_bound, self.num_vars), + } + } + + fn from_chalk( + _db: &impl HirDatabase, + _data: chalk_rust_ir::AssociatedTyValue, + ) -> builtin::BuiltinImplAssocTyValueData { + unimplemented!() + } +} + fn make_binders(value: T, num_vars: usize) -> chalk_ir::Binders { chalk_ir::Binders { value, @@ -456,18 +500,10 @@ where .collect(); let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref().clone()); - if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { - for &fn_trait in - [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() - { - if let Some(actual_trait) = get_fn_trait(self.db, self.krate, fn_trait) { - if trait_ == actual_trait { - let impl_ = super::ClosureFnTraitImplData { def, expr, fn_trait }; - result.push(Impl::ClosureFnTraitImpl(impl_).to_chalk(self.db)); - } - } - } - } + + builtin::get_builtin_impls(self.db, self.krate, &ty, trait_, |i| { + result.push(i.to_chalk(self.db)) + }); debug!("impls_for_trait returned {} impls", result.len()); result @@ -619,7 +655,7 @@ pub(crate) fn impl_datum_query( let impl_: Impl = from_chalk(db, impl_id); match impl_ { Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), - Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), + _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), } .unwrap_or_else(invalid_impl_datum) } @@ -700,63 +736,6 @@ fn invalid_impl_datum() -> Arc> { Arc::new(impl_datum) } -fn closure_fn_trait_impl_datum( - db: &impl HirDatabase, - krate: CrateId, - data: super::ClosureFnTraitImplData, -) -> Option>> { - // for some closure |X, Y| -> Z: - // impl Fn<(T, U)> for closure V> { Output = V } - - let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait - - // validate FnOnce trait, since we need it in the assoc ty value definition - // and don't want to return a valid value only to find out later that FnOnce - // is broken - let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; - - let num_args: u16 = match &db.body(data.def.into())[data.expr] { - Expr::Lambda { args, .. } => args.len() as u16, - _ => { - log::warn!("closure for closure type {:?} not found", data); - 0 - } - }; - - let arg_ty = Ty::apply( - TypeCtor::Tuple { cardinality: num_args }, - Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), - ); - let sig_ty = Ty::apply( - TypeCtor::FnPtr { num_args }, - Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), - ); - - let self_ty = Ty::apply_one(TypeCtor::Closure { def: data.def, expr: data.expr }, sig_ty); - - let trait_ref = TraitRef { - trait_: trait_.into(), - substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), - }; - - let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); - - let impl_type = chalk_rust_ir::ImplType::External; - - let impl_datum_bound = chalk_rust_ir::ImplDatumBound { - trait_ref: trait_ref.to_chalk(db), - where_clauses: Vec::new(), - }; - let impl_datum = ImplDatum { - binders: make_binders(impl_datum_bound, num_args as usize + 1), - impl_type, - polarity: chalk_rust_ir::Polarity::Positive, - associated_ty_value_ids: vec![output_ty_id], - }; - Some(Arc::new(impl_datum)) -} - pub(crate) fn associated_ty_value_query( db: &impl HirDatabase, krate: CrateId, @@ -767,9 +746,7 @@ pub(crate) fn associated_ty_value_query( AssocTyValue::TypeAlias(type_alias) => { type_alias_associated_ty_value(db, krate, type_alias) } - AssocTyValue::ClosureFnTraitImplOutput(data) => { - closure_fn_trait_output_assoc_ty_value(db, krate, data) - } + _ => Arc::new(builtin::associated_ty_value(db, krate, data).to_chalk(db)), } } @@ -802,53 +779,6 @@ fn type_alias_associated_ty_value( Arc::new(value) } -fn closure_fn_trait_output_assoc_ty_value( - db: &impl HirDatabase, - krate: CrateId, - data: super::ClosureFnTraitImplData, -) -> Arc> { - let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); - - let num_args: u16 = match &db.body(data.def.into())[data.expr] { - Expr::Lambda { args, .. } => args.len() as u16, - _ => { - log::warn!("closure for closure type {:?} not found", data); - 0 - } - }; - - let output_ty = Ty::Bound(num_args.into()); - - let fn_once_trait = - get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); - - let output_ty_id = db - .trait_data(fn_once_trait) - .associated_type_by_name(&name::OUTPUT_TYPE) - .expect("assoc ty value should not exist"); - - let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; - - let value = chalk_rust_ir::AssociatedTyValue { - associated_ty_id: output_ty_id.to_chalk(db), - impl_id, - value: make_binders(value_bound, num_args as usize + 1), - }; - Arc::new(value) -} - -fn get_fn_trait( - db: &impl HirDatabase, - krate: CrateId, - fn_trait: super::FnTrait, -) -> Option { - let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; - match target { - LangItemTarget::TraitId(t) => Some(t), - _ => None, - } -} - fn id_from_chalk(chalk_id: chalk_ir::RawId) -> T { T::from_intern_id(InternId::from(chalk_id.index)) } From 18f25acb89304b2eb0a822b7b49b5e66a439ada7 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 3 Dec 2019 13:58:02 +0100 Subject: [PATCH 035/312] Make unify pub(crate) --- crates/ra_hir_ty/src/infer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 0889a6bf9e..d16f1eb46d 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -41,7 +41,7 @@ use super::{ }; use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; -pub use unify::unify; +pub(crate) use unify::unify; macro_rules! ty_app { ($ctor:pat, $param:pat) => { From e4add45951511f9afe348bf6066a724deb0d3ccf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 3 Dec 2019 14:59:29 +0100 Subject: [PATCH 036/312] Fix #2467 The stand-alone `unify` requires that the type doesn't contain any type variables. So we can't share the code here for now (without more refactoring)... --- crates/ra_hir_ty/src/infer/path.rs | 13 ++++++- crates/ra_hir_ty/src/infer/unify.rs | 4 +- crates/ra_hir_ty/src/method_resolution.rs | 8 ++-- crates/ra_hir_ty/src/tests.rs | 47 +++++++++++++++++++++++ 4 files changed, 65 insertions(+), 7 deletions(-) diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index b0024c6e1c..37db005ea5 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -1,5 +1,7 @@ //! Path expression resolution. +use std::iter; + use hir_def::{ path::{Path, PathKind, PathSegment}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, @@ -207,7 +209,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }; let substs = match container { ContainerId::ImplId(impl_id) => { - method_resolution::inherent_impl_substs(self.db, impl_id, &ty) + let impl_substs = Substs::build_for_def(self.db, impl_id) + .fill(iter::repeat_with(|| self.table.new_type_var())) + .build(); + let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); + let substs = Substs::build_for_def(self.db, item) + .use_parent_substs(&impl_substs) + .fill_with_params() + .build(); + self.unify(&impl_self_ty, &ty); + Some(substs) } ContainerId::TraitId(trait_) => { // we're picking this method diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs index 8ed2a6090a..fe05642ae3 100644 --- a/crates/ra_hir_ty/src/infer/unify.rs +++ b/crates/ra_hir_ty/src/infer/unify.rs @@ -167,12 +167,12 @@ impl Canonicalized { } } -pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option { +pub fn unify(ty1: &Canonical, ty2: &Canonical) -> Option { let mut table = InferenceTable::new(); let vars = Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build(); let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); - if !table.unify(&ty_with_vars, ty2) { + if !table.unify(&ty_with_vars, &ty2.value) { return None; } Some( diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 21efb196af..7220d6e0a7 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -437,12 +437,12 @@ fn is_valid_candidate( pub(crate) fn inherent_impl_substs( db: &impl HirDatabase, impl_id: ImplId, - self_ty: &Ty, + self_ty: &Canonical, ) -> Option { let vars = Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build(); let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); - let self_ty_with_vars = Canonical { num_vars: vars.len(), value: &self_ty_with_vars }; - super::infer::unify(self_ty_with_vars, self_ty) + let self_ty_with_vars = Canonical { num_vars: vars.len(), value: self_ty_with_vars }; + super::infer::unify(&self_ty_with_vars, self_ty) } fn transform_receiver_ty( @@ -455,7 +455,7 @@ fn transform_receiver_ty( .push(self_ty.value.clone()) .fill_with_unknown() .build(), - hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty.value)?, + hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, hir_def::ContainerId::ModuleId(_) => unreachable!(), }; let sig = db.callable_item_signature(function_id.into()); diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index d5b8d10e2a..2ea9e261cd 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -4820,6 +4820,53 @@ fn test() where T: Trait, U: Trait { assert_eq!(t, "{unknown}"); } +#[test] +fn bug_2467() { + assert_snapshot!( + infer(r#" +struct S(T); +impl S { + fn foo(self) -> T; +} +fn test() { + // needs to nest multiple times for variable indices to get high enough + let a = S::foo(S(1)); + let b = S::foo(S(a)); + let c = S::foo(S(b)); + let d: u32 = S::foo(S(c)); +} +"#), + @r###" + [43; 47) 'self': S + [67; 255) '{ ...c)); }': () + [153; 154) 'a': u32 + [157; 163) 'S::foo': fn foo(S) -> T + [157; 169) 'S::foo(S(1))': u32 + [164; 165) 'S': S(T) -> S + [164; 168) 'S(1)': S + [166; 167) '1': u32 + [179; 180) 'b': u32 + [183; 189) 'S::foo': fn foo(S) -> T + [183; 195) 'S::foo(S(a))': u32 + [190; 191) 'S': S(T) -> S + [190; 194) 'S(a)': S + [192; 193) 'a': u32 + [205; 206) 'c': u32 + [209; 215) 'S::foo': fn foo(S) -> T + [209; 221) 'S::foo(S(b))': u32 + [216; 217) 'S': S(T) -> S + [216; 220) 'S(b)': S + [218; 219) 'b': u32 + [231; 232) 'd': u32 + [240; 246) 'S::foo': fn foo(S) -> T + [240; 252) 'S::foo(S(c))': u32 + [247; 248) 'S': S(T) -> S + [247; 251) 'S(c)': S + [249; 250) 'c': u32 + "### + ); +} + fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { let file = db.parse(pos.file_id).ok().unwrap(); let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); From 009437f5d9949d2276aa26040e03af0ab328acf3 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 11:07:56 -0500 Subject: [PATCH 037/312] Replace `ra_hir_expand::either` with crate --- Cargo.lock | 4 ++ crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/code_model.rs | 7 ++- crates/ra_hir/src/code_model/src.rs | 12 ++--- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 7 +-- crates/ra_hir_def/Cargo.toml | 1 + crates/ra_hir_def/src/adt.rs | 6 +-- crates/ra_hir_def/src/attr.rs | 7 +-- crates/ra_hir_def/src/body.rs | 9 ++-- crates/ra_hir_def/src/body/lower.rs | 16 +++--- crates/ra_hir_def/src/docs.rs | 6 +-- crates/ra_hir_def/src/nameres.rs | 8 +-- crates/ra_hir_def/src/nameres/raw.rs | 6 +-- crates/ra_hir_def/src/path.rs | 10 ++-- crates/ra_hir_expand/Cargo.toml | 1 + crates/ra_hir_expand/src/either.rs | 54 ------------------- crates/ra_hir_expand/src/hygiene.rs | 6 +-- crates/ra_hir_expand/src/lib.rs | 1 - crates/ra_hir_ty/src/expr.rs | 4 +- crates/ra_ide/Cargo.toml | 1 + crates/ra_ide/src/completion/complete_path.rs | 5 +- .../ra_ide/src/display/navigation_target.rs | 7 +-- 23 files changed, 69 insertions(+), 112 deletions(-) delete mode 100644 crates/ra_hir_expand/src/either.rs diff --git a/Cargo.lock b/Cargo.lock index 57cfde9781..23c9e25436 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -944,6 +944,7 @@ dependencies = [ name = "ra_hir" version = "0.1.0" dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "ra_db 0.1.0", "ra_hir_def 0.1.0", @@ -957,6 +958,7 @@ dependencies = [ name = "ra_hir_def" version = "0.1.0" dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -976,6 +978,7 @@ dependencies = [ name = "ra_hir_expand" version = "0.1.0" dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "ra_arena 0.1.0", "ra_db 0.1.0", @@ -1012,6 +1015,7 @@ dependencies = [ name = "ra_ide" version = "0.1.0" dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "format-buf 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "fst 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index e79361e7cc..6ca9cc2e7d 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -10,6 +10,7 @@ doctest = false [dependencies] log = "0.4.5" rustc-hash = "1.0" +either = "1.5" ra_syntax = { path = "../ra_syntax" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index dddac915bc..5877afefa2 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -4,6 +4,7 @@ pub(crate) mod src; use std::sync::Arc; +use either::Either; use hir_def::{ adt::VariantData, body::{Body, BodySourceMap}, @@ -30,7 +31,7 @@ use crate::{ db::{DefDatabase, HirDatabase}, ty::display::HirFormatter, ty::{self, InEnvironment, InferenceResult, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk}, - CallableDef, Either, HirDisplay, InFile, Name, + CallableDef, HirDisplay, InFile, Name, }; /// hir::Crate describes a single crate. It's the main interface with which @@ -905,7 +906,9 @@ impl Local { let (_body, source_map) = db.body_with_source_map(self.parent.into()); let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm... let root = src.file_syntax(db); - src.map(|ast| ast.map(|it| it.cast().unwrap().to_node(&root), |it| it.to_node(&root))) + src.map(|ast| { + ast.map_left(|it| it.cast().unwrap().to_node(&root)).map_right(|it| it.to_node(&root)) + }) } } diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 2cf2103497..36cfbc8f12 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -1,10 +1,10 @@ //! FIXME: write short doc here +use either::Either; use hir_def::{ src::{HasChildSource, HasSource as _}, AstItemDef, Lookup, VariantId, }; -use hir_expand::either::Either; use ra_syntax::ast; use crate::{ @@ -27,8 +27,8 @@ impl Module { let def_map = db.crate_def_map(self.id.krate); let src = def_map[self.id.local_id].definition_source(db); src.map(|it| match it { - Either::A(it) => ModuleSource::SourceFile(it), - Either::B(it) => ModuleSource::Module(it), + Either::Left(it) => ModuleSource::SourceFile(it), + Either::Right(it) => ModuleSource::Module(it), }) } @@ -46,8 +46,8 @@ impl HasSource for StructField { let var = VariantId::from(self.parent); let src = var.child_source(db); src.map(|it| match it[self.id].clone() { - Either::A(it) => FieldSource::Pos(it), - Either::B(it) => FieldSource::Named(it), + Either::Left(it) => FieldSource::Pos(it), + Either::Right(it) => FieldSource::Named(it), }) } } @@ -126,6 +126,6 @@ impl HasSource for Import { let (_, source_map) = db.raw_items_with_source_map(src.file_id); let root = db.parse_or_expand(src.file_id).unwrap(); let ptr = source_map.get(self.id); - src.with_value(ptr.map(|it| it.to_node(&root), |it| it.to_node(&root))) + src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) } } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 88d2f6e02a..853760cb1a 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -63,5 +63,5 @@ pub use hir_def::{ type_ref::Mutability, }; pub use hir_expand::{ - either::Either, name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, + name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0df7a7cb49..28d41b6474 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,6 +7,7 @@ //! purely for "IDE needs". use std::sync::Arc; +use either::Either; use hir_def::{ body::{ scope::{ExprScopes, ScopeId}, @@ -33,8 +34,8 @@ use crate::{ method_resolution::{self, implements_trait}, InEnvironment, TraitEnvironment, Ty, }, - Adt, AssocItem, Const, DefWithBody, Either, Enum, EnumVariant, FromSource, Function, - GenericParam, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, + Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, GenericParam, + Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option { @@ -349,7 +350,7 @@ impl SourceAnalyzer { // should switch to general reference search infra there. pub fn find_all_refs(&self, pat: &ast::BindPat) -> Vec { let fn_def = pat.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); - let ptr = Either::A(AstPtr::new(&ast::Pat::from(pat.clone()))); + let ptr = Either::Left(AstPtr::new(&ast::Pat::from(pat.clone()))); fn_def .syntax() .descendants() diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index 7e65f4c1d5..cf3a446fcc 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml @@ -11,6 +11,7 @@ doctest = false log = "0.4.5" once_cell = "1.0.1" rustc-hash = "1.0" +either = "1.5" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 9ab829aab2..db3e63ef82 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -2,8 +2,8 @@ use std::sync::Arc; +use either::Either; use hir_expand::{ - either::Either, name::{AsName, Name}, InFile, }; @@ -184,7 +184,7 @@ fn lower_struct( ast::StructKind::Tuple(fl) => { for (i, fd) in fl.fields().enumerate() { trace.alloc( - || Either::A(fd.clone()), + || Either::Left(fd.clone()), || StructFieldData { name: Name::new_tuple_field(i), type_ref: TypeRef::from_ast_opt(fd.type_ref()), @@ -196,7 +196,7 @@ fn lower_struct( ast::StructKind::Record(fl) => { for fd in fl.fields() { trace.alloc( - || Either::B(fd.clone()), + || Either::Right(fd.clone()), || StructFieldData { name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), type_ref: TypeRef::from_ast_opt(fd.ascribed_type()), diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index bc7ade9212..7f9a6e7ca8 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -2,7 +2,8 @@ use std::{ops, sync::Arc}; -use hir_expand::{either::Either, hygiene::Hygiene, AstId, InFile}; +use either::Either; +use hir_expand::{hygiene::Hygiene, AstId, InFile}; use mbe::ast_to_token_tree; use ra_syntax::{ ast::{self, AstNode, AttrsOwner}, @@ -45,8 +46,8 @@ impl Attrs { AttrDefId::StructFieldId(it) => { let src = it.parent.child_source(db); match &src.value[it.local_id] { - Either::A(_tuple) => Attrs::default(), - Either::B(record) => Attrs::from_attrs_owner(db, src.with_value(record)), + Either::Left(_tuple) => Attrs::default(), + Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)), } } AttrDefId::EnumVariantId(var_id) => { diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 239f35229a..ef18168363 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -5,9 +5,8 @@ pub mod scope; use std::{ops::Index, sync::Arc}; -use hir_expand::{ - either::Either, hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId, MacroFileKind, -}; +use either::Either; +use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId, MacroFileKind}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -210,7 +209,7 @@ impl BodySourceMap { } pub fn node_expr(&self, node: InFile<&ast::Expr>) -> Option { - let src = node.map(|it| Either::A(AstPtr::new(it))); + let src = node.map(|it| Either::Left(AstPtr::new(it))); self.expr_map.get(&src).cloned() } @@ -219,7 +218,7 @@ impl BodySourceMap { } pub fn node_pat(&self, node: InFile<&ast::Pat>) -> Option { - let src = node.map(|it| Either::A(AstPtr::new(it))); + let src = node.map(|it| Either::Left(AstPtr::new(it))); self.pat_map.get(&src).cloned() } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index be1eaa5234..71c08f0247 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -1,10 +1,8 @@ //! Transforms `ast::Expr` into an equivalent `hir_def::expr::Expr` //! representation. -use hir_expand::{ - either::Either, - name::{self, AsName, Name}, -}; +use either::Either; +use hir_expand::name::{self, AsName, Name}; use ra_arena::Arena; use ra_syntax::{ ast::{ @@ -74,7 +72,7 @@ where mode: BindingAnnotation::Unannotated, subpat: None, }, - Either::B(ptr), + Either::Right(ptr), ); self.body.params.push(param_pat); } @@ -94,7 +92,7 @@ where } fn alloc_expr(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { - let ptr = Either::A(ptr); + let ptr = Either::Left(ptr); let id = self.body.exprs.alloc(expr); let src = self.expander.to_source(ptr); self.source_map.expr_map.insert(src, id); @@ -107,7 +105,7 @@ where self.body.exprs.alloc(expr) } fn alloc_expr_field_shorthand(&mut self, expr: Expr, ptr: AstPtr) -> ExprId { - let ptr = Either::B(ptr); + let ptr = Either::Right(ptr); let id = self.body.exprs.alloc(expr); let src = self.expander.to_source(ptr); self.source_map.expr_map.insert(src, id); @@ -277,7 +275,7 @@ where ast::Expr::ParenExpr(e) => { let inner = self.collect_expr_opt(e.expr()); // make the paren expr point to the inner expression as well - let src = self.expander.to_source(Either::A(syntax_ptr)); + let src = self.expander.to_source(Either::Left(syntax_ptr)); self.source_map.expr_map.insert(src, inner); inner } @@ -550,7 +548,7 @@ where ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing, }; let ptr = AstPtr::new(&pat); - self.alloc_pat(pattern, Either::A(ptr)) + self.alloc_pat(pattern, Either::Left(ptr)) } fn collect_pat_opt(&mut self, pat: Option) -> PatId { diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index ec944373da..3fc6d6934c 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -5,7 +5,7 @@ use std::sync::Arc; -use hir_expand::either::Either; +use either::Either; use ra_syntax::ast; use crate::{ @@ -46,8 +46,8 @@ impl Documentation { AttrDefId::StructFieldId(it) => { let src = it.parent.child_source(db); match &src.value[it.local_id] { - Either::A(_tuple) => None, - Either::B(record) => docs_from_ast(record), + Either::Left(_tuple) => None, + Either::Right(record) => docs_from_ast(record), } } AttrDefId::AdtId(it) => match it { diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 3e15218704..faf3566f44 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -57,9 +57,9 @@ mod tests; use std::sync::Arc; +use either::Either; use hir_expand::{ - ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, InFile, - MacroDefId, + ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId, }; use once_cell::sync::Lazy; use ra_arena::Arena; @@ -287,10 +287,10 @@ impl ModuleData { ) -> InFile> { if let Some(file_id) = self.definition { let sf = db.parse(file_id).tree(); - return InFile::new(file_id.into(), Either::A(sf)); + return InFile::new(file_id.into(), Either::Left(sf)); } let decl = self.declaration.unwrap(); - InFile::new(decl.file_id, Either::B(decl.to_node(db))) + InFile::new(decl.file_id, Either::Right(decl.to_node(db))) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 5196b67cad..de4e706c29 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -7,10 +7,10 @@ use std::{ops::Index, sync::Arc}; +use either::Either; use hir_expand::{ ast_id_map::AstIdMap, db::AstDatabase, - either::Either, hygiene::Hygiene, name::{AsName, Name}, }; @@ -324,7 +324,7 @@ impl RawItemsCollector { is_extern_crate: false, is_macro_use: false, }; - buf.push((import_data, Either::A(AstPtr::new(use_tree)))); + buf.push((import_data, Either::Left(AstPtr::new(use_tree)))); }, ); for (import_data, ptr) in buf { @@ -355,7 +355,7 @@ impl RawItemsCollector { current_module, attrs, import_data, - Either::B(AstPtr::new(&extern_crate)), + Either::Right(AstPtr::new(&extern_crate)), ); } } diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ff252fe442..3030dcdf6e 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -2,8 +2,8 @@ use std::{iter, sync::Arc}; +use either::Either; use hir_expand::{ - either::Either, hygiene::Hygiene, name::{self, AsName, Name}, }; @@ -111,7 +111,7 @@ impl Path { ast::PathSegmentKind::Name(name_ref) => { // FIXME: this should just return name match hygiene.name_ref_to_name(name_ref) { - Either::A(name) => { + Either::Left(name) => { let args = segment .type_arg_list() .and_then(GenericArgs::from_ast) @@ -125,7 +125,7 @@ impl Path { let segment = PathSegment { name, args_and_bindings: args }; segments.push(segment); } - Either::B(crate_id) => { + Either::Right(crate_id) => { kind = PathKind::DollarCrate(crate_id); break; } @@ -347,7 +347,7 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt let res = match segment.kind()? { ast::PathSegmentKind::Name(name_ref) => { match hygiene.name_ref_to_name(name_ref) { - Either::A(name) => { + Either::Left(name) => { // no type args in use let mut res = prefix.unwrap_or_else(|| Path { kind: PathKind::Plain, @@ -359,7 +359,7 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt }); res } - Either::B(crate_id) => { + Either::Right(crate_id) => { return Some(Path::from_simple_segments( PathKind::DollarCrate(crate_id), iter::empty(), diff --git a/crates/ra_hir_expand/Cargo.toml b/crates/ra_hir_expand/Cargo.toml index c60152a799..3ae4376dc7 100644 --- a/crates/ra_hir_expand/Cargo.toml +++ b/crates/ra_hir_expand/Cargo.toml @@ -9,6 +9,7 @@ doctest = false [dependencies] log = "0.4.5" +either = "1.5" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_expand/src/either.rs b/crates/ra_hir_expand/src/either.rs deleted file mode 100644 index 83583ef8bd..0000000000 --- a/crates/ra_hir_expand/src/either.rs +++ /dev/null @@ -1,54 +0,0 @@ -//! FIXME: write short doc here - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum Either { - A(A), - B(B), -} - -impl Either { - pub fn either(self, f1: F1, f2: F2) -> R - where - F1: FnOnce(A) -> R, - F2: FnOnce(B) -> R, - { - match self { - Either::A(a) => f1(a), - Either::B(b) => f2(b), - } - } - pub fn map(self, f1: F1, f2: F2) -> Either - where - F1: FnOnce(A) -> U, - F2: FnOnce(B) -> V, - { - match self { - Either::A(a) => Either::A(f1(a)), - Either::B(b) => Either::B(f2(b)), - } - } - pub fn map_a(self, f: F) -> Either - where - F: FnOnce(A) -> U, - { - self.map(f, |it| it) - } - pub fn a(self) -> Option { - match self { - Either::A(it) => Some(it), - Either::B(_) => None, - } - } - pub fn b(self) -> Option { - match self { - Either::A(_) => None, - Either::B(it) => Some(it), - } - } - pub fn as_ref(&self) -> Either<&A, &B> { - match self { - Either::A(it) => Either::A(it), - Either::B(it) => Either::B(it), - } - } -} diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index 379562a2c1..64c8b06c6e 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs @@ -2,12 +2,12 @@ //! //! Specifically, `ast` + `Hygiene` allows you to create a `Name`. Note that, at //! this moment, this is horribly incomplete and handles only `$crate`. +use either::Either; use ra_db::CrateId; use ra_syntax::ast; use crate::{ db::AstDatabase, - either::Either, name::{AsName, Name}, HirFileId, HirFileIdRepr, MacroDefKind, }; @@ -41,9 +41,9 @@ impl Hygiene { pub fn name_ref_to_name(&self, name_ref: ast::NameRef) -> Either { if let Some(def_crate) = self.def_crate { if name_ref.text() == "$crate" { - return Either::B(def_crate); + return Either::Right(def_crate); } } - Either::A(name_ref.as_name()) + Either::Left(name_ref.as_name()) } } diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index fb88d2ac27..3be9bdf869 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -6,7 +6,6 @@ pub mod db; pub mod ast_id_map; -pub mod either; pub mod name; pub mod hygiene; pub mod diagnostics; diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index 5c65f93707..d2bd64e5cc 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs @@ -97,7 +97,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { let (_, source_map) = db.body_with_source_map(self.func.into()); if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.value.a() { + if let Some(expr) = source_ptr.value.left() { let root = source_ptr.file_syntax(db); if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { if let Some(field_list) = record_lit.record_field_list() { @@ -142,7 +142,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { let (_, source_map) = db.body_with_source_map(self.func.into()); if let Some(source_ptr) = source_map.expr_syntax(id) { - if let Some(expr) = source_ptr.value.a() { + if let Some(expr) = source_ptr.value.left() { self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); } } diff --git a/crates/ra_ide/Cargo.toml b/crates/ra_ide/Cargo.toml index e6383dd352..e3439ae313 100644 --- a/crates/ra_ide/Cargo.toml +++ b/crates/ra_ide/Cargo.toml @@ -11,6 +11,7 @@ doctest = false wasm = [] [dependencies] +either = "1.5" format-buf = "1.0.0" itertools = "0.8.0" join_to_string = "0.1.3" diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 89e0009a17..28f94e0a77 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here -use hir::{Adt, Either, HasSource, PathResolution}; +use either::Either; +use hir::{Adt, HasSource, PathResolution}; use ra_syntax::AstNode; use test_utils::tested_by; @@ -27,7 +28,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { } if Some(module) == ctx.module { if let Some(import) = import { - if let Either::A(use_tree) = import.source(ctx.db).value { + if let Either::Left(use_tree) = import.source(ctx.db).value { if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { // for `use self::foo<|>`, don't suggest `foo` as a completion tested_by!(dont_complete_current_use); diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 61dca14ac5..f920d3db62 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here -use hir::{AssocItem, Either, FieldSource, HasSource, InFile, ModuleSource}; +use either::Either; +use hir::{AssocItem, FieldSource, HasSource, InFile, ModuleSource}; use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, @@ -342,10 +343,10 @@ impl ToNav for hir::Local { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); let (full_range, focus_range) = match src.value { - Either::A(it) => { + Either::Left(it) => { (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) } - Either::B(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), + Either::Right(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), }; let name = match self.name(db) { Some(it) => it.to_string().into(), From 9747156f6c5c9b5cccc347a68042e6d9a6b0f704 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Tue, 3 Dec 2019 13:38:54 +0100 Subject: [PATCH 038/312] Split up ty tests a bit --- crates/ra_hir_ty/src/tests.rs | 4908 +---------------- crates/ra_hir_ty/src/tests/macros.rs | 268 + .../ra_hir_ty/src/tests/method_resolution.rs | 1005 ++++ crates/ra_hir_ty/src/tests/patterns.rs | 238 + crates/ra_hir_ty/src/tests/regression.rs | 333 ++ crates/ra_hir_ty/src/tests/simple.rs | 1608 ++++++ crates/ra_hir_ty/src/tests/traits.rs | 1424 +++++ 7 files changed, 4882 insertions(+), 4902 deletions(-) create mode 100644 crates/ra_hir_ty/src/tests/macros.rs create mode 100644 crates/ra_hir_ty/src/tests/method_resolution.rs create mode 100644 crates/ra_hir_ty/src/tests/patterns.rs create mode 100644 crates/ra_hir_ty/src/tests/regression.rs create mode 100644 crates/ra_hir_ty/src/tests/simple.rs create mode 100644 crates/ra_hir_ty/src/tests/traits.rs diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 2ea9e261cd..c520bb375e 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -1,5 +1,11 @@ mod never_type; mod coercion; +mod regression; +mod simple; +mod patterns; +mod traits; +mod method_resolution; +mod macros; use std::fmt::Write; use std::sync::Arc; @@ -15,7 +21,6 @@ use ra_syntax::{ algo, ast::{self, AstNode}, }; -use test_utils::covers; use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; @@ -23,4850 +28,6 @@ use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResu // against snapshots of the expected results using insta. Use cargo-insta to // update the snapshots. -#[test] -fn cfg_impl_block() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:foo cfg:test -use foo::S as T; -struct S; - -#[cfg(test)] -impl S { - fn foo1(&self) -> i32 { 0 } -} - -#[cfg(not(test))] -impl S { - fn foo2(&self) -> i32 { 0 } -} - -fn test() { - let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4()); - t<|>; -} - -//- /foo.rs crate:foo -struct S; - -#[cfg(not(test))] -impl S { - fn foo3(&self) -> i32 { 0 } -} - -#[cfg(test)] -impl S { - fn foo4(&self) -> i32 { 0 } -} -"#, - ); - assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos)); -} - -#[test] -fn infer_await() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std - -struct IntFuture; - -impl Future for IntFuture { - type Output = u64; -} - -fn test() { - let r = IntFuture; - let v = r.await; - v<|>; -} - -//- /std.rs crate:std -#[prelude_import] use future::*; -mod future { - trait Future { - type Output; - } -} - -"#, - ); - assert_eq!("u64", type_at_pos(&db, pos)); -} - -#[test] -fn infer_box() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std - -fn test() { - let x = box 1; - let t = (x, box x, box &1, box [1]); - t<|>; -} - -//- /std.rs crate:std -#[prelude_import] use prelude::*; -mod prelude {} - -mod boxed { - pub struct Box { - inner: *mut T, - } -} - -"#, - ); - assert_eq!("(Box, Box>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos)); -} - -#[test] -fn infer_adt_self() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs -enum Nat { Succ(Self), Demo(Nat), Zero } - -fn test() { - let foo: Nat = Nat::Zero; - if let Nat::Succ(x) = foo { - x<|> - } -} - -"#, - ); - assert_eq!("Nat", type_at_pos(&db, pos)); -} - -#[test] -fn infer_try() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std - -fn test() { - let r: Result = Result::Ok(1); - let v = r?; - v<|>; -} - -//- /std.rs crate:std - -#[prelude_import] use ops::*; -mod ops { - trait Try { - type Ok; - type Error; - } -} - -#[prelude_import] use result::*; -mod result { - enum Result { - Ok(O), - Err(E) - } - - impl crate::ops::Try for Result { - type Ok = O; - type Error = E; - } -} - -"#, - ); - assert_eq!("i32", type_at_pos(&db, pos)); -} - -#[test] -fn infer_for_loop() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std - -use std::collections::Vec; - -fn test() { - let v = Vec::new(); - v.push("foo"); - for x in v { - x<|>; - } -} - -//- /std.rs crate:std - -#[prelude_import] use iter::*; -mod iter { - trait IntoIterator { - type Item; - } -} - -mod collections { - struct Vec {} - impl Vec { - fn new() -> Self { Vec {} } - fn push(&mut self, t: T) { } - } - - impl crate::iter::IntoIterator for Vec { - type Item=T; - } -} -"#, - ); - assert_eq!("&str", type_at_pos(&db, pos)); -} - -#[test] -fn infer_ranges() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std -fn test() { - let a = ..; - let b = 1..; - let c = ..2u32; - let d = 1..2usize; - let e = ..=10; - let f = 'a'..='z'; - - let t = (a, b, c, d, e, f); - t<|>; -} - -//- /std.rs crate:std -#[prelude_import] use prelude::*; -mod prelude {} - -pub mod ops { - pub struct Range { - pub start: Idx, - pub end: Idx, - } - pub struct RangeFrom { - pub start: Idx, - } - struct RangeFull; - pub struct RangeInclusive { - start: Idx, - end: Idx, - is_empty: u8, - } - pub struct RangeTo { - pub end: Idx, - } - pub struct RangeToInclusive { - pub end: Idx, - } -} -"#, - ); - assert_eq!( - "(RangeFull, RangeFrom, RangeTo, Range, RangeToInclusive, RangeInclusive)", - type_at_pos(&db, pos), - ); -} - -#[test] -fn infer_while_let() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs -enum Option { Some(T), None } - -fn test() { - let foo: Option = None; - while let Option::Some(x) = foo { - <|>x - } -} - -"#, - ); - assert_eq!("f32", type_at_pos(&db, pos)); -} - -#[test] -fn infer_basics() { - assert_snapshot!( - infer(r#" -fn test(a: u32, b: isize, c: !, d: &str) { - a; - b; - c; - d; - 1usize; - 1isize; - "test"; - 1.0f32; -}"#), - @r###" - [9; 10) 'a': u32 - [17; 18) 'b': isize - [27; 28) 'c': ! - [33; 34) 'd': &str - [42; 121) '{ ...f32; }': ! - [48; 49) 'a': u32 - [55; 56) 'b': isize - [62; 63) 'c': ! - [69; 70) 'd': &str - [76; 82) '1usize': usize - [88; 94) '1isize': isize - [100; 106) '"test"': &str - [112; 118) '1.0f32': f32 - "### - ); -} - -#[test] -fn infer_let() { - assert_snapshot!( - infer(r#" -fn test() { - let a = 1isize; - let b: usize = 1; - let c = b; - let d: u32; - let e; - let f: i32 = e; -} -"#), - @r###" - [11; 118) '{ ...= e; }': () - [21; 22) 'a': isize - [25; 31) '1isize': isize - [41; 42) 'b': usize - [52; 53) '1': usize - [63; 64) 'c': usize - [67; 68) 'b': usize - [78; 79) 'd': u32 - [94; 95) 'e': i32 - [105; 106) 'f': i32 - [114; 115) 'e': i32 - "### - ); -} - -#[test] -fn infer_paths() { - assert_snapshot!( - infer(r#" -fn a() -> u32 { 1 } - -mod b { - fn c() -> u32 { 1 } -} - -fn test() { - a(); - b::c(); -} -"#), - @r###" - [15; 20) '{ 1 }': u32 - [17; 18) '1': u32 - [48; 53) '{ 1 }': u32 - [50; 51) '1': u32 - [67; 91) '{ ...c(); }': () - [73; 74) 'a': fn a() -> u32 - [73; 76) 'a()': u32 - [82; 86) 'b::c': fn c() -> u32 - [82; 88) 'b::c()': u32 - "### - ); -} - -#[test] -fn infer_path_type() { - assert_snapshot!( - infer(r#" -struct S; - -impl S { - fn foo() -> i32 { 1 } -} - -fn test() { - S::foo(); - ::foo(); -} -"#), - @r###" - [41; 46) '{ 1 }': i32 - [43; 44) '1': i32 - [60; 93) '{ ...o(); }': () - [66; 72) 'S::foo': fn foo() -> i32 - [66; 74) 'S::foo()': i32 - [80; 88) '::foo': fn foo() -> i32 - [80; 90) '::foo()': i32 - "### - ); -} - -#[test] -fn infer_slice_method() { - assert_snapshot!( - infer(r#" -#[lang = "slice"] -impl [T] { - fn foo(&self) -> T { - loop {} - } -} - -#[lang = "slice_alloc"] -impl [T] {} - -fn test() { - <[_]>::foo(b"foo"); -} -"#), - @r###" - [45; 49) 'self': &[T] - [56; 79) '{ ... }': T - [66; 73) 'loop {}': ! - [71; 73) '{}': () - [133; 160) '{ ...o"); }': () - [139; 149) '<[_]>::foo': fn foo(&[T]) -> T - [139; 157) '<[_]>:..."foo")': u8 - [150; 156) 'b"foo"': &[u8] - "### - ); -} - -#[test] -fn infer_struct() { - assert_snapshot!( - infer(r#" -struct A { - b: B, - c: C, -} -struct B; -struct C(usize); - -fn test() { - let c = C(1); - B; - let a: A = A { b: B, c: C(1) }; - a.b; - a.c; -} -"#), - @r###" - [72; 154) '{ ...a.c; }': () - [82; 83) 'c': C - [86; 87) 'C': C(usize) -> C - [86; 90) 'C(1)': C - [88; 89) '1': usize - [96; 97) 'B': B - [107; 108) 'a': A - [114; 133) 'A { b:...C(1) }': A - [121; 122) 'B': B - [127; 128) 'C': C(usize) -> C - [127; 131) 'C(1)': C - [129; 130) '1': usize - [139; 140) 'a': A - [139; 142) 'a.b': B - [148; 149) 'a': A - [148; 151) 'a.c': C - "### - ); -} - -#[test] -fn infer_enum() { - assert_snapshot!( - infer(r#" -enum E { - V1 { field: u32 }, - V2 -} -fn test() { - E::V1 { field: 1 }; - E::V2; -}"#), - @r###" - [48; 82) '{ E:...:V2; }': () - [52; 70) 'E::V1 ...d: 1 }': E - [67; 68) '1': u32 - [74; 79) 'E::V2': E - "### - ); -} - -#[test] -fn infer_refs() { - assert_snapshot!( - infer(r#" -fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { - a; - *a; - &a; - &mut a; - b; - *b; - &b; - c; - *c; - d; - *d; -} -"#), - @r###" - [9; 10) 'a': &u32 - [18; 19) 'b': &mut u32 - [31; 32) 'c': *const u32 - [46; 47) 'd': *mut u32 - [59; 150) '{ ... *d; }': () - [65; 66) 'a': &u32 - [72; 74) '*a': u32 - [73; 74) 'a': &u32 - [80; 82) '&a': &&u32 - [81; 82) 'a': &u32 - [88; 94) '&mut a': &mut &u32 - [93; 94) 'a': &u32 - [100; 101) 'b': &mut u32 - [107; 109) '*b': u32 - [108; 109) 'b': &mut u32 - [115; 117) '&b': &&mut u32 - [116; 117) 'b': &mut u32 - [123; 124) 'c': *const u32 - [130; 132) '*c': u32 - [131; 132) 'c': *const u32 - [138; 139) 'd': *mut u32 - [145; 147) '*d': u32 - [146; 147) 'd': *mut u32 - "### - ); -} - -#[test] -fn infer_literals() { - assert_snapshot!( - infer(r##" -fn test() { - 5i32; - 5f32; - 5f64; - "hello"; - b"bytes"; - 'c'; - b'b'; - 3.14; - 5000; - false; - true; - r#" - //! doc - // non-doc - mod foo {} - "#; - br#"yolo"#; -} -"##), - @r###" - [11; 221) '{ ...o"#; }': () - [17; 21) '5i32': i32 - [27; 31) '5f32': f32 - [37; 41) '5f64': f64 - [47; 54) '"hello"': &str - [60; 68) 'b"bytes"': &[u8] - [74; 77) ''c'': char - [83; 87) 'b'b'': u8 - [93; 97) '3.14': f64 - [103; 107) '5000': i32 - [113; 118) 'false': bool - [124; 128) 'true': bool - [134; 202) 'r#" ... "#': &str - [208; 218) 'br#"yolo"#': &[u8] - "### - ); -} - -#[test] -fn infer_unary_op() { - assert_snapshot!( - infer(r#" -enum SomeType {} - -fn test(x: SomeType) { - let b = false; - let c = !b; - let a = 100; - let d: i128 = -a; - let e = -100; - let f = !!!true; - let g = !42; - let h = !10u32; - let j = !a; - -3.14; - !3; - -x; - !x; - -"hello"; - !"hello"; -} -"#), - @r###" - [27; 28) 'x': SomeType - [40; 272) '{ ...lo"; }': () - [50; 51) 'b': bool - [54; 59) 'false': bool - [69; 70) 'c': bool - [73; 75) '!b': bool - [74; 75) 'b': bool - [85; 86) 'a': i128 - [89; 92) '100': i128 - [102; 103) 'd': i128 - [112; 114) '-a': i128 - [113; 114) 'a': i128 - [124; 125) 'e': i32 - [128; 132) '-100': i32 - [129; 132) '100': i32 - [142; 143) 'f': bool - [146; 153) '!!!true': bool - [147; 153) '!!true': bool - [148; 153) '!true': bool - [149; 153) 'true': bool - [163; 164) 'g': i32 - [167; 170) '!42': i32 - [168; 170) '42': i32 - [180; 181) 'h': u32 - [184; 190) '!10u32': u32 - [185; 190) '10u32': u32 - [200; 201) 'j': i128 - [204; 206) '!a': i128 - [205; 206) 'a': i128 - [212; 217) '-3.14': f64 - [213; 217) '3.14': f64 - [223; 225) '!3': i32 - [224; 225) '3': i32 - [231; 233) '-x': {unknown} - [232; 233) 'x': SomeType - [239; 241) '!x': {unknown} - [240; 241) 'x': SomeType - [247; 255) '-"hello"': {unknown} - [248; 255) '"hello"': &str - [261; 269) '!"hello"': {unknown} - [262; 269) '"hello"': &str - "### - ); -} - -#[test] -fn infer_backwards() { - assert_snapshot!( - infer(r#" -fn takes_u32(x: u32) {} - -struct S { i32_field: i32 } - -fn test() -> &mut &f64 { - let a = unknown_function(); - takes_u32(a); - let b = unknown_function(); - S { i32_field: b }; - let c = unknown_function(); - &mut &c -} -"#), - @r###" - [14; 15) 'x': u32 - [22; 24) '{}': () - [78; 231) '{ ...t &c }': &mut &f64 - [88; 89) 'a': u32 - [92; 108) 'unknow...nction': {unknown} - [92; 110) 'unknow...tion()': u32 - [116; 125) 'takes_u32': fn takes_u32(u32) -> () - [116; 128) 'takes_u32(a)': () - [126; 127) 'a': u32 - [138; 139) 'b': i32 - [142; 158) 'unknow...nction': {unknown} - [142; 160) 'unknow...tion()': i32 - [166; 184) 'S { i3...d: b }': S - [181; 182) 'b': i32 - [194; 195) 'c': f64 - [198; 214) 'unknow...nction': {unknown} - [198; 216) 'unknow...tion()': f64 - [222; 229) '&mut &c': &mut &f64 - [227; 229) '&c': &f64 - [228; 229) 'c': f64 - "### - ); -} - -#[test] -fn infer_self() { - assert_snapshot!( - infer(r#" -struct S; - -impl S { - fn test(&self) { - self; - } - fn test2(self: &Self) { - self; - } - fn test3() -> Self { - S {} - } - fn test4() -> Self { - Self {} - } -} -"#), - @r###" - [34; 38) 'self': &S - [40; 61) '{ ... }': () - [50; 54) 'self': &S - [75; 79) 'self': &S - [88; 109) '{ ... }': () - [98; 102) 'self': &S - [133; 153) '{ ... }': S - [143; 147) 'S {}': S - [177; 200) '{ ... }': S - [187; 194) 'Self {}': S - "### - ); -} - -#[test] -fn infer_binary_op() { - assert_snapshot!( - infer(r#" -fn f(x: bool) -> i32 { - 0i32 -} - -fn test() -> bool { - let x = a && b; - let y = true || false; - let z = x == y; - let t = x != y; - let minus_forty: isize = -40isize; - let h = minus_forty <= CONST_2; - let c = f(z || y) + 5; - let d = b; - let g = minus_forty ^= i; - let ten: usize = 10; - let ten_is_eleven = ten == some_num; - - ten < 3 -} -"#), - @r###" - [6; 7) 'x': bool - [22; 34) '{ 0i32 }': i32 - [28; 32) '0i32': i32 - [54; 370) '{ ... < 3 }': bool - [64; 65) 'x': bool - [68; 69) 'a': bool - [68; 74) 'a && b': bool - [73; 74) 'b': bool - [84; 85) 'y': bool - [88; 92) 'true': bool - [88; 101) 'true || false': bool - [96; 101) 'false': bool - [111; 112) 'z': bool - [115; 116) 'x': bool - [115; 121) 'x == y': bool - [120; 121) 'y': bool - [131; 132) 't': bool - [135; 136) 'x': bool - [135; 141) 'x != y': bool - [140; 141) 'y': bool - [151; 162) 'minus_forty': isize - [172; 180) '-40isize': isize - [173; 180) '40isize': isize - [190; 191) 'h': bool - [194; 205) 'minus_forty': isize - [194; 216) 'minus_...ONST_2': bool - [209; 216) 'CONST_2': isize - [226; 227) 'c': i32 - [230; 231) 'f': fn f(bool) -> i32 - [230; 239) 'f(z || y)': i32 - [230; 243) 'f(z || y) + 5': i32 - [232; 233) 'z': bool - [232; 238) 'z || y': bool - [237; 238) 'y': bool - [242; 243) '5': i32 - [253; 254) 'd': {unknown} - [257; 258) 'b': {unknown} - [268; 269) 'g': () - [272; 283) 'minus_forty': isize - [272; 288) 'minus_...y ^= i': () - [287; 288) 'i': isize - [298; 301) 'ten': usize - [311; 313) '10': usize - [323; 336) 'ten_is_eleven': bool - [339; 342) 'ten': usize - [339; 354) 'ten == some_num': bool - [346; 354) 'some_num': usize - [361; 364) 'ten': usize - [361; 368) 'ten < 3': bool - [367; 368) '3': usize - "### - ); -} - -#[test] -fn infer_field_autoderef() { - assert_snapshot!( - infer(r#" -struct A { - b: B, -} -struct B; - -fn test1(a: A) { - let a1 = a; - a1.b; - let a2 = &a; - a2.b; - let a3 = &mut a; - a3.b; - let a4 = &&&&&&&a; - a4.b; - let a5 = &mut &&mut &&mut a; - a5.b; -} - -fn test2(a1: *const A, a2: *mut A) { - a1.b; - a2.b; -} -"#), - @r###" - [44; 45) 'a': A - [50; 213) '{ ...5.b; }': () - [60; 62) 'a1': A - [65; 66) 'a': A - [72; 74) 'a1': A - [72; 76) 'a1.b': B - [86; 88) 'a2': &A - [91; 93) '&a': &A - [92; 93) 'a': A - [99; 101) 'a2': &A - [99; 103) 'a2.b': B - [113; 115) 'a3': &mut A - [118; 124) '&mut a': &mut A - [123; 124) 'a': A - [130; 132) 'a3': &mut A - [130; 134) 'a3.b': B - [144; 146) 'a4': &&&&&&&A - [149; 157) '&&&&&&&a': &&&&&&&A - [150; 157) '&&&&&&a': &&&&&&A - [151; 157) '&&&&&a': &&&&&A - [152; 157) '&&&&a': &&&&A - [153; 157) '&&&a': &&&A - [154; 157) '&&a': &&A - [155; 157) '&a': &A - [156; 157) 'a': A - [163; 165) 'a4': &&&&&&&A - [163; 167) 'a4.b': B - [177; 179) 'a5': &mut &&mut &&mut A - [182; 200) '&mut &...&mut a': &mut &&mut &&mut A - [187; 200) '&&mut &&mut a': &&mut &&mut A - [188; 200) '&mut &&mut a': &mut &&mut A - [193; 200) '&&mut a': &&mut A - [194; 200) '&mut a': &mut A - [199; 200) 'a': A - [206; 208) 'a5': &mut &&mut &&mut A - [206; 210) 'a5.b': B - [224; 226) 'a1': *const A - [238; 240) 'a2': *mut A - [250; 273) '{ ...2.b; }': () - [256; 258) 'a1': *const A - [256; 260) 'a1.b': B - [266; 268) 'a2': *mut A - [266; 270) 'a2.b': B - "### - ); -} - -#[test] -fn infer_argument_autoderef() { - assert_snapshot!( - infer(r#" -#[lang = "deref"] -pub trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct A(T); - -impl A { - fn foo(&self) -> &T { - &self.0 - } -} - -struct B(T); - -impl Deref for B { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -fn test() { - let t = A::foo(&&B(B(A(42)))); -} -"#), - @r###" - [68; 72) 'self': &Self - [139; 143) 'self': &A - [151; 174) '{ ... }': &T - [161; 168) '&self.0': &T - [162; 166) 'self': &A - [162; 168) 'self.0': T - [255; 259) 'self': &B - [278; 301) '{ ... }': &T - [288; 295) '&self.0': &T - [289; 293) 'self': &B - [289; 295) 'self.0': T - [315; 353) '{ ...))); }': () - [325; 326) 't': &i32 - [329; 335) 'A::foo': fn foo(&A) -> &T - [329; 350) 'A::foo...42))))': &i32 - [336; 349) '&&B(B(A(42)))': &&B>> - [337; 349) '&B(B(A(42)))': &B>> - [338; 339) 'B': B>>(T) -> B - [338; 349) 'B(B(A(42)))': B>> - [340; 341) 'B': B>(T) -> B - [340; 348) 'B(A(42))': B> - [342; 343) 'A': A(T) -> A - [342; 347) 'A(42)': A - [344; 346) '42': i32 - "### - ); -} - -#[test] -fn infer_method_argument_autoderef() { - assert_snapshot!( - infer(r#" -#[lang = "deref"] -pub trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct A(*mut T); - -impl A { - fn foo(&self, x: &A) -> &T { - &*x.0 - } -} - -struct B(T); - -impl Deref for B { - type Target = T; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -fn test(a: A) { - let t = A(0 as *mut _).foo(&&B(B(a))); -} -"#), - @r###" - [68; 72) 'self': &Self - [144; 148) 'self': &A - [150; 151) 'x': &A - [166; 187) '{ ... }': &T - [176; 181) '&*x.0': &T - [177; 181) '*x.0': T - [178; 179) 'x': &A - [178; 181) 'x.0': *mut T - [268; 272) 'self': &B - [291; 314) '{ ... }': &T - [301; 308) '&self.0': &T - [302; 306) 'self': &B - [302; 308) 'self.0': T - [326; 327) 'a': A - [337; 383) '{ ...))); }': () - [347; 348) 't': &i32 - [351; 352) 'A': A(*mut T) -> A - [351; 365) 'A(0 as *mut _)': A - [351; 380) 'A(0 as...B(a)))': &i32 - [353; 354) '0': i32 - [353; 364) '0 as *mut _': *mut i32 - [370; 379) '&&B(B(a))': &&B>> - [371; 379) '&B(B(a))': &B>> - [372; 373) 'B': B>>(T) -> B - [372; 379) 'B(B(a))': B>> - [374; 375) 'B': B>(T) -> B - [374; 378) 'B(a)': B> - [376; 377) 'a': A - "### - ); -} - -#[test] -fn bug_484() { - assert_snapshot!( - infer(r#" -fn test() { - let x = if true {}; -} -"#), - @r###" - [11; 37) '{ l... {}; }': () - [20; 21) 'x': () - [24; 34) 'if true {}': () - [27; 31) 'true': bool - [32; 34) '{}': () - "### - ); -} - -#[test] -fn infer_in_elseif() { - assert_snapshot!( - infer(r#" -struct Foo { field: i32 } -fn main(foo: Foo) { - if true { - - } else if false { - foo.field - } -} -"#), - @r###" - [35; 38) 'foo': Foo - [45; 109) '{ ... } }': () - [51; 107) 'if tru... }': () - [54; 58) 'true': bool - [59; 67) '{ }': () - [73; 107) 'if fal... }': () - [76; 81) 'false': bool - [82; 107) '{ ... }': i32 - [92; 95) 'foo': Foo - [92; 101) 'foo.field': i32 - "### - ) -} - -#[test] -fn infer_if_match_with_return() { - assert_snapshot!( - infer(r#" -fn foo() { - let _x1 = if true { - 1 - } else { - return; - }; - let _x2 = if true { - 2 - } else { - return - }; - let _x3 = match true { - true => 3, - _ => { - return; - } - }; - let _x4 = match true { - true => 4, - _ => return - }; -}"#), - @r###" - [10; 323) '{ ... }; }': () - [20; 23) '_x1': i32 - [26; 80) 'if tru... }': i32 - [29; 33) 'true': bool - [34; 51) '{ ... }': i32 - [44; 45) '1': i32 - [57; 80) '{ ... }': ! - [67; 73) 'return': ! - [90; 93) '_x2': i32 - [96; 149) 'if tru... }': i32 - [99; 103) 'true': bool - [104; 121) '{ ... }': i32 - [114; 115) '2': i32 - [127; 149) '{ ... }': ! - [137; 143) 'return': ! - [159; 162) '_x3': i32 - [165; 247) 'match ... }': i32 - [171; 175) 'true': bool - [186; 190) 'true': bool - [194; 195) '3': i32 - [205; 206) '_': bool - [210; 241) '{ ... }': ! - [224; 230) 'return': ! - [257; 260) '_x4': i32 - [263; 320) 'match ... }': i32 - [269; 273) 'true': bool - [284; 288) 'true': bool - [292; 293) '4': i32 - [303; 304) '_': bool - [308; 314) 'return': ! - "### - ) -} - -#[test] -fn infer_inherent_method() { - assert_snapshot!( - infer(r#" -struct A; - -impl A { - fn foo(self, x: u32) -> i32 {} -} - -mod b { - impl super::A { - fn bar(&self, x: u64) -> i64 {} - } -} - -fn test(a: A) { - a.foo(1); - (&a).bar(1); - a.bar(1); -} -"#), - @r###" - [32; 36) 'self': A - [38; 39) 'x': u32 - [53; 55) '{}': () - [103; 107) 'self': &A - [109; 110) 'x': u64 - [124; 126) '{}': () - [144; 145) 'a': A - [150; 198) '{ ...(1); }': () - [156; 157) 'a': A - [156; 164) 'a.foo(1)': i32 - [162; 163) '1': u32 - [170; 181) '(&a).bar(1)': i64 - [171; 173) '&a': &A - [172; 173) 'a': A - [179; 180) '1': u64 - [187; 188) 'a': A - [187; 195) 'a.bar(1)': i64 - [193; 194) '1': u64 - "### - ); -} - -#[test] -fn infer_inherent_method_str() { - assert_snapshot!( - infer(r#" -#[lang = "str"] -impl str { - fn foo(&self) -> i32 {} -} - -fn test() { - "foo".foo(); -} -"#), - @r###" - [40; 44) 'self': &str - [53; 55) '{}': () - [69; 89) '{ ...o(); }': () - [75; 80) '"foo"': &str - [75; 86) '"foo".foo()': i32 - "### - ); -} - -#[test] -fn infer_tuple() { - assert_snapshot!( - infer(r#" -fn test(x: &str, y: isize) { - let a: (u32, &str) = (1, "a"); - let b = (a, x); - let c = (y, x); - let d = (c, x); - let e = (1, "e"); - let f = (e, "d"); -} -"#), - @r###" - [9; 10) 'x': &str - [18; 19) 'y': isize - [28; 170) '{ ...d"); }': () - [38; 39) 'a': (u32, &str) - [55; 63) '(1, "a")': (u32, &str) - [56; 57) '1': u32 - [59; 62) '"a"': &str - [73; 74) 'b': ((u32, &str), &str) - [77; 83) '(a, x)': ((u32, &str), &str) - [78; 79) 'a': (u32, &str) - [81; 82) 'x': &str - [93; 94) 'c': (isize, &str) - [97; 103) '(y, x)': (isize, &str) - [98; 99) 'y': isize - [101; 102) 'x': &str - [113; 114) 'd': ((isize, &str), &str) - [117; 123) '(c, x)': ((isize, &str), &str) - [118; 119) 'c': (isize, &str) - [121; 122) 'x': &str - [133; 134) 'e': (i32, &str) - [137; 145) '(1, "e")': (i32, &str) - [138; 139) '1': i32 - [141; 144) '"e"': &str - [155; 156) 'f': ((i32, &str), &str) - [159; 167) '(e, "d")': ((i32, &str), &str) - [160; 161) 'e': (i32, &str) - [163; 166) '"d"': &str - "### - ); -} - -#[test] -fn infer_array() { - assert_snapshot!( - infer(r#" -fn test(x: &str, y: isize) { - let a = [x]; - let b = [a, a]; - let c = [b, b]; - - let d = [y, 1, 2, 3]; - let d = [1, y, 2, 3]; - let e = [y]; - let f = [d, d]; - let g = [e, e]; - - let h = [1, 2]; - let i = ["a", "b"]; - - let b = [a, ["b"]]; - let x: [u8; 0] = []; -} -"#), - @r###" - [9; 10) 'x': &str - [18; 19) 'y': isize - [28; 293) '{ ... []; }': () - [38; 39) 'a': [&str;_] - [42; 45) '[x]': [&str;_] - [43; 44) 'x': &str - [55; 56) 'b': [[&str;_];_] - [59; 65) '[a, a]': [[&str;_];_] - [60; 61) 'a': [&str;_] - [63; 64) 'a': [&str;_] - [75; 76) 'c': [[[&str;_];_];_] - [79; 85) '[b, b]': [[[&str;_];_];_] - [80; 81) 'b': [[&str;_];_] - [83; 84) 'b': [[&str;_];_] - [96; 97) 'd': [isize;_] - [100; 112) '[y, 1, 2, 3]': [isize;_] - [101; 102) 'y': isize - [104; 105) '1': isize - [107; 108) '2': isize - [110; 111) '3': isize - [122; 123) 'd': [isize;_] - [126; 138) '[1, y, 2, 3]': [isize;_] - [127; 128) '1': isize - [130; 131) 'y': isize - [133; 134) '2': isize - [136; 137) '3': isize - [148; 149) 'e': [isize;_] - [152; 155) '[y]': [isize;_] - [153; 154) 'y': isize - [165; 166) 'f': [[isize;_];_] - [169; 175) '[d, d]': [[isize;_];_] - [170; 171) 'd': [isize;_] - [173; 174) 'd': [isize;_] - [185; 186) 'g': [[isize;_];_] - [189; 195) '[e, e]': [[isize;_];_] - [190; 191) 'e': [isize;_] - [193; 194) 'e': [isize;_] - [206; 207) 'h': [i32;_] - [210; 216) '[1, 2]': [i32;_] - [211; 212) '1': i32 - [214; 215) '2': i32 - [226; 227) 'i': [&str;_] - [230; 240) '["a", "b"]': [&str;_] - [231; 234) '"a"': &str - [236; 239) '"b"': &str - [251; 252) 'b': [[&str;_];_] - [255; 265) '[a, ["b"]]': [[&str;_];_] - [256; 257) 'a': [&str;_] - [259; 264) '["b"]': [&str;_] - [260; 263) '"b"': &str - [275; 276) 'x': [u8;_] - [288; 290) '[]': [u8;_] - "### - ); -} - -#[test] -fn infer_pattern() { - assert_snapshot!( - infer(r#" -fn test(x: &i32) { - let y = x; - let &z = x; - let a = z; - let (c, d) = (1, "hello"); - - for (e, f) in some_iter { - let g = e; - } - - if let [val] = opt { - let h = val; - } - - let lambda = |a: u64, b, c: i32| { a + b; c }; - - let ref ref_to_x = x; - let mut mut_x = x; - let ref mut mut_ref_to_x = x; - let k = mut_ref_to_x; -} -"#), - @r###" - [9; 10) 'x': &i32 - [18; 369) '{ ...o_x; }': () - [28; 29) 'y': &i32 - [32; 33) 'x': &i32 - [43; 45) '&z': &i32 - [44; 45) 'z': i32 - [48; 49) 'x': &i32 - [59; 60) 'a': i32 - [63; 64) 'z': i32 - [74; 80) '(c, d)': (i32, &str) - [75; 76) 'c': i32 - [78; 79) 'd': &str - [83; 95) '(1, "hello")': (i32, &str) - [84; 85) '1': i32 - [87; 94) '"hello"': &str - [102; 152) 'for (e... }': () - [106; 112) '(e, f)': ({unknown}, {unknown}) - [107; 108) 'e': {unknown} - [110; 111) 'f': {unknown} - [116; 125) 'some_iter': {unknown} - [126; 152) '{ ... }': () - [140; 141) 'g': {unknown} - [144; 145) 'e': {unknown} - [158; 205) 'if let... }': () - [165; 170) '[val]': {unknown} - [173; 176) 'opt': {unknown} - [177; 205) '{ ... }': () - [191; 192) 'h': {unknown} - [195; 198) 'val': {unknown} - [215; 221) 'lambda': |u64, u64, i32| -> i32 - [224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32 - [225; 226) 'a': u64 - [233; 234) 'b': u64 - [236; 237) 'c': i32 - [244; 256) '{ a + b; c }': i32 - [246; 247) 'a': u64 - [246; 251) 'a + b': u64 - [250; 251) 'b': u64 - [253; 254) 'c': i32 - [267; 279) 'ref ref_to_x': &&i32 - [282; 283) 'x': &i32 - [293; 302) 'mut mut_x': &i32 - [305; 306) 'x': &i32 - [316; 336) 'ref mu...f_to_x': &mut &i32 - [339; 340) 'x': &i32 - [350; 351) 'k': &mut &i32 - [354; 366) 'mut_ref_to_x': &mut &i32 - "### - ); -} - -#[test] -fn infer_pattern_match_ergonomics() { - assert_snapshot!( - infer(r#" -struct A(T); - -fn test() { - let A(n) = &A(1); - let A(n) = &mut A(1); -} -"#), - @r###" - [28; 79) '{ ...(1); }': () - [38; 42) 'A(n)': A - [40; 41) 'n': &i32 - [45; 50) '&A(1)': &A - [46; 47) 'A': A(T) -> A - [46; 50) 'A(1)': A - [48; 49) '1': i32 - [60; 64) 'A(n)': A - [62; 63) 'n': &mut i32 - [67; 76) '&mut A(1)': &mut A - [72; 73) 'A': A(T) -> A - [72; 76) 'A(1)': A - [74; 75) '1': i32 - "### - ); -} - -#[test] -fn infer_pattern_match_ergonomics_ref() { - covers!(match_ergonomics_ref); - assert_snapshot!( - infer(r#" -fn test() { - let v = &(1, &2); - let (_, &w) = v; -} -"#), - @r###" - [11; 57) '{ ...= v; }': () - [21; 22) 'v': &(i32, &i32) - [25; 33) '&(1, &2)': &(i32, &i32) - [26; 33) '(1, &2)': (i32, &i32) - [27; 28) '1': i32 - [30; 32) '&2': &i32 - [31; 32) '2': i32 - [43; 50) '(_, &w)': (i32, &i32) - [44; 45) '_': i32 - [47; 49) '&w': &i32 - [48; 49) 'w': i32 - [53; 54) 'v': &(i32, &i32) - "### - ); -} - -#[test] -fn infer_adt_pattern() { - assert_snapshot!( - infer(r#" -enum E { - A { x: usize }, - B -} - -struct S(u32, E); - -fn test() { - let e = E::A { x: 3 }; - - let S(y, z) = foo; - let E::A { x: new_var } = e; - - match e { - E::A { x } => x, - E::B if foo => 1, - E::B => 10, - }; - - let ref d @ E::A { .. } = e; - d; -} -"#), - @r###" - [68; 289) '{ ... d; }': () - [78; 79) 'e': E - [82; 95) 'E::A { x: 3 }': E - [92; 93) '3': usize - [106; 113) 'S(y, z)': S - [108; 109) 'y': u32 - [111; 112) 'z': E - [116; 119) 'foo': S - [129; 148) 'E::A {..._var }': E - [139; 146) 'new_var': usize - [151; 152) 'e': E - [159; 245) 'match ... }': usize - [165; 166) 'e': E - [177; 187) 'E::A { x }': E - [184; 185) 'x': usize - [191; 192) 'x': usize - [202; 206) 'E::B': E - [210; 213) 'foo': bool - [217; 218) '1': usize - [228; 232) 'E::B': E - [236; 238) '10': usize - [256; 275) 'ref d ...{ .. }': &E - [264; 275) 'E::A { .. }': E - [278; 279) 'e': E - [285; 286) 'd': &E - "### - ); -} - -#[test] -fn infer_struct_generics() { - assert_snapshot!( - infer(r#" -struct A { - x: T, -} - -fn test(a1: A, i: i32) { - a1.x; - let a2 = A { x: i }; - a2.x; - let a3 = A:: { x: 1 }; - a3.x; -} -"#), - @r###" - [36; 38) 'a1': A - [48; 49) 'i': i32 - [56; 147) '{ ...3.x; }': () - [62; 64) 'a1': A - [62; 66) 'a1.x': u32 - [76; 78) 'a2': A - [81; 91) 'A { x: i }': A - [88; 89) 'i': i32 - [97; 99) 'a2': A - [97; 101) 'a2.x': i32 - [111; 113) 'a3': A - [116; 134) 'A:: - [131; 132) '1': i128 - [140; 142) 'a3': A - [140; 144) 'a3.x': i128 - "### - ); -} - -#[test] -fn infer_tuple_struct_generics() { - assert_snapshot!( - infer(r#" -struct A(T); -enum Option { Some(T), None } -use Option::*; - -fn test() { - A(42); - A(42u128); - Some("x"); - Option::Some("x"); - None; - let x: Option = None; -} -"#), - @r###" - [76; 184) '{ ...one; }': () - [82; 83) 'A': A(T) -> A - [82; 87) 'A(42)': A - [84; 86) '42': i32 - [93; 94) 'A': A(T) -> A - [93; 102) 'A(42u128)': A - [95; 101) '42u128': u128 - [108; 112) 'Some': Some<&str>(T) -> Option - [108; 117) 'Some("x")': Option<&str> - [113; 116) '"x"': &str - [123; 135) 'Option::Some': Some<&str>(T) -> Option - [123; 140) 'Option...e("x")': Option<&str> - [136; 139) '"x"': &str - [146; 150) 'None': Option<{unknown}> - [160; 161) 'x': Option - [177; 181) 'None': Option - "### - ); -} - -#[test] -fn infer_generics_in_patterns() { - assert_snapshot!( - infer(r#" -struct A { - x: T, -} - -enum Option { - Some(T), - None, -} - -fn test(a1: A, o: Option) { - let A { x: x2 } = a1; - let A:: { x: x3 } = A { x: 1 }; - match o { - Option::Some(t) => t, - _ => 1, - }; -} -"#), - @r###" - [79; 81) 'a1': A - [91; 92) 'o': Option - [107; 244) '{ ... }; }': () - [117; 128) 'A { x: x2 }': A - [124; 126) 'x2': u32 - [131; 133) 'a1': A - [143; 161) 'A:: - [157; 159) 'x3': i64 - [164; 174) 'A { x: 1 }': A - [171; 172) '1': i64 - [180; 241) 'match ... }': u64 - [186; 187) 'o': Option - [198; 213) 'Option::Some(t)': Option - [211; 212) 't': u64 - [217; 218) 't': u64 - [228; 229) '_': Option - [233; 234) '1': u64 - "### - ); -} - -#[test] -fn infer_function_generics() { - assert_snapshot!( - infer(r#" -fn id(t: T) -> T { t } - -fn test() { - id(1u32); - id::(1); - let x: u64 = id(1); -} -"#), - @r###" - [10; 11) 't': T - [21; 26) '{ t }': T - [23; 24) 't': T - [38; 98) '{ ...(1); }': () - [44; 46) 'id': fn id(T) -> T - [44; 52) 'id(1u32)': u32 - [47; 51) '1u32': u32 - [58; 68) 'id::': fn id(T) -> T - [58; 71) 'id::(1)': i128 - [69; 70) '1': i128 - [81; 82) 'x': u64 - [90; 92) 'id': fn id(T) -> T - [90; 95) 'id(1)': u64 - [93; 94) '1': u64 - "### - ); -} - -#[test] -fn infer_impl_generics() { - assert_snapshot!( - infer(r#" -struct A { - x: T1, - y: T2, -} -impl A { - fn x(self) -> X { - self.x - } - fn y(self) -> Y { - self.y - } - fn z(self, t: T) -> (X, Y, T) { - (self.x, self.y, t) - } -} - -fn test() -> i128 { - let a = A { x: 1u64, y: 1i64 }; - a.x(); - a.y(); - a.z(1i128); - a.z::(1); -} -"#), - @r###" - [74; 78) 'self': A - [85; 107) '{ ... }': X - [95; 99) 'self': A - [95; 101) 'self.x': X - [117; 121) 'self': A - [128; 150) '{ ... }': Y - [138; 142) 'self': A - [138; 144) 'self.y': Y - [163; 167) 'self': A - [169; 170) 't': T - [188; 223) '{ ... }': (X, Y, T) - [198; 217) '(self.....y, t)': (X, Y, T) - [199; 203) 'self': A - [199; 205) 'self.x': X - [207; 211) 'self': A - [207; 213) 'self.y': Y - [215; 216) 't': T - [245; 342) '{ ...(1); }': () - [255; 256) 'a': A - [259; 281) 'A { x:...1i64 }': A - [266; 270) '1u64': u64 - [275; 279) '1i64': i64 - [287; 288) 'a': A - [287; 292) 'a.x()': u64 - [298; 299) 'a': A - [298; 303) 'a.y()': i64 - [309; 310) 'a': A - [309; 319) 'a.z(1i128)': (u64, i64, i128) - [313; 318) '1i128': i128 - [325; 326) 'a': A - [325; 339) 'a.z::(1)': (u64, i64, u128) - [337; 338) '1': u128 - "### - ); -} - -#[test] -fn infer_impl_generics_with_autoderef() { - assert_snapshot!( - infer(r#" -enum Option { - Some(T), - None, -} -impl Option { - fn as_ref(&self) -> Option<&T> {} -} -fn test(o: Option) { - (&o).as_ref(); - o.as_ref(); -} -"#), - @r###" - [78; 82) 'self': &Option - [98; 100) '{}': () - [111; 112) 'o': Option - [127; 165) '{ ...f(); }': () - [133; 146) '(&o).as_ref()': Option<&u32> - [134; 136) '&o': &Option - [135; 136) 'o': Option - [152; 153) 'o': Option - [152; 162) 'o.as_ref()': Option<&u32> - "### - ); -} - -#[test] -fn infer_generic_chain() { - assert_snapshot!( - infer(r#" -struct A { - x: T, -} -impl A { - fn x(self) -> T2 { - self.x - } -} -fn id(t: T) -> T { t } - -fn test() -> i128 { - let x = 1; - let y = id(x); - let a = A { x: id(y) }; - let z = id(a.x); - let b = A { x: z }; - b.x() -} -"#), - @r###" - [53; 57) 'self': A - [65; 87) '{ ... }': T2 - [75; 79) 'self': A - [75; 81) 'self.x': T2 - [99; 100) 't': T - [110; 115) '{ t }': T - [112; 113) 't': T - [135; 261) '{ ....x() }': i128 - [146; 147) 'x': i128 - [150; 151) '1': i128 - [162; 163) 'y': i128 - [166; 168) 'id': fn id(T) -> T - [166; 171) 'id(x)': i128 - [169; 170) 'x': i128 - [182; 183) 'a': A - [186; 200) 'A { x: id(y) }': A - [193; 195) 'id': fn id(T) -> T - [193; 198) 'id(y)': i128 - [196; 197) 'y': i128 - [211; 212) 'z': i128 - [215; 217) 'id': fn id(T) -> T - [215; 222) 'id(a.x)': i128 - [218; 219) 'a': A - [218; 221) 'a.x': i128 - [233; 234) 'b': A - [237; 247) 'A { x: z }': A - [244; 245) 'z': i128 - [254; 255) 'b': A - [254; 259) 'b.x()': i128 - "### - ); -} - -#[test] -fn infer_associated_const() { - assert_snapshot!( - infer(r#" -struct Struct; - -impl Struct { - const FOO: u32 = 1; -} - -enum Enum {} - -impl Enum { - const BAR: u32 = 2; -} - -trait Trait { - const ID: u32; -} - -struct TraitTest; - -impl Trait for TraitTest { - const ID: u32 = 5; -} - -fn test() { - let x = Struct::FOO; - let y = Enum::BAR; - let z = TraitTest::ID; -} -"#), - @r###" - [52; 53) '1': u32 - [105; 106) '2': u32 - [213; 214) '5': u32 - [229; 307) '{ ...:ID; }': () - [239; 240) 'x': u32 - [243; 254) 'Struct::FOO': u32 - [264; 265) 'y': u32 - [268; 277) 'Enum::BAR': u32 - [287; 288) 'z': u32 - [291; 304) 'TraitTest::ID': u32 - "### - ); -} - -#[test] -fn infer_associated_method_struct() { - assert_snapshot!( - infer(r#" -struct A { x: u32 } - -impl A { - fn new() -> A { - A { x: 0 } - } -} -fn test() { - let a = A::new(); - a.x; -} -"#), - @r###" - [49; 75) '{ ... }': A - [59; 69) 'A { x: 0 }': A - [66; 67) '0': u32 - [88; 122) '{ ...a.x; }': () - [98; 99) 'a': A - [102; 108) 'A::new': fn new() -> A - [102; 110) 'A::new()': A - [116; 117) 'a': A - [116; 119) 'a.x': u32 - "### - ); -} - -#[test] -fn infer_associated_method_enum() { - assert_snapshot!( - infer(r#" -enum A { B, C } - -impl A { - pub fn b() -> A { - A::B - } - pub fn c() -> A { - A::C - } -} -fn test() { - let a = A::b(); - a; - let c = A::c(); - c; -} -"#), - @r###" - [47; 67) '{ ... }': A - [57; 61) 'A::B': A - [88; 108) '{ ... }': A - [98; 102) 'A::C': A - [121; 178) '{ ... c; }': () - [131; 132) 'a': A - [135; 139) 'A::b': fn b() -> A - [135; 141) 'A::b()': A - [147; 148) 'a': A - [158; 159) 'c': A - [162; 166) 'A::c': fn c() -> A - [162; 168) 'A::c()': A - [174; 175) 'c': A - "### - ); -} - -#[test] -fn infer_associated_method_with_modules() { - assert_snapshot!( - infer(r#" -mod a { - struct A; - impl A { pub fn thing() -> A { A {} }} -} - -mod b { - struct B; - impl B { pub fn thing() -> u32 { 99 }} - - mod c { - struct C; - impl C { pub fn thing() -> C { C {} }} - } -} -use b::c; - -fn test() { - let x = a::A::thing(); - let y = b::B::thing(); - let z = c::C::thing(); -} -"#), - @r###" - [56; 64) '{ A {} }': A - [58; 62) 'A {}': A - [126; 132) '{ 99 }': u32 - [128; 130) '99': u32 - [202; 210) '{ C {} }': C - [204; 208) 'C {}': C - [241; 325) '{ ...g(); }': () - [251; 252) 'x': A - [255; 266) 'a::A::thing': fn thing() -> A - [255; 268) 'a::A::thing()': A - [278; 279) 'y': u32 - [282; 293) 'b::B::thing': fn thing() -> u32 - [282; 295) 'b::B::thing()': u32 - [305; 306) 'z': C - [309; 320) 'c::C::thing': fn thing() -> C - [309; 322) 'c::C::thing()': C - "### - ); -} - -#[test] -fn infer_associated_method_generics() { - assert_snapshot!( - infer(r#" -struct Gen { - val: T -} - -impl Gen { - pub fn make(val: T) -> Gen { - Gen { val } - } -} - -fn test() { - let a = Gen::make(0u32); -} -"#), - @r###" - [64; 67) 'val': T - [82; 109) '{ ... }': Gen - [92; 103) 'Gen { val }': Gen - [98; 101) 'val': T - [123; 155) '{ ...32); }': () - [133; 134) 'a': Gen - [137; 146) 'Gen::make': fn make(T) -> Gen - [137; 152) 'Gen::make(0u32)': Gen - [147; 151) '0u32': u32 - "### - ); -} - -#[test] -fn infer_associated_method_generics_with_default_param() { - assert_snapshot!( - infer(r#" -struct Gen { - val: T -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::make(); -} -"#), - @r###" - [80; 104) '{ ... }': Gen - [90; 98) 'loop { }': ! - [95; 98) '{ }': () - [118; 146) '{ ...e(); }': () - [128; 129) 'a': Gen - [132; 141) 'Gen::make': fn make() -> Gen - [132; 143) 'Gen::make()': Gen - "### - ); -} - -#[test] -fn infer_associated_method_generics_with_default_tuple_param() { - let t = type_at( - r#" -//- /main.rs -struct Gen { - val: T -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::make(); - a.val<|>; -} -"#, - ); - assert_eq!(t, "()"); -} - -#[test] -fn infer_associated_method_generics_without_args() { - assert_snapshot!( - infer(r#" -struct Gen { - val: T -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::::make(); -} -"#), - @r###" - [76; 100) '{ ... }': Gen - [86; 94) 'loop { }': ! - [91; 94) '{ }': () - [114; 149) '{ ...e(); }': () - [124; 125) 'a': Gen - [128; 144) 'Gen::<...::make': fn make() -> Gen - [128; 146) 'Gen::<...make()': Gen - "### - ); -} - -#[test] -fn infer_associated_method_generics_2_type_params_without_args() { - assert_snapshot!( - infer(r#" -struct Gen { - val: T, - val2: U, -} - -impl Gen { - pub fn make() -> Gen { - loop { } - } -} - -fn test() { - let a = Gen::::make(); -} -"#), - @r###" - [102; 126) '{ ... }': Gen - [112; 120) 'loop { }': ! - [117; 120) '{ }': () - [140; 180) '{ ...e(); }': () - [150; 151) 'a': Gen - [154; 175) 'Gen::<...::make': fn make() -> Gen - [154; 177) 'Gen::<...make()': Gen - "### - ); -} - -#[test] -fn infer_type_alias() { - assert_snapshot!( - infer(r#" -struct A { x: X, y: Y } -type Foo = A; -type Bar = A; -type Baz = A; -fn test(x: Foo, y: Bar<&str>, z: Baz) { - x.x; - x.y; - y.x; - y.y; - z.x; - z.y; -} -"#), - @r###" - [116; 117) 'x': A - [124; 125) 'y': A<&str, u128> - [138; 139) 'z': A - [154; 211) '{ ...z.y; }': () - [160; 161) 'x': A - [160; 163) 'x.x': u32 - [169; 170) 'x': A - [169; 172) 'x.y': i128 - [178; 179) 'y': A<&str, u128> - [178; 181) 'y.x': &str - [187; 188) 'y': A<&str, u128> - [187; 190) 'y.y': u128 - [196; 197) 'z': A - [196; 199) 'z.x': u8 - [205; 206) 'z': A - [205; 208) 'z.y': i8 - "### - ) -} - -#[test] -fn recursive_type_alias() { - assert_snapshot!( - infer(r#" -struct A {} -type Foo = Foo; -type Bar = A; -fn test(x: Foo) {} -"#), - @r###" - [59; 60) 'x': {unknown} - [67; 69) '{}': () - "### - ) -} - -#[test] -fn no_panic_on_field_of_enum() { - assert_snapshot!( - infer(r#" -enum X {} - -fn test(x: X) { - x.some_field; -} -"#), - @r###" - [20; 21) 'x': X - [26; 47) '{ ...eld; }': () - [32; 33) 'x': X - [32; 44) 'x.some_field': {unknown} - "### - ); -} - -#[test] -fn bug_585() { - assert_snapshot!( - infer(r#" -fn test() { - X {}; - match x { - A::B {} => (), - A::Y() => (), - } -} -"#), - @r###" - [11; 89) '{ ... } }': () - [17; 21) 'X {}': {unknown} - [27; 87) 'match ... }': () - [33; 34) 'x': {unknown} - [45; 52) 'A::B {}': {unknown} - [56; 58) '()': () - [68; 74) 'A::Y()': {unknown} - [78; 80) '()': () - "### - ); -} - -#[test] -fn bug_651() { - assert_snapshot!( - infer(r#" -fn quux() { - let y = 92; - 1 + y; -} -"#), - @r###" - [11; 41) '{ ...+ y; }': () - [21; 22) 'y': i32 - [25; 27) '92': i32 - [33; 34) '1': i32 - [33; 38) '1 + y': i32 - [37; 38) 'y': i32 - "### - ); -} - -#[test] -fn recursive_vars() { - covers!(type_var_cycles_resolve_completely); - covers!(type_var_cycles_resolve_as_possible); - assert_snapshot!( - infer(r#" -fn test() { - let y = unknown; - [y, &y]; -} -"#), - @r###" - [11; 48) '{ ...&y]; }': () - [21; 22) 'y': &{unknown} - [25; 32) 'unknown': &{unknown} - [38; 45) '[y, &y]': [&&{unknown};_] - [39; 40) 'y': &{unknown} - [42; 44) '&y': &&{unknown} - [43; 44) 'y': &{unknown} - "### - ); -} - -#[test] -fn recursive_vars_2() { - covers!(type_var_cycles_resolve_completely); - covers!(type_var_cycles_resolve_as_possible); - assert_snapshot!( - infer(r#" -fn test() { - let x = unknown; - let y = unknown; - [(x, y), (&y, &x)]; -} -"#), - @r###" - [11; 80) '{ ...x)]; }': () - [21; 22) 'x': &&{unknown} - [25; 32) 'unknown': &&{unknown} - [42; 43) 'y': &&{unknown} - [46; 53) 'unknown': &&{unknown} - [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_] - [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown}) - [61; 62) 'x': &&{unknown} - [64; 65) 'y': &&{unknown} - [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown}) - [69; 71) '&y': &&&{unknown} - [70; 71) 'y': &&{unknown} - [73; 75) '&x': &&&{unknown} - [74; 75) 'x': &&{unknown} - "### - ); -} - -#[test] -fn infer_type_param() { - assert_snapshot!( - infer(r#" -fn id(x: T) -> T { - x -} - -fn clone(x: &T) -> T { - *x -} - -fn test() { - let y = 10u32; - id(y); - let x: bool = clone(z); - id::(1); -} -"#), - @r###" - [10; 11) 'x': T - [21; 30) '{ x }': T - [27; 28) 'x': T - [44; 45) 'x': &T - [56; 66) '{ *x }': T - [62; 64) '*x': T - [63; 64) 'x': &T - [78; 158) '{ ...(1); }': () - [88; 89) 'y': u32 - [92; 97) '10u32': u32 - [103; 105) 'id': fn id(T) -> T - [103; 108) 'id(y)': u32 - [106; 107) 'y': u32 - [118; 119) 'x': bool - [128; 133) 'clone': fn clone(&T) -> T - [128; 136) 'clone(z)': bool - [134; 135) 'z': &bool - [142; 152) 'id::': fn id(T) -> T - [142; 155) 'id::(1)': i128 - [153; 154) '1': i128 - "### - ); -} - -#[test] -fn infer_std_crash_1() { - // caused stack overflow, taken from std - assert_snapshot!( - infer(r#" -enum Maybe { - Real(T), - Fake, -} - -fn write() { - match something_unknown { - Maybe::Real(ref mut something) => (), - } -} -"#), - @r###" - [54; 139) '{ ... } }': () - [60; 137) 'match ... }': () - [66; 83) 'someth...nknown': Maybe<{unknown}> - [94; 124) 'Maybe:...thing)': Maybe<{unknown}> - [106; 123) 'ref mu...ething': &mut {unknown} - [128; 130) '()': () - "### - ); -} - -#[test] -fn infer_std_crash_2() { - covers!(type_var_resolves_to_int_var); - // caused "equating two type variables, ...", taken from std - assert_snapshot!( - infer(r#" -fn test_line_buffer() { - &[0, b'\n', 1, b'\n']; -} -"#), - @r###" - [23; 53) '{ ...n']; }': () - [29; 50) '&[0, b...b'\n']': &[u8;_] - [30; 50) '[0, b'...b'\n']': [u8;_] - [31; 32) '0': u8 - [34; 39) 'b'\n'': u8 - [41; 42) '1': u8 - [44; 49) 'b'\n'': u8 - "### - ); -} - -#[test] -fn infer_std_crash_3() { - // taken from rustc - assert_snapshot!( - infer(r#" -pub fn compute() { - match nope!() { - SizeSkeleton::Pointer { non_zero: true, tail } => {} - } -} -"#), - @r###" - [18; 108) '{ ... } }': () - [24; 106) 'match ... }': () - [30; 37) 'nope!()': {unknown} - [48; 94) 'SizeSk...tail }': {unknown} - [82; 86) 'true': {unknown} - [88; 92) 'tail': {unknown} - [98; 100) '{}': () - "### - ); -} - -#[test] -fn infer_std_crash_4() { - // taken from rustc - assert_snapshot!( - infer(r#" -pub fn primitive_type() { - match *self { - BorrowedRef { type_: Primitive(p), ..} => {}, - } -} -"#), - @r###" - [25; 106) '{ ... } }': () - [31; 104) 'match ... }': () - [37; 42) '*self': {unknown} - [38; 42) 'self': {unknown} - [53; 91) 'Borrow...), ..}': {unknown} - [74; 86) 'Primitive(p)': {unknown} - [84; 85) 'p': {unknown} - [95; 97) '{}': () - "### - ); -} - -#[test] -fn infer_std_crash_5() { - // taken from rustc - assert_snapshot!( - infer(r#" -fn extra_compiler_flags() { - for content in doesnt_matter { - let name = if doesnt_matter { - first - } else { - &content - }; - - let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { - name - } else { - content - }; - } -} -"#), - @r###" - [27; 323) '{ ... } }': () - [33; 321) 'for co... }': () - [37; 44) 'content': &{unknown} - [48; 61) 'doesnt_matter': {unknown} - [62; 321) '{ ... }': () - [76; 80) 'name': &&{unknown} - [83; 167) 'if doe... }': &&{unknown} - [86; 99) 'doesnt_matter': bool - [100; 129) '{ ... }': &&{unknown} - [114; 119) 'first': &&{unknown} - [135; 167) '{ ... }': &&{unknown} - [149; 157) '&content': &&{unknown} - [150; 157) 'content': &{unknown} - [182; 189) 'content': &{unknown} - [192; 314) 'if ICE... }': &{unknown} - [195; 232) 'ICE_RE..._VALUE': {unknown} - [195; 248) 'ICE_RE...&name)': bool - [242; 247) '&name': &&&{unknown} - [243; 247) 'name': &&{unknown} - [249; 277) '{ ... }': &&{unknown} - [263; 267) 'name': &&{unknown} - [283; 314) '{ ... }': &{unknown} - [297; 304) 'content': &{unknown} - "### - ); -} - -#[test] -fn infer_nested_generics_crash() { - // another crash found typechecking rustc - assert_snapshot!( - infer(r#" -struct Canonical { - value: V, -} -struct QueryResponse { - value: V, -} -fn test(query_response: Canonical>) { - &query_response.value; -} -"#), - @r###" - [92; 106) 'query_response': Canonical> - [137; 167) '{ ...lue; }': () - [143; 164) '&query....value': &QueryResponse - [144; 158) 'query_response': Canonical> - [144; 164) 'query_....value': QueryResponse - "### - ); -} - -#[test] -fn bug_1030() { - assert_snapshot!(infer(r#" -struct HashSet; -struct FxHasher; -type FxHashSet = HashSet; - -impl HashSet { - fn default() -> HashSet {} -} - -pub fn main_loop() { - FxHashSet::default(); -} -"#), - @r###" - [144; 146) '{}': () - [169; 198) '{ ...t(); }': () - [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet - [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher> - "### - ); -} - -#[test] -fn cross_crate_associated_method_call() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:other_crate -fn test() { - let x = other_crate::foo::S::thing(); - x<|>; -} - -//- /lib.rs crate:other_crate -mod foo { - struct S; - impl S { - fn thing() -> i128 {} - } -} -"#, - ); - assert_eq!("i128", type_at_pos(&db, pos)); -} - -#[test] -fn infer_const() { - assert_snapshot!( - infer(r#" -struct Foo; -impl Foo { const ASSOC_CONST: u32 = 0; } -const GLOBAL_CONST: u32 = 101; -fn test() { - const LOCAL_CONST: u32 = 99; - let x = LOCAL_CONST; - let z = GLOBAL_CONST; - let id = Foo::ASSOC_CONST; -} -"#), - @r###" - [49; 50) '0': u32 - [80; 83) '101': u32 - [95; 213) '{ ...NST; }': () - [138; 139) 'x': {unknown} - [142; 153) 'LOCAL_CONST': {unknown} - [163; 164) 'z': u32 - [167; 179) 'GLOBAL_CONST': u32 - [189; 191) 'id': u32 - [194; 210) 'Foo::A..._CONST': u32 - "### - ); -} - -#[test] -fn infer_static() { - assert_snapshot!( - infer(r#" -static GLOBAL_STATIC: u32 = 101; -static mut GLOBAL_STATIC_MUT: u32 = 101; -fn test() { - static LOCAL_STATIC: u32 = 99; - static mut LOCAL_STATIC_MUT: u32 = 99; - let x = LOCAL_STATIC; - let y = LOCAL_STATIC_MUT; - let z = GLOBAL_STATIC; - let w = GLOBAL_STATIC_MUT; -} -"#), - @r###" - [29; 32) '101': u32 - [70; 73) '101': u32 - [85; 280) '{ ...MUT; }': () - [173; 174) 'x': {unknown} - [177; 189) 'LOCAL_STATIC': {unknown} - [199; 200) 'y': {unknown} - [203; 219) 'LOCAL_...IC_MUT': {unknown} - [229; 230) 'z': u32 - [233; 246) 'GLOBAL_STATIC': u32 - [256; 257) 'w': u32 - [260; 277) 'GLOBAL...IC_MUT': u32 - "### - ); -} - -#[test] -fn infer_trait_method_simple() { - // the trait implementation is intentionally incomplete -- it shouldn't matter - assert_snapshot!( - infer(r#" -trait Trait1 { - fn method(&self) -> u32; -} -struct S1; -impl Trait1 for S1 {} -trait Trait2 { - fn method(&self) -> i128; -} -struct S2; -impl Trait2 for S2 {} -fn test() { - S1.method(); // -> u32 - S2.method(); // -> i128 -} -"#), - @r###" - [31; 35) 'self': &Self - [110; 114) 'self': &Self - [170; 228) '{ ...i128 }': () - [176; 178) 'S1': S1 - [176; 187) 'S1.method()': u32 - [203; 205) 'S2': S2 - [203; 214) 'S2.method()': i128 - "### - ); -} - -#[test] -fn infer_trait_method_scoped() { - // the trait implementation is intentionally incomplete -- it shouldn't matter - assert_snapshot!( - infer(r#" -struct S; -mod foo { - pub trait Trait1 { - fn method(&self) -> u32; - } - impl Trait1 for super::S {} -} -mod bar { - pub trait Trait2 { - fn method(&self) -> i128; - } - impl Trait2 for super::S {} -} - -mod foo_test { - use super::S; - use super::foo::Trait1; - fn test() { - S.method(); // -> u32 - } -} - -mod bar_test { - use super::S; - use super::bar::Trait2; - fn test() { - S.method(); // -> i128 - } -} -"#), - @r###" - [63; 67) 'self': &Self - [169; 173) 'self': &Self - [300; 337) '{ ... }': () - [310; 311) 'S': S - [310; 320) 'S.method()': u32 - [416; 454) '{ ... }': () - [426; 427) 'S': S - [426; 436) 'S.method()': i128 - "### - ); -} - -#[test] -fn infer_trait_method_generic_1() { - // the trait implementation is intentionally incomplete -- it shouldn't matter - assert_snapshot!( - infer(r#" -trait Trait { - fn method(&self) -> T; -} -struct S; -impl Trait for S {} -fn test() { - S.method(); -} -"#), - @r###" - [33; 37) 'self': &Self - [92; 111) '{ ...d(); }': () - [98; 99) 'S': S - [98; 108) 'S.method()': u32 - "### - ); -} - -#[test] -fn infer_trait_method_generic_more_params() { - // the trait implementation is intentionally incomplete -- it shouldn't matter - assert_snapshot!( - infer(r#" -trait Trait { - fn method1(&self) -> (T1, T2, T3); - fn method2(&self) -> (T3, T2, T1); -} -struct S1; -impl Trait for S1 {} -struct S2; -impl Trait for S2 {} -fn test() { - S1.method1(); // u8, u16, u32 - S1.method2(); // u32, u16, u8 - S2.method1(); // i8, i16, {unknown} - S2.method2(); // {unknown}, i16, i8 -} -"#), - @r###" - [43; 47) 'self': &Self - [82; 86) 'self': &Self - [210; 361) '{ ..., i8 }': () - [216; 218) 'S1': S1 - [216; 228) 'S1.method1()': (u8, u16, u32) - [250; 252) 'S1': S1 - [250; 262) 'S1.method2()': (u32, u16, u8) - [284; 286) 'S2': S2 - [284; 296) 'S2.method1()': (i8, i16, {unknown}) - [324; 326) 'S2': S2 - [324; 336) 'S2.method2()': ({unknown}, i16, i8) - "### - ); -} - -#[test] -fn infer_trait_method_generic_2() { - // the trait implementation is intentionally incomplete -- it shouldn't matter - assert_snapshot!( - infer(r#" -trait Trait { - fn method(&self) -> T; -} -struct S(T); -impl Trait for S {} -fn test() { - S(1u32).method(); -} -"#), - @r###" - [33; 37) 'self': &Self - [102; 127) '{ ...d(); }': () - [108; 109) 'S': S(T) -> S - [108; 115) 'S(1u32)': S - [108; 124) 'S(1u32...thod()': u32 - [110; 114) '1u32': u32 - "### - ); -} - -#[test] -fn infer_trait_assoc_method() { - assert_snapshot!( - infer(r#" -trait Default { - fn default() -> Self; -} -struct S; -impl Default for S {} -fn test() { - let s1: S = Default::default(); - let s2 = S::default(); - let s3 = ::default(); -} -"#), - @r###" - [87; 193) '{ ...t(); }': () - [97; 99) 's1': S - [105; 121) 'Defaul...efault': fn default() -> Self - [105; 123) 'Defaul...ault()': S - [133; 135) 's2': S - [138; 148) 'S::default': fn default() -> Self - [138; 150) 'S::default()': S - [160; 162) 's3': S - [165; 188) '() -> Self - [165; 190) ' { - fn make() -> T; -} -struct S; -impl Trait for S {} -struct G; -impl Trait for G {} -fn test() { - let a = S::make(); - let b = G::::make(); - let c: f64 = G::make(); -} -"#), - @r###" - [127; 211) '{ ...e(); }': () - [137; 138) 'a': u32 - [141; 148) 'S::make': fn make() -> T - [141; 150) 'S::make()': u32 - [160; 161) 'b': u64 - [164; 178) 'G::::make': fn make, u64>() -> T - [164; 180) 'G::, f64>() -> T - [199; 208) 'G::make()': f64 - "### - ); -} - -#[test] -fn infer_trait_assoc_method_generics_2() { - assert_snapshot!( - infer(r#" -trait Trait { - fn make() -> (T, U); -} -struct S; -impl Trait for S {} -struct G; -impl Trait for G {} -fn test() { - let a = S::make::(); - let b: (_, i64) = S::make(); - let c = G::::make::(); - let d: (u32, _) = G::make::(); - let e: (u32, i64) = G::make(); -} -"#), - @r###" - [135; 313) '{ ...e(); }': () - [145; 146) 'a': (u32, i64) - [149; 163) 'S::make::': fn make() -> (T, U) - [149; 165) 'S::mak...i64>()': (u32, i64) - [175; 176) 'b': (u32, i64) - [189; 196) 'S::make': fn make() -> (T, U) - [189; 198) 'S::make()': (u32, i64) - [208; 209) 'c': (u32, i64) - [212; 233) 'G::': fn make, u32, i64>() -> (T, U) - [212; 235) 'G::()': (u32, i64) - [245; 246) 'd': (u32, i64) - [259; 273) 'G::make::': fn make, u32, i64>() -> (T, U) - [259; 275) 'G::mak...i64>()': (u32, i64) - [285; 286) 'e': (u32, i64) - [301; 308) 'G::make': fn make, u32, i64>() -> (T, U) - [301; 310) 'G::make()': (u32, i64) - "### - ); -} - -#[test] -fn infer_trait_assoc_method_generics_3() { - assert_snapshot!( - infer(r#" -trait Trait { - fn make() -> (Self, T); -} -struct S; -impl Trait for S {} -fn test() { - let a = S::make(); -} -"#), - @r###" - [101; 127) '{ ...e(); }': () - [111; 112) 'a': (S, i64) - [115; 122) 'S::make': fn make, i64>() -> (Self, T) - [115; 124) 'S::make()': (S, i64) - "### - ); -} - -#[test] -fn infer_trait_assoc_method_generics_4() { - assert_snapshot!( - infer(r#" -trait Trait { - fn make() -> (Self, T); -} -struct S; -impl Trait for S {} -impl Trait for S {} -fn test() { - let a: (S, _) = S::make(); - let b: (_, i32) = S::make(); -} -"#), - @r###" - [131; 203) '{ ...e(); }': () - [141; 142) 'a': (S, i64) - [158; 165) 'S::make': fn make, i64>() -> (Self, T) - [158; 167) 'S::make()': (S, i64) - [177; 178) 'b': (S, i32) - [191; 198) 'S::make': fn make, i32>() -> (Self, T) - [191; 200) 'S::make()': (S, i32) - "### - ); -} - -#[test] -fn infer_trait_assoc_method_generics_5() { - assert_snapshot!( - infer(r#" -trait Trait { - fn make() -> (Self, T, U); -} -struct S; -impl Trait for S {} -fn test() { - let a = >::make::(); - let b: (S, _, _) = Trait::::make::(); -} -"#), - @r###" - [107; 211) '{ ...>(); }': () - [117; 118) 'a': (S, i64, u8) - [121; 150) '': fn make, i64, u8>() -> (Self, T, U) - [121; 152) '()': (S, i64, u8) - [162; 163) 'b': (S, i64, u8) - [182; 206) 'Trait:...::': fn make, i64, u8>() -> (Self, T, U) - [182; 208) 'Trait:...()': (S, i64, u8) - "### - ); -} - -#[test] -fn infer_from_bound_1() { - assert_snapshot!( - infer(r#" -trait Trait {} -struct S(T); -impl Trait for S {} -fn foo>(t: T) {} -fn test() { - let s = S(unknown); - foo(s); -} -"#), - @r###" - [86; 87) 't': T - [92; 94) '{}': () - [105; 144) '{ ...(s); }': () - [115; 116) 's': S - [119; 120) 'S': S(T) -> S - [119; 129) 'S(unknown)': S - [121; 128) 'unknown': u32 - [135; 138) 'foo': fn foo>(T) -> () - [135; 141) 'foo(s)': () - [139; 140) 's': S - "### - ); -} - -#[test] -fn infer_from_bound_2() { - assert_snapshot!( - infer(r#" -trait Trait {} -struct S(T); -impl Trait for S {} -fn foo>(t: T) -> U {} -fn test() { - let s = S(unknown); - let x: u32 = foo(s); -} -"#), - @r###" - [87; 88) 't': T - [98; 100) '{}': () - [111; 163) '{ ...(s); }': () - [121; 122) 's': S - [125; 126) 'S': S(T) -> S - [125; 135) 'S(unknown)': S - [127; 134) 'unknown': u32 - [145; 146) 'x': u32 - [154; 157) 'foo': fn foo>(T) -> U - [154; 160) 'foo(s)': u32 - [158; 159) 's': S - "### - ); -} - -#[test] -fn infer_call_trait_method_on_generic_param_1() { - assert_snapshot!( - infer(r#" -trait Trait { - fn method(&self) -> u32; -} -fn test(t: T) { - t.method(); -} -"#), - @r###" - [30; 34) 'self': &Self - [64; 65) 't': T - [70; 89) '{ ...d(); }': () - [76; 77) 't': T - [76; 86) 't.method()': u32 - "### - ); -} - -#[test] -fn infer_call_trait_method_on_generic_param_2() { - assert_snapshot!( - infer(r#" -trait Trait { - fn method(&self) -> T; -} -fn test>(t: T) { - t.method(); -} -"#), - @r###" - [33; 37) 'self': &Self - [71; 72) 't': T - [77; 96) '{ ...d(); }': () - [83; 84) 't': T - [83; 93) 't.method()': [missing name] - "### - ); -} - -#[test] -fn infer_with_multiple_trait_impls() { - assert_snapshot!( - infer(r#" -trait Into { - fn into(self) -> T; -} -struct S; -impl Into for S {} -impl Into for S {} -fn test() { - let x: u32 = S.into(); - let y: u64 = S.into(); - let z = Into::::into(S); -} -"#), - @r###" - [29; 33) 'self': Self - [111; 202) '{ ...(S); }': () - [121; 122) 'x': u32 - [130; 131) 'S': S - [130; 138) 'S.into()': u32 - [148; 149) 'y': u64 - [157; 158) 'S': S - [157; 165) 'S.into()': u64 - [175; 176) 'z': u64 - [179; 196) 'Into::...::into': fn into(Self) -> T - [179; 199) 'Into::...nto(S)': u64 - [197; 198) 'S': S - "### - ); -} - -#[test] -fn infer_project_associated_type() { - // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234 - assert_snapshot!( - infer(r#" -trait Iterable { - type Item; -} -struct S; -impl Iterable for S { type Item = u32; } -fn test() { - let x: ::Item = 1; - let y: ::Item = no_matter; - let z: T::Item = no_matter; - let a: ::Item = no_matter; -} -"#), - @r###" - [108; 261) '{ ...ter; }': () - [118; 119) 'x': u32 - [145; 146) '1': u32 - [156; 157) 'y': {unknown} - [183; 192) 'no_matter': {unknown} - [202; 203) 'z': {unknown} - [215; 224) 'no_matter': {unknown} - [234; 235) 'a': {unknown} - [249; 258) 'no_matter': {unknown} - "### - ); -} - -#[test] -fn infer_return_associated_type() { - assert_snapshot!( - infer(r#" -trait Iterable { - type Item; -} -struct S; -impl Iterable for S { type Item = u32; } -fn foo1(t: T) -> T::Item {} -fn foo2(t: T) -> ::Item {} -fn foo3(t: T) -> ::Item {} -fn test() { - let x = foo1(S); - let y = foo2(S); - let z = foo3(S); -} -"#), - @r###" - [106; 107) 't': T - [123; 125) '{}': () - [147; 148) 't': T - [178; 180) '{}': () - [202; 203) 't': T - [221; 223) '{}': () - [234; 300) '{ ...(S); }': () - [244; 245) 'x': u32 - [248; 252) 'foo1': fn foo1(T) -> ::Item - [248; 255) 'foo1(S)': u32 - [253; 254) 'S': S - [265; 266) 'y': u32 - [269; 273) 'foo2': fn foo2(T) -> ::Item - [269; 276) 'foo2(S)': u32 - [274; 275) 'S': S - [286; 287) 'z': u32 - [290; 294) 'foo3': fn foo3(T) -> ::Item - [290; 297) 'foo3(S)': u32 - [295; 296) 'S': S - "### - ); -} - -#[test] -fn infer_associated_type_bound() { - assert_snapshot!( - infer(r#" -trait Iterable { - type Item; -} -fn test>() { - let y: T::Item = unknown; -} -"#), - @r###" - [67; 100) '{ ...own; }': () - [77; 78) 'y': {unknown} - [90; 97) 'unknown': {unknown} - "### - ); -} - -#[test] -fn infer_const_body() { - assert_snapshot!( - infer(r#" -const A: u32 = 1 + 1; -static B: u64 = { let x = 1; x }; -"#), - @r###" - [16; 17) '1': u32 - [16; 21) '1 + 1': u32 - [20; 21) '1': u32 - [39; 55) '{ let ...1; x }': u64 - [45; 46) 'x': u64 - [49; 50) '1': u64 - [52; 53) 'x': u64 - "### - ); -} - -#[test] -fn tuple_struct_fields() { - assert_snapshot!( - infer(r#" -struct S(i32, u64); -fn test() -> u64 { - let a = S(4, 6); - let b = a.0; - a.1 -} -"#), - @r###" - [38; 87) '{ ... a.1 }': u64 - [48; 49) 'a': S - [52; 53) 'S': S(i32, u64) -> S - [52; 59) 'S(4, 6)': S - [54; 55) '4': i32 - [57; 58) '6': u64 - [69; 70) 'b': i32 - [73; 74) 'a': S - [73; 76) 'a.0': i32 - [82; 83) 'a': S - [82; 85) 'a.1': u64 - "### - ); -} - -#[test] -fn tuple_struct_with_fn() { - assert_snapshot!( - infer(r#" -struct S(fn(u32) -> u64); -fn test() -> u64 { - let a = S(|i| 2*i); - let b = a.0(4); - a.0(2) -} -"#), - @r###" - [44; 102) '{ ...0(2) }': u64 - [54; 55) 'a': S - [58; 59) 'S': S(fn(u32) -> u64) -> S - [58; 68) 'S(|i| 2*i)': S - [60; 67) '|i| 2*i': |i32| -> i32 - [61; 62) 'i': i32 - [64; 65) '2': i32 - [64; 67) '2*i': i32 - [66; 67) 'i': i32 - [78; 79) 'b': u64 - [82; 83) 'a': S - [82; 85) 'a.0': fn(u32) -> u64 - [82; 88) 'a.0(4)': u64 - [86; 87) '4': u32 - [94; 95) 'a': S - [94; 97) 'a.0': fn(u32) -> u64 - [94; 100) 'a.0(2)': u64 - [98; 99) '2': u32 - "### - ); -} - -#[test] -fn indexing_arrays() { - assert_snapshot!( - infer("fn main() { &mut [9][2]; }"), - @r###" - [10; 26) '{ &mut...[2]; }': () - [12; 23) '&mut [9][2]': &mut {unknown} - [17; 20) '[9]': [i32;_] - [17; 23) '[9][2]': {unknown} - [18; 19) '9': i32 - [21; 22) '2': i32 - "### - ) -} - -#[test] -fn infer_macros_expanded() { - assert_snapshot!( - infer(r#" -struct Foo(Vec); - -macro_rules! foo { - ($($item:expr),*) => { - { - Foo(vec![$($item,)*]) - } - }; -} - -fn main() { - let x = foo!(1,2); -} -"#), - @r###" - ![0; 17) '{Foo(v...,2,])}': Foo - ![1; 4) 'Foo': Foo({unknown}) -> Foo - ![1; 16) 'Foo(vec![1,2,])': Foo - ![5; 15) 'vec![1,2,]': {unknown} - [156; 182) '{ ...,2); }': () - [166; 167) 'x': Foo - "### - ); -} - -#[test] -fn infer_legacy_textual_scoped_macros_expanded() { - assert_snapshot!( - infer(r#" -struct Foo(Vec); - -#[macro_use] -mod m { - macro_rules! foo { - ($($item:expr),*) => { - { - Foo(vec![$($item,)*]) - } - }; - } -} - -fn main() { - let x = foo!(1,2); - let y = crate::foo!(1,2); -} -"#), - @r###" - ![0; 17) '{Foo(v...,2,])}': Foo - ![1; 4) 'Foo': Foo({unknown}) -> Foo - ![1; 16) 'Foo(vec![1,2,])': Foo - ![5; 15) 'vec![1,2,]': {unknown} - [195; 251) '{ ...,2); }': () - [205; 206) 'x': Foo - [228; 229) 'y': {unknown} - [232; 248) 'crate:...!(1,2)': {unknown} - "### - ); -} - -#[test] -fn infer_path_qualified_macros_expanded() { - assert_snapshot!( - infer(r#" -#[macro_export] -macro_rules! foo { - () => { 42i32 } -} - -mod m { - pub use super::foo as bar; -} - -fn main() { - let x = crate::foo!(); - let y = m::bar!(); -} -"#), - @r###" - ![0; 5) '42i32': i32 - ![0; 5) '42i32': i32 - [111; 164) '{ ...!(); }': () - [121; 122) 'x': i32 - [148; 149) 'y': i32 - "### - ); -} - -#[test] -fn infer_type_value_macro_having_same_name() { - assert_snapshot!( - infer(r#" -#[macro_export] -macro_rules! foo { - () => { - mod foo { - pub use super::foo; - } - }; - ($x:tt) => { - $x - }; -} - -foo!(); - -fn foo() { - let foo = foo::foo!(42i32); -} -"#), - @r###" - ![0; 5) '42i32': i32 - [171; 206) '{ ...32); }': () - [181; 184) 'foo': i32 - "### - ); -} - -#[test] -fn processes_impls_generated_by_macros() { - let t = type_at( - r#" -//- /main.rs -macro_rules! m { - ($ident:ident) => (impl Trait for $ident {}) -} -trait Trait { fn foo(self) -> u128 {} } -struct S; -m!(S); -fn test() { S.foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn infer_macro_with_dollar_crate_is_correct_in_expr() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:foo -fn test() { - let x = (foo::foo!(1), foo::foo!(2)); - x<|>; -} - -//- /lib.rs crate:foo -#[macro_export] -macro_rules! foo { - (1) => { $crate::bar!() }; - (2) => { 1 + $crate::baz() }; -} - -#[macro_export] -macro_rules! bar { - () => { 42 } -} - -pub fn baz() -> usize { 31usize } -"#, - ); - assert_eq!("(i32, usize)", type_at_pos(&db, pos)); -} - -#[test] -fn method_resolution_unify_impl_self_type() { - let t = type_at( - r#" -//- /main.rs -struct S; -impl S { fn foo(&self) -> u8 {} } -impl S { fn foo(&self) -> i8 {} } -fn test() { (S::.foo(), S::.foo())<|>; } -"#, - ); - assert_eq!(t, "(u8, i8)"); -} - -#[test] -fn method_resolution_trait_before_autoref() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl S { fn foo(&self) -> i8 { 0 } } -impl Trait for S { fn foo(self) -> u128 { 0 } } -fn test() { S.foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn method_resolution_by_value_before_autoref() { - let t = type_at( - r#" -//- /main.rs -trait Clone { fn clone(&self) -> Self; } -struct S; -impl Clone for S {} -impl Clone for &S {} -fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; } -"#, - ); - assert_eq!(t, "(S, S, &S)"); -} - -#[test] -fn method_resolution_trait_before_autoderef() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl S { fn foo(self) -> i8 { 0 } } -impl Trait for &S { fn foo(self) -> u128 { 0 } } -fn test() { (&S).foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn method_resolution_impl_before_trait() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl S { fn foo(self) -> i8 { 0 } } -impl Trait for S { fn foo(self) -> u128 { 0 } } -fn test() { S.foo()<|>; } -"#, - ); - assert_eq!(t, "i8"); -} - -#[test] -fn method_resolution_impl_ref_before_trait() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl S { fn foo(&self) -> i8 { 0 } } -impl Trait for &S { fn foo(self) -> u128 { 0 } } -fn test() { S.foo()<|>; } -"#, - ); - assert_eq!(t, "i8"); -} - -#[test] -fn method_resolution_trait_autoderef() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for S { fn foo(self) -> u128 { 0 } } -fn test() { (&S).foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn method_resolution_trait_from_prelude() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:other_crate -struct S; -impl Clone for S {} - -fn test() { - S.clone()<|>; -} - -//- /lib.rs crate:other_crate -#[prelude_import] use foo::*; - -mod foo { - trait Clone { - fn clone(&self) -> Self; - } -} -"#, - ); - assert_eq!("S", type_at_pos(&db, pos)); -} - -#[test] -fn method_resolution_where_clause_for_unknown_trait() { - // The blanket impl shouldn't apply because we can't even resolve UnknownTrait - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for T where T: UnknownTrait {} -fn test() { (&S).foo()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn method_resolution_where_clause_not_met() { - // The blanket impl shouldn't apply because we can't prove S: Clone - let t = type_at( - r#" -//- /main.rs -trait Clone {} -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for T where T: Clone {} -fn test() { (&S).foo()<|>; } -"#, - ); - // This is also to make sure that we don't resolve to the foo method just - // because that's the only method named foo we can find, which would make - // the below tests not work - assert_eq!(t, "{unknown}"); -} - -#[test] -fn method_resolution_where_clause_inline_not_met() { - // The blanket impl shouldn't apply because we can't prove S: Clone - let t = type_at( - r#" -//- /main.rs -trait Clone {} -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for T {} -fn test() { (&S).foo()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn method_resolution_where_clause_1() { - let t = type_at( - r#" -//- /main.rs -trait Clone {} -trait Trait { fn foo(self) -> u128; } -struct S; -impl Clone for S {} -impl Trait for T where T: Clone {} -fn test() { S.foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn method_resolution_where_clause_2() { - let t = type_at( - r#" -//- /main.rs -trait Into { fn into(self) -> T; } -trait From { fn from(other: T) -> Self; } -struct S1; -struct S2; -impl From for S1 {} -impl Into for T where U: From {} -fn test() { S2.into()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn method_resolution_where_clause_inline() { - let t = type_at( - r#" -//- /main.rs -trait Into { fn into(self) -> T; } -trait From { fn from(other: T) -> Self; } -struct S1; -struct S2; -impl From for S1 {} -impl> Into for T {} -fn test() { S2.into()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn method_resolution_encountering_fn_type() { - type_at( - r#" -//- /main.rs -fn foo() {} -trait FnOnce { fn call(self); } -fn test() { foo.call()<|>; } -"#, - ); -} - -#[test] -fn method_resolution_slow() { - // this can get quite slow if we set the solver size limit too high - let t = type_at( - r#" -//- /main.rs -trait SendX {} - -struct S1; impl SendX for S1 {} -struct S2; impl SendX for S2 {} -struct U1; - -trait Trait { fn method(self); } - -struct X1 {} -impl SendX for X1 where A: SendX, B: SendX {} - -struct S {} - -trait FnX {} - -impl Trait for S where C: FnX, B: SendX {} - -fn test() { (S {}).method()<|>; } -"#, - ); - assert_eq!(t, "()"); -} - -#[test] -fn shadowing_primitive() { - let t = type_at( - r#" -//- /main.rs -struct i32; -struct Foo; - -impl i32 { fn foo(&self) -> Foo { Foo } } - -fn main() { - let x: i32 = i32; - x.foo()<|>; -}"#, - ); - assert_eq!(t, "Foo"); -} - -#[test] -fn not_shadowing_primitive_by_module() { - let t = type_at( - r#" -//- /str.rs -fn foo() {} - -//- /main.rs -mod str; -fn foo() -> &'static str { "" } - -fn main() { - foo()<|>; -}"#, - ); - assert_eq!(t, "&str"); -} - -#[test] -fn not_shadowing_module_by_primitive() { - let t = type_at( - r#" -//- /str.rs -fn foo() -> u32 {0} - -//- /main.rs -mod str; -fn foo() -> &'static str { "" } - -fn main() { - str::foo()<|>; -}"#, - ); - assert_eq!(t, "u32"); -} - -#[test] -fn deref_trait() { - let t = type_at( - r#" -//- /main.rs -#[lang = "deref"] -trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct Arc; -impl Deref for Arc { - type Target = T; -} - -struct S; -impl S { - fn foo(&self) -> u128 {} -} - -fn test(s: Arc) { - (*s, s.foo())<|>; -} -"#, - ); - assert_eq!(t, "(S, u128)"); -} - -#[test] -fn deref_trait_with_inference_var() { - let t = type_at( - r#" -//- /main.rs -#[lang = "deref"] -trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct Arc; -fn new_arc() -> Arc {} -impl Deref for Arc { - type Target = T; -} - -struct S; -fn foo(a: Arc) {} - -fn test() { - let a = new_arc(); - let b = (*a)<|>; - foo(a); -} -"#, - ); - assert_eq!(t, "S"); -} - -#[test] -fn deref_trait_infinite_recursion() { - let t = type_at( - r#" -//- /main.rs -#[lang = "deref"] -trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct S; - -impl Deref for S { - type Target = S; -} - -fn test(s: S) { - s.foo()<|>; -} -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn deref_trait_with_question_mark_size() { - let t = type_at( - r#" -//- /main.rs -#[lang = "deref"] -trait Deref { - type Target; - fn deref(&self) -> &Self::Target; -} - -struct Arc; -impl Deref for Arc { - type Target = T; -} - -struct S; -impl S { - fn foo(&self) -> u128 {} -} - -fn test(s: Arc) { - (*s, s.foo())<|>; -} -"#, - ); - assert_eq!(t, "(S, u128)"); -} - -#[test] -fn obligation_from_function_clause() { - let t = type_at( - r#" -//- /main.rs -struct S; - -trait Trait {} -impl Trait for S {} - -fn foo, U>(t: T) -> U {} - -fn test(s: S) { - foo(s)<|>; -} -"#, - ); - assert_eq!(t, "u32"); -} - -#[test] -fn obligation_from_method_clause() { - let t = type_at( - r#" -//- /main.rs -struct S; - -trait Trait {} -impl Trait for S {} - -struct O; -impl O { - fn foo, U>(&self, t: T) -> U {} -} - -fn test() { - O.foo(S)<|>; -} -"#, - ); - assert_eq!(t, "isize"); -} - -#[test] -fn obligation_from_self_method_clause() { - let t = type_at( - r#" -//- /main.rs -struct S; - -trait Trait {} -impl Trait for S {} - -impl S { - fn foo(&self) -> U where Self: Trait {} -} - -fn test() { - S.foo()<|>; -} -"#, - ); - assert_eq!(t, "i64"); -} - -#[test] -fn obligation_from_impl_clause() { - let t = type_at( - r#" -//- /main.rs -struct S; - -trait Trait {} -impl Trait<&str> for S {} - -struct O; -impl> O { - fn foo(&self) -> U {} -} - -fn test(o: O) { - o.foo()<|>; -} -"#, - ); - assert_eq!(t, "&str"); -} - -#[test] -fn generic_param_env_1() { - let t = type_at( - r#" -//- /main.rs -trait Clone {} -trait Trait { fn foo(self) -> u128; } -struct S; -impl Clone for S {} -impl Trait for T where T: Clone {} -fn test(t: T) { t.foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn generic_param_env_1_not_met() { - let t = type_at( - r#" -//- /main.rs -trait Clone {} -trait Trait { fn foo(self) -> u128; } -struct S; -impl Clone for S {} -impl Trait for T where T: Clone {} -fn test(t: T) { t.foo()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn generic_param_env_2() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for S {} -fn test(t: T) { t.foo()<|>; } -"#, - ); - assert_eq!(t, "u128"); -} - -#[test] -fn generic_param_env_2_not_met() { - let t = type_at( - r#" -//- /main.rs -trait Trait { fn foo(self) -> u128; } -struct S; -impl Trait for S {} -fn test(t: T) { t.foo()<|>; } -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn generic_param_env_deref() { - let t = type_at( - r#" -//- /main.rs -#[lang = "deref"] -trait Deref { - type Target; -} -trait Trait {} -impl Deref for T where T: Trait { - type Target = i128; -} -fn test(t: T) { (*t)<|>; } -"#, - ); - assert_eq!(t, "i128"); -} - -#[test] -fn associated_type_placeholder() { - let t = type_at( - r#" -//- /main.rs -pub trait ApplyL { - type Out; -} - -pub struct RefMutL; - -impl ApplyL for RefMutL { - type Out = ::Out; -} - -fn test() { - let y: as ApplyL>::Out = no_matter; - y<|>; -} -"#, - ); - // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. - // FIXME: fix type parameter names going missing when going through Chalk - assert_eq!(t, "ApplyL::Out<[missing name]>"); -} - -#[test] -fn associated_type_placeholder_2() { - let t = type_at( - r#" -//- /main.rs -pub trait ApplyL { - type Out; -} -fn foo(t: T) -> ::Out; - -fn test(t: T) { - let y = foo(t); - y<|>; -} -"#, - ); - // FIXME here Chalk doesn't normalize the type to a placeholder. I think we - // need to add a rule like Normalize(::Out -> ApplyL::Out) - // to the trait env ourselves here; probably Chalk can't do this by itself. - // assert_eq!(t, "ApplyL::Out<[missing name]>"); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn impl_trait() { - assert_snapshot!( - infer(r#" -trait Trait { - fn foo(&self) -> T; - fn foo2(&self) -> i64; -} -fn bar() -> impl Trait {} - -fn test(x: impl Trait, y: &impl Trait) { - x; - y; - let z = bar(); - x.foo(); - y.foo(); - z.foo(); - x.foo2(); - y.foo2(); - z.foo2(); -} -"#), - @r###" - [30; 34) 'self': &Self - [55; 59) 'self': &Self - [99; 101) '{}': () - [111; 112) 'x': impl Trait - [131; 132) 'y': &impl Trait - [152; 269) '{ ...2(); }': () - [158; 159) 'x': impl Trait - [165; 166) 'y': &impl Trait - [176; 177) 'z': impl Trait - [180; 183) 'bar': fn bar() -> impl Trait - [180; 185) 'bar()': impl Trait - [191; 192) 'x': impl Trait - [191; 198) 'x.foo()': u64 - [204; 205) 'y': &impl Trait - [204; 211) 'y.foo()': u64 - [217; 218) 'z': impl Trait - [217; 224) 'z.foo()': u64 - [230; 231) 'x': impl Trait - [230; 238) 'x.foo2()': i64 - [244; 245) 'y': &impl Trait - [244; 252) 'y.foo2()': i64 - [258; 259) 'z': impl Trait - [258; 266) 'z.foo2()': i64 - "### - ); -} - -#[test] -fn dyn_trait() { - assert_snapshot!( - infer(r#" -trait Trait { - fn foo(&self) -> T; - fn foo2(&self) -> i64; -} -fn bar() -> dyn Trait {} - -fn test(x: dyn Trait, y: &dyn Trait) { - x; - y; - let z = bar(); - x.foo(); - y.foo(); - z.foo(); - x.foo2(); - y.foo2(); - z.foo2(); -} -"#), - @r###" - [30; 34) 'self': &Self - [55; 59) 'self': &Self - [98; 100) '{}': () - [110; 111) 'x': dyn Trait - [129; 130) 'y': &dyn Trait - [149; 266) '{ ...2(); }': () - [155; 156) 'x': dyn Trait - [162; 163) 'y': &dyn Trait - [173; 174) 'z': dyn Trait - [177; 180) 'bar': fn bar() -> dyn Trait - [177; 182) 'bar()': dyn Trait - [188; 189) 'x': dyn Trait - [188; 195) 'x.foo()': u64 - [201; 202) 'y': &dyn Trait - [201; 208) 'y.foo()': u64 - [214; 215) 'z': dyn Trait - [214; 221) 'z.foo()': u64 - [227; 228) 'x': dyn Trait - [227; 235) 'x.foo2()': i64 - [241; 242) 'y': &dyn Trait - [241; 249) 'y.foo2()': i64 - [255; 256) 'z': dyn Trait - [255; 263) 'z.foo2()': i64 - "### - ); -} - -#[test] -fn dyn_trait_bare() { - assert_snapshot!( - infer(r#" -trait Trait { - fn foo(&self) -> u64; -} -fn bar() -> Trait {} - -fn test(x: Trait, y: &Trait) -> u64 { - x; - y; - let z = bar(); - x.foo(); - y.foo(); - z.foo(); -} -"#), - @r###" - [27; 31) 'self': &Self - [61; 63) '{}': () - [73; 74) 'x': dyn Trait - [83; 84) 'y': &dyn Trait - [101; 176) '{ ...o(); }': () - [107; 108) 'x': dyn Trait - [114; 115) 'y': &dyn Trait - [125; 126) 'z': dyn Trait - [129; 132) 'bar': fn bar() -> dyn Trait - [129; 134) 'bar()': dyn Trait - [140; 141) 'x': dyn Trait - [140; 147) 'x.foo()': u64 - [153; 154) 'y': &dyn Trait - [153; 160) 'y.foo()': u64 - [166; 167) 'z': dyn Trait - [166; 173) 'z.foo()': u64 - "### - ); -} - -#[test] -fn weird_bounds() { - assert_snapshot!( - infer(r#" -trait Trait {} -fn test() { - let a: impl Trait + 'lifetime = foo; - let b: impl 'lifetime = foo; - let b: impl (Trait) = foo; - let b: impl ('lifetime) = foo; - let d: impl ?Sized = foo; - let e: impl Trait + ?Sized = foo; -} -"#), - @r###" - [26; 237) '{ ...foo; }': () - [36; 37) 'a': impl Trait + {error} - [64; 67) 'foo': impl Trait + {error} - [77; 78) 'b': impl {error} - [97; 100) 'foo': impl {error} - [110; 111) 'b': impl Trait - [128; 131) 'foo': impl Trait - [141; 142) 'b': impl {error} - [163; 166) 'foo': impl {error} - [176; 177) 'd': impl {error} - [193; 196) 'foo': impl {error} - [206; 207) 'e': impl Trait + {error} - [231; 234) 'foo': impl Trait + {error} - "### - ); -} - -#[test] -fn assoc_type_bindings() { - assert_snapshot!( - infer(r#" -trait Trait { - type Type; -} - -fn get(t: T) -> ::Type {} -fn get2>(t: T) -> U {} -fn set>(t: T) -> T {t} - -struct S; -impl Trait for S { type Type = T; } - -fn test>(x: T, y: impl Trait) { - get(x); - get2(x); - get(y); - get2(y); - get(set(S)); - get2(set(S)); - get2(S::); -} -"#), - @r###" - [50; 51) 't': T - [78; 80) '{}': () - [112; 113) 't': T - [123; 125) '{}': () - [155; 156) 't': T - [166; 169) '{t}': T - [167; 168) 't': T - [257; 258) 'x': T - [263; 264) 'y': impl Trait - [290; 398) '{ ...r>); }': () - [296; 299) 'get': fn get(T) -> ::Type - [296; 302) 'get(x)': {unknown} - [300; 301) 'x': T - [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U - [308; 315) 'get2(x)': {unknown} - [313; 314) 'x': T - [321; 324) 'get': fn get>(T) -> ::Type - [321; 327) 'get(y)': {unknown} - [325; 326) 'y': impl Trait - [333; 337) 'get2': fn get2<{unknown}, impl Trait>(T) -> U - [333; 340) 'get2(y)': {unknown} - [338; 339) 'y': impl Trait - [346; 349) 'get': fn get>(T) -> ::Type - [346; 357) 'get(set(S))': u64 - [350; 353) 'set': fn set>(T) -> T - [350; 356) 'set(S)': S - [354; 355) 'S': S - [363; 367) 'get2': fn get2>(T) -> U - [363; 375) 'get2(set(S))': u64 - [368; 371) 'set': fn set>(T) -> T - [368; 374) 'set(S)': S - [372; 373) 'S': S - [381; 385) 'get2': fn get2>(T) -> U - [381; 395) 'get2(S::)': str - [386; 394) 'S::': S - "### - ); -} - -#[test] -fn impl_trait_assoc_binding_projection_bug() { - let (db, pos) = TestDB::with_position( - r#" -//- /main.rs crate:main deps:std -pub trait Language { - type Kind; -} -pub enum RustLanguage {} -impl Language for RustLanguage { - type Kind = SyntaxKind; -} -struct SyntaxNode {} -fn foo() -> impl Iterator> {} - -trait Clone { - fn clone(&self) -> Self; -} - -fn api_walkthrough() { - for node in foo() { - node.clone()<|>; - } -} - -//- /std.rs crate:std -#[prelude_import] use iter::*; -mod iter { - trait IntoIterator { - type Item; - } - trait Iterator { - type Item; - } - impl IntoIterator for T { - type Item = ::Item; - } -} -"#, - ); - assert_eq!("{unknown}", type_at_pos(&db, pos)); -} - -#[test] -fn projection_eq_within_chalk() { - // std::env::set_var("CHALK_DEBUG", "1"); - assert_snapshot!( - infer(r#" -trait Trait1 { - type Type; -} -trait Trait2 { - fn foo(self) -> T; -} -impl Trait2 for U where U: Trait1 {} - -fn test>(x: T) { - x.foo(); -} -"#), - @r###" - [62; 66) 'self': Self - [164; 165) 'x': T - [170; 186) '{ ...o(); }': () - [176; 177) 'x': T - [176; 183) 'x.foo()': {unknown} - "### - ); -} - -#[test] -fn where_clause_trait_in_scope_for_method_resolution() { - let t = type_at( - r#" -//- /main.rs -mod foo { - trait Trait { - fn foo(&self) -> u32 {} - } -} - -fn test(x: T) { - x.foo()<|>; -} -"#, - ); - assert_eq!(t, "u32"); -} - -#[test] -fn super_trait_method_resolution() { - assert_snapshot!( - infer(r#" -mod foo { - trait SuperTrait { - fn foo(&self) -> u32 {} - } -} -trait Trait1: foo::SuperTrait {} -trait Trait2 where Self: foo::SuperTrait {} - -fn test(x: T, y: U) { - x.foo(); - y.foo(); -} -"#), - @r###" - [50; 54) 'self': &Self - [63; 65) '{}': () - [182; 183) 'x': T - [188; 189) 'y': U - [194; 223) '{ ...o(); }': () - [200; 201) 'x': T - [200; 207) 'x.foo()': u32 - [213; 214) 'y': U - [213; 220) 'y.foo()': u32 - "### - ); -} - -#[test] -fn super_trait_cycle() { - // This just needs to not crash - assert_snapshot!( - infer(r#" -trait A: B {} -trait B: A {} - -fn test(x: T) { - x.foo(); -} -"#), - @r###" - [44; 45) 'x': T - [50; 66) '{ ...o(); }': () - [56; 57) 'x': T - [56; 63) 'x.foo()': {unknown} - "### - ); -} - -#[test] -fn super_trait_assoc_type_bounds() { - assert_snapshot!( - infer(r#" -trait SuperTrait { type Type; } -trait Trait where Self: SuperTrait {} - -fn get2>(t: T) -> U {} -fn set>(t: T) -> T {t} - -struct S; -impl SuperTrait for S { type Type = T; } -impl Trait for S {} - -fn test() { - get2(set(S)); -} -"#), - @r###" - [103; 104) 't': T - [114; 116) '{}': () - [146; 147) 't': T - [157; 160) '{t}': T - [158; 159) 't': T - [259; 280) '{ ...S)); }': () - [265; 269) 'get2': fn get2>(T) -> U - [265; 277) 'get2(set(S))': u64 - [270; 273) 'set': fn set>(T) -> T - [270; 276) 'set(S)': S - [274; 275) 'S': S - "### - ); -} - -#[test] -fn fn_trait() { - assert_snapshot!( - infer(r#" -trait FnOnce { - type Output; - - fn call_once(self, args: Args) -> >::Output; -} - -fn test u128>(f: F) { - f.call_once((1, 2)); -} -"#), - @r###" - [57; 61) 'self': Self - [63; 67) 'args': Args - [150; 151) 'f': F - [156; 184) '{ ...2)); }': () - [162; 163) 'f': F - [162; 181) 'f.call...1, 2))': {unknown} - [174; 180) '(1, 2)': (u32, u64) - [175; 176) '1': u32 - [178; 179) '2': u64 - "### - ); -} - -#[test] -fn closure_1() { - assert_snapshot!( - infer(r#" -#[lang = "fn_once"] -trait FnOnce { - type Output; -} - -enum Option { Some(T), None } -impl Option { - fn map U>(self, f: F) -> Option {} -} - -fn test() { - let x = Option::Some(1u32); - x.map(|v| v + 1); - x.map(|_v| 1u64); - let y: Option = x.map(|_v| 1); -} -"#), - @r###" - [148; 152) 'self': Option - [154; 155) 'f': F - [173; 175) '{}': () - [189; 308) '{ ... 1); }': () - [199; 200) 'x': Option - [203; 215) 'Option::Some': Some(T) -> Option - [203; 221) 'Option...(1u32)': Option - [216; 220) '1u32': u32 - [227; 228) 'x': Option - [227; 243) 'x.map(...v + 1)': Option - [233; 242) '|v| v + 1': |u32| -> u32 - [234; 235) 'v': u32 - [237; 238) 'v': u32 - [237; 242) 'v + 1': u32 - [241; 242) '1': u32 - [249; 250) 'x': Option - [249; 265) 'x.map(... 1u64)': Option - [255; 264) '|_v| 1u64': |u32| -> u64 - [256; 258) '_v': u32 - [260; 264) '1u64': u64 - [275; 276) 'y': Option - [292; 293) 'x': Option - [292; 305) 'x.map(|_v| 1)': Option - [298; 304) '|_v| 1': |u32| -> i64 - [299; 301) '_v': u32 - [303; 304) '1': i64 - "### - ); -} - -#[test] -fn closure_2() { - assert_snapshot!( - infer(r#" -trait FnOnce { - type Output; -} - -fn test u64>(f: F) { - f(1); - let g = |v| v + 1; - g(1u64); - let h = |v| 1u128 + v; -} -"#), - @r###" - [73; 74) 'f': F - [79; 155) '{ ...+ v; }': () - [85; 86) 'f': F - [85; 89) 'f(1)': {unknown} - [87; 88) '1': i32 - [99; 100) 'g': |u64| -> i32 - [103; 112) '|v| v + 1': |u64| -> i32 - [104; 105) 'v': u64 - [107; 108) 'v': u64 - [107; 112) 'v + 1': i32 - [111; 112) '1': i32 - [118; 119) 'g': |u64| -> i32 - [118; 125) 'g(1u64)': i32 - [120; 124) '1u64': u64 - [135; 136) 'h': |u128| -> u128 - [139; 152) '|v| 1u128 + v': |u128| -> u128 - [140; 141) 'v': u128 - [143; 148) '1u128': u128 - [143; 152) '1u128 + v': u128 - [151; 152) 'v': u128 - "### - ); -} - -#[test] -fn closure_as_argument_inference_order() { - assert_snapshot!( - infer(r#" -#[lang = "fn_once"] -trait FnOnce { - type Output; -} - -fn foo1 U>(x: T, f: F) -> U {} -fn foo2 U>(f: F, x: T) -> U {} - -struct S; -impl S { - fn method(self) -> u64; - - fn foo1 U>(self, x: T, f: F) -> U {} - fn foo2 U>(self, f: F, x: T) -> U {} -} - -fn test() { - let x1 = foo1(S, |s| s.method()); - let x2 = foo2(|s| s.method(), S); - let x3 = S.foo1(S, |s| s.method()); - let x4 = S.foo2(|s| s.method(), S); -} -"#), - @r###" - [95; 96) 'x': T - [101; 102) 'f': F - [112; 114) '{}': () - [148; 149) 'f': F - [154; 155) 'x': T - [165; 167) '{}': () - [202; 206) 'self': S - [254; 258) 'self': S - [260; 261) 'x': T - [266; 267) 'f': F - [277; 279) '{}': () - [317; 321) 'self': S - [323; 324) 'f': F - [329; 330) 'x': T - [340; 342) '{}': () - [356; 515) '{ ... S); }': () - [366; 368) 'x1': u64 - [371; 375) 'foo1': fn foo1 u64>(T, F) -> U - [371; 394) 'foo1(S...hod())': u64 - [376; 377) 'S': S - [379; 393) '|s| s.method()': |S| -> u64 - [380; 381) 's': S - [383; 384) 's': S - [383; 393) 's.method()': u64 - [404; 406) 'x2': u64 - [409; 413) 'foo2': fn foo2 u64>(F, T) -> U - [409; 432) 'foo2(|...(), S)': u64 - [414; 428) '|s| s.method()': |S| -> u64 - [415; 416) 's': S - [418; 419) 's': S - [418; 428) 's.method()': u64 - [430; 431) 'S': S - [442; 444) 'x3': u64 - [447; 448) 'S': S - [447; 472) 'S.foo1...hod())': u64 - [454; 455) 'S': S - [457; 471) '|s| s.method()': |S| -> u64 - [458; 459) 's': S - [461; 462) 's': S - [461; 471) 's.method()': u64 - [482; 484) 'x4': u64 - [487; 488) 'S': S - [487; 512) 'S.foo2...(), S)': u64 - [494; 508) '|s| s.method()': |S| -> u64 - [495; 496) 's': S - [498; 499) 's': S - [498; 508) 's.method()': u64 - [510; 511) 'S': S - "### - ); -} - -#[test] -fn unselected_projection_in_trait_env_1() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - type Item; -} - -trait Trait2 { - fn foo(&self) -> u32; -} - -fn test() where T::Item: Trait2 { - let x: T::Item = no_matter; - x.foo()<|>; -} -"#, - ); - assert_eq!(t, "u32"); -} - -#[test] -fn unselected_projection_in_trait_env_2() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - type Item; -} - -trait Trait2 { - fn foo(&self) -> u32; -} - -fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { - let x: T::Item = no_matter; - x.foo()<|>; -} -"#, - ); - assert_eq!(t, "u32"); -} - -#[test] -fn trait_impl_self_ty() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - fn foo(&self); -} - -struct S; - -impl Trait for S {} - -fn test() { - S.foo()<|>; -} -"#, - ); - assert_eq!(t, "()"); -} - -#[test] -fn trait_impl_self_ty_cycle() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - fn foo(&self); -} - -struct S; - -impl Trait for S {} - -fn test() { - S.foo()<|>; -} -"#, - ); - assert_eq!(t, "{unknown}"); -} - -#[test] -fn unselected_projection_in_trait_env_cycle_1() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - type Item; -} - -trait Trait2 {} - -fn test() where T: Trait2 { - let x: T::Item = no_matter<|>; -} -"#, - ); - // this is a legitimate cycle - assert_eq!(t, "{unknown}"); -} - -#[test] -fn unselected_projection_in_trait_env_cycle_2() { - let t = type_at( - r#" -//- /main.rs -trait Trait { - type Item; -} - -fn test() where T: Trait, U: Trait { - let x: T::Item = no_matter<|>; -} -"#, - ); - // this is a legitimate cycle - assert_eq!(t, "{unknown}"); -} - -#[test] -fn bug_2467() { - assert_snapshot!( - infer(r#" -struct S(T); -impl S { - fn foo(self) -> T; -} -fn test() { - // needs to nest multiple times for variable indices to get high enough - let a = S::foo(S(1)); - let b = S::foo(S(a)); - let c = S::foo(S(b)); - let d: u32 = S::foo(S(c)); -} -"#), - @r###" - [43; 47) 'self': S - [67; 255) '{ ...c)); }': () - [153; 154) 'a': u32 - [157; 163) 'S::foo': fn foo(S) -> T - [157; 169) 'S::foo(S(1))': u32 - [164; 165) 'S': S(T) -> S - [164; 168) 'S(1)': S - [166; 167) '1': u32 - [179; 180) 'b': u32 - [183; 189) 'S::foo': fn foo(S) -> T - [183; 195) 'S::foo(S(a))': u32 - [190; 191) 'S': S(T) -> S - [190; 194) 'S(a)': S - [192; 193) 'a': u32 - [205; 206) 'c': u32 - [209; 215) 'S::foo': fn foo(S) -> T - [209; 221) 'S::foo(S(b))': u32 - [216; 217) 'S': S(T) -> S - [216; 220) 'S(b)': S - [218; 219) 'b': u32 - [231; 232) 'd': u32 - [240; 246) 'S::foo': fn foo(S) -> T - [240; 252) 'S::foo(S(c))': u32 - [247; 248) 'S': S(T) -> S - [247; 251) 'S(c)': S - [249; 250) 'c': u32 - "### - ); -} - fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { let file = db.parse(pos.file_id).ok().unwrap(); let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); @@ -5095,60 +256,3 @@ fn no_such_field_diagnostics() { "### ); } - -#[test] -fn infer_builtin_macros_line() { - assert_snapshot!( - infer(r#" -#[rustc_builtin_macro] -macro_rules! line {() => {}} - -fn main() { - let x = line!(); -} -"#), - @r###" - ![0; 1) '6': i32 - [64; 88) '{ ...!(); }': () - [74; 75) 'x': i32 - "### - ); -} - -#[test] -fn infer_builtin_macros_file() { - assert_snapshot!( - infer(r#" -#[rustc_builtin_macro] -macro_rules! file {() => {}} - -fn main() { - let x = file!(); -} -"#), - @r###" - ![0; 2) '""': &str - [64; 88) '{ ...!(); }': () - [74; 75) 'x': &str - "### - ); -} - -#[test] -fn infer_builtin_macros_column() { - assert_snapshot!( - infer(r#" -#[rustc_builtin_macro] -macro_rules! column {() => {}} - -fn main() { - let x = column!(); -} -"#), - @r###" - ![0; 2) '13': i32 - [66; 92) '{ ...!(); }': () - [76; 77) 'x': i32 - "### - ); -} diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs new file mode 100644 index 0000000000..0d9a35ce08 --- /dev/null +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -0,0 +1,268 @@ +use super::{infer, type_at, type_at_pos}; +use crate::test_db::TestDB; +use insta::assert_snapshot; +use ra_db::fixture::WithFixture; + +#[test] +fn cfg_impl_block() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:foo cfg:test +use foo::S as T; +struct S; + +#[cfg(test)] +impl S { + fn foo1(&self) -> i32 { 0 } +} + +#[cfg(not(test))] +impl S { + fn foo2(&self) -> i32 { 0 } +} + +fn test() { + let t = (S.foo1(), S.foo2(), T.foo3(), T.foo4()); + t<|>; +} + +//- /foo.rs crate:foo +struct S; + +#[cfg(not(test))] +impl S { + fn foo3(&self) -> i32 { 0 } +} + +#[cfg(test)] +impl S { + fn foo4(&self) -> i32 { 0 } +} +"#, + ); + assert_eq!("(i32, {unknown}, i32, {unknown})", type_at_pos(&db, pos)); +} + +#[test] +fn infer_macros_expanded() { + assert_snapshot!( + infer(r#" +struct Foo(Vec); + +macro_rules! foo { + ($($item:expr),*) => { + { + Foo(vec![$($item,)*]) + } + }; +} + +fn main() { + let x = foo!(1,2); +} +"#), + @r###" + ![0; 17) '{Foo(v...,2,])}': Foo + ![1; 4) 'Foo': Foo({unknown}) -> Foo + ![1; 16) 'Foo(vec![1,2,])': Foo + ![5; 15) 'vec![1,2,]': {unknown} + [156; 182) '{ ...,2); }': () + [166; 167) 'x': Foo + "### + ); +} + +#[test] +fn infer_legacy_textual_scoped_macros_expanded() { + assert_snapshot!( + infer(r#" +struct Foo(Vec); + +#[macro_use] +mod m { + macro_rules! foo { + ($($item:expr),*) => { + { + Foo(vec![$($item,)*]) + } + }; + } +} + +fn main() { + let x = foo!(1,2); + let y = crate::foo!(1,2); +} +"#), + @r###" + ![0; 17) '{Foo(v...,2,])}': Foo + ![1; 4) 'Foo': Foo({unknown}) -> Foo + ![1; 16) 'Foo(vec![1,2,])': Foo + ![5; 15) 'vec![1,2,]': {unknown} + [195; 251) '{ ...,2); }': () + [205; 206) 'x': Foo + [228; 229) 'y': {unknown} + [232; 248) 'crate:...!(1,2)': {unknown} + "### + ); +} + +#[test] +fn infer_path_qualified_macros_expanded() { + assert_snapshot!( + infer(r#" +#[macro_export] +macro_rules! foo { + () => { 42i32 } +} + +mod m { + pub use super::foo as bar; +} + +fn main() { + let x = crate::foo!(); + let y = m::bar!(); +} +"#), + @r###" + ![0; 5) '42i32': i32 + ![0; 5) '42i32': i32 + [111; 164) '{ ...!(); }': () + [121; 122) 'x': i32 + [148; 149) 'y': i32 + "### + ); +} + +#[test] +fn infer_type_value_macro_having_same_name() { + assert_snapshot!( + infer(r#" +#[macro_export] +macro_rules! foo { + () => { + mod foo { + pub use super::foo; + } + }; + ($x:tt) => { + $x + }; +} + +foo!(); + +fn foo() { + let foo = foo::foo!(42i32); +} +"#), + @r###" + ![0; 5) '42i32': i32 + [171; 206) '{ ...32); }': () + [181; 184) 'foo': i32 + "### + ); +} + +#[test] +fn processes_impls_generated_by_macros() { + let t = type_at( + r#" +//- /main.rs +macro_rules! m { + ($ident:ident) => (impl Trait for $ident {}) +} +trait Trait { fn foo(self) -> u128 {} } +struct S; +m!(S); +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn infer_macro_with_dollar_crate_is_correct_in_expr() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:foo +fn test() { + let x = (foo::foo!(1), foo::foo!(2)); + x<|>; +} + +//- /lib.rs crate:foo +#[macro_export] +macro_rules! foo { + (1) => { $crate::bar!() }; + (2) => { 1 + $crate::baz() }; +} + +#[macro_export] +macro_rules! bar { + () => { 42 } +} + +pub fn baz() -> usize { 31usize } +"#, + ); + assert_eq!("(i32, usize)", type_at_pos(&db, pos)); +} + +#[test] +fn infer_builtin_macros_line() { + assert_snapshot!( + infer(r#" +#[rustc_builtin_macro] +macro_rules! line {() => {}} + +fn main() { + let x = line!(); +} +"#), + @r###" + ![0; 1) '6': i32 + [64; 88) '{ ...!(); }': () + [74; 75) 'x': i32 + "### + ); +} + +#[test] +fn infer_builtin_macros_file() { + assert_snapshot!( + infer(r#" +#[rustc_builtin_macro] +macro_rules! file {() => {}} + +fn main() { + let x = file!(); +} +"#), + @r###" + ![0; 2) '""': &str + [64; 88) '{ ...!(); }': () + [74; 75) 'x': &str + "### + ); +} + +#[test] +fn infer_builtin_macros_column() { + assert_snapshot!( + infer(r#" +#[rustc_builtin_macro] +macro_rules! column {() => {}} + +fn main() { + let x = column!(); +} +"#), + @r###" + ![0; 2) '13': i32 + [66; 92) '{ ...!(); }': () + [76; 77) 'x': i32 + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs new file mode 100644 index 0000000000..45164c9e96 --- /dev/null +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs @@ -0,0 +1,1005 @@ +use super::{infer, type_at, type_at_pos}; +use crate::test_db::TestDB; +use insta::assert_snapshot; +use ra_db::fixture::WithFixture; + +#[test] +fn infer_slice_method() { + assert_snapshot!( + infer(r#" +#[lang = "slice"] +impl [T] { + fn foo(&self) -> T { + loop {} + } +} + +#[lang = "slice_alloc"] +impl [T] {} + +fn test() { + <[_]>::foo(b"foo"); +} +"#), + @r###" + [45; 49) 'self': &[T] + [56; 79) '{ ... }': T + [66; 73) 'loop {}': ! + [71; 73) '{}': () + [133; 160) '{ ...o"); }': () + [139; 149) '<[_]>::foo': fn foo(&[T]) -> T + [139; 157) '<[_]>:..."foo")': u8 + [150; 156) 'b"foo"': &[u8] + "### + ); +} + +#[test] +fn infer_associated_method_struct() { + assert_snapshot!( + infer(r#" +struct A { x: u32 } + +impl A { + fn new() -> A { + A { x: 0 } + } +} +fn test() { + let a = A::new(); + a.x; +} +"#), + @r###" + [49; 75) '{ ... }': A + [59; 69) 'A { x: 0 }': A + [66; 67) '0': u32 + [88; 122) '{ ...a.x; }': () + [98; 99) 'a': A + [102; 108) 'A::new': fn new() -> A + [102; 110) 'A::new()': A + [116; 117) 'a': A + [116; 119) 'a.x': u32 + "### + ); +} + +#[test] +fn infer_associated_method_enum() { + assert_snapshot!( + infer(r#" +enum A { B, C } + +impl A { + pub fn b() -> A { + A::B + } + pub fn c() -> A { + A::C + } +} +fn test() { + let a = A::b(); + a; + let c = A::c(); + c; +} +"#), + @r###" + [47; 67) '{ ... }': A + [57; 61) 'A::B': A + [88; 108) '{ ... }': A + [98; 102) 'A::C': A + [121; 178) '{ ... c; }': () + [131; 132) 'a': A + [135; 139) 'A::b': fn b() -> A + [135; 141) 'A::b()': A + [147; 148) 'a': A + [158; 159) 'c': A + [162; 166) 'A::c': fn c() -> A + [162; 168) 'A::c()': A + [174; 175) 'c': A + "### + ); +} + +#[test] +fn infer_associated_method_with_modules() { + assert_snapshot!( + infer(r#" +mod a { + struct A; + impl A { pub fn thing() -> A { A {} }} +} + +mod b { + struct B; + impl B { pub fn thing() -> u32 { 99 }} + + mod c { + struct C; + impl C { pub fn thing() -> C { C {} }} + } +} +use b::c; + +fn test() { + let x = a::A::thing(); + let y = b::B::thing(); + let z = c::C::thing(); +} +"#), + @r###" + [56; 64) '{ A {} }': A + [58; 62) 'A {}': A + [126; 132) '{ 99 }': u32 + [128; 130) '99': u32 + [202; 210) '{ C {} }': C + [204; 208) 'C {}': C + [241; 325) '{ ...g(); }': () + [251; 252) 'x': A + [255; 266) 'a::A::thing': fn thing() -> A + [255; 268) 'a::A::thing()': A + [278; 279) 'y': u32 + [282; 293) 'b::B::thing': fn thing() -> u32 + [282; 295) 'b::B::thing()': u32 + [305; 306) 'z': C + [309; 320) 'c::C::thing': fn thing() -> C + [309; 322) 'c::C::thing()': C + "### + ); +} + +#[test] +fn infer_associated_method_generics() { + assert_snapshot!( + infer(r#" +struct Gen { + val: T +} + +impl Gen { + pub fn make(val: T) -> Gen { + Gen { val } + } +} + +fn test() { + let a = Gen::make(0u32); +} +"#), + @r###" + [64; 67) 'val': T + [82; 109) '{ ... }': Gen + [92; 103) 'Gen { val }': Gen + [98; 101) 'val': T + [123; 155) '{ ...32); }': () + [133; 134) 'a': Gen + [137; 146) 'Gen::make': fn make(T) -> Gen + [137; 152) 'Gen::make(0u32)': Gen + [147; 151) '0u32': u32 + "### + ); +} + +#[test] +fn infer_associated_method_generics_with_default_param() { + assert_snapshot!( + infer(r#" +struct Gen { + val: T +} + +impl Gen { + pub fn make() -> Gen { + loop { } + } +} + +fn test() { + let a = Gen::make(); +} +"#), + @r###" + [80; 104) '{ ... }': Gen + [90; 98) 'loop { }': ! + [95; 98) '{ }': () + [118; 146) '{ ...e(); }': () + [128; 129) 'a': Gen + [132; 141) 'Gen::make': fn make() -> Gen + [132; 143) 'Gen::make()': Gen + "### + ); +} + +#[test] +fn infer_associated_method_generics_with_default_tuple_param() { + let t = type_at( + r#" +//- /main.rs +struct Gen { + val: T +} + +impl Gen { + pub fn make() -> Gen { + loop { } + } +} + +fn test() { + let a = Gen::make(); + a.val<|>; +} +"#, + ); + assert_eq!(t, "()"); +} + +#[test] +fn infer_associated_method_generics_without_args() { + assert_snapshot!( + infer(r#" +struct Gen { + val: T +} + +impl Gen { + pub fn make() -> Gen { + loop { } + } +} + +fn test() { + let a = Gen::::make(); +} +"#), + @r###" + [76; 100) '{ ... }': Gen + [86; 94) 'loop { }': ! + [91; 94) '{ }': () + [114; 149) '{ ...e(); }': () + [124; 125) 'a': Gen + [128; 144) 'Gen::<...::make': fn make() -> Gen + [128; 146) 'Gen::<...make()': Gen + "### + ); +} + +#[test] +fn infer_associated_method_generics_2_type_params_without_args() { + assert_snapshot!( + infer(r#" +struct Gen { + val: T, + val2: U, +} + +impl Gen { + pub fn make() -> Gen { + loop { } + } +} + +fn test() { + let a = Gen::::make(); +} +"#), + @r###" + [102; 126) '{ ... }': Gen + [112; 120) 'loop { }': ! + [117; 120) '{ }': () + [140; 180) '{ ...e(); }': () + [150; 151) 'a': Gen + [154; 175) 'Gen::<...::make': fn make() -> Gen + [154; 177) 'Gen::<...make()': Gen + "### + ); +} + +#[test] +fn cross_crate_associated_method_call() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:other_crate +fn test() { + let x = other_crate::foo::S::thing(); + x<|>; +} + +//- /lib.rs crate:other_crate +mod foo { + struct S; + impl S { + fn thing() -> i128 {} + } +} +"#, + ); + assert_eq!("i128", type_at_pos(&db, pos)); +} + +#[test] +fn infer_trait_method_simple() { + // the trait implementation is intentionally incomplete -- it shouldn't matter + assert_snapshot!( + infer(r#" +trait Trait1 { + fn method(&self) -> u32; +} +struct S1; +impl Trait1 for S1 {} +trait Trait2 { + fn method(&self) -> i128; +} +struct S2; +impl Trait2 for S2 {} +fn test() { + S1.method(); // -> u32 + S2.method(); // -> i128 +} +"#), + @r###" + [31; 35) 'self': &Self + [110; 114) 'self': &Self + [170; 228) '{ ...i128 }': () + [176; 178) 'S1': S1 + [176; 187) 'S1.method()': u32 + [203; 205) 'S2': S2 + [203; 214) 'S2.method()': i128 + "### + ); +} + +#[test] +fn infer_trait_method_scoped() { + // the trait implementation is intentionally incomplete -- it shouldn't matter + assert_snapshot!( + infer(r#" +struct S; +mod foo { + pub trait Trait1 { + fn method(&self) -> u32; + } + impl Trait1 for super::S {} +} +mod bar { + pub trait Trait2 { + fn method(&self) -> i128; + } + impl Trait2 for super::S {} +} + +mod foo_test { + use super::S; + use super::foo::Trait1; + fn test() { + S.method(); // -> u32 + } +} + +mod bar_test { + use super::S; + use super::bar::Trait2; + fn test() { + S.method(); // -> i128 + } +} +"#), + @r###" + [63; 67) 'self': &Self + [169; 173) 'self': &Self + [300; 337) '{ ... }': () + [310; 311) 'S': S + [310; 320) 'S.method()': u32 + [416; 454) '{ ... }': () + [426; 427) 'S': S + [426; 436) 'S.method()': i128 + "### + ); +} + +#[test] +fn infer_trait_method_generic_1() { + // the trait implementation is intentionally incomplete -- it shouldn't matter + assert_snapshot!( + infer(r#" +trait Trait { + fn method(&self) -> T; +} +struct S; +impl Trait for S {} +fn test() { + S.method(); +} +"#), + @r###" + [33; 37) 'self': &Self + [92; 111) '{ ...d(); }': () + [98; 99) 'S': S + [98; 108) 'S.method()': u32 + "### + ); +} + +#[test] +fn infer_trait_method_generic_more_params() { + // the trait implementation is intentionally incomplete -- it shouldn't matter + assert_snapshot!( + infer(r#" +trait Trait { + fn method1(&self) -> (T1, T2, T3); + fn method2(&self) -> (T3, T2, T1); +} +struct S1; +impl Trait for S1 {} +struct S2; +impl Trait for S2 {} +fn test() { + S1.method1(); // u8, u16, u32 + S1.method2(); // u32, u16, u8 + S2.method1(); // i8, i16, {unknown} + S2.method2(); // {unknown}, i16, i8 +} +"#), + @r###" + [43; 47) 'self': &Self + [82; 86) 'self': &Self + [210; 361) '{ ..., i8 }': () + [216; 218) 'S1': S1 + [216; 228) 'S1.method1()': (u8, u16, u32) + [250; 252) 'S1': S1 + [250; 262) 'S1.method2()': (u32, u16, u8) + [284; 286) 'S2': S2 + [284; 296) 'S2.method1()': (i8, i16, {unknown}) + [324; 326) 'S2': S2 + [324; 336) 'S2.method2()': ({unknown}, i16, i8) + "### + ); +} + +#[test] +fn infer_trait_method_generic_2() { + // the trait implementation is intentionally incomplete -- it shouldn't matter + assert_snapshot!( + infer(r#" +trait Trait { + fn method(&self) -> T; +} +struct S(T); +impl Trait for S {} +fn test() { + S(1u32).method(); +} +"#), + @r###" + [33; 37) 'self': &Self + [102; 127) '{ ...d(); }': () + [108; 109) 'S': S(T) -> S + [108; 115) 'S(1u32)': S + [108; 124) 'S(1u32...thod()': u32 + [110; 114) '1u32': u32 + "### + ); +} + +#[test] +fn infer_trait_assoc_method() { + assert_snapshot!( + infer(r#" +trait Default { + fn default() -> Self; +} +struct S; +impl Default for S {} +fn test() { + let s1: S = Default::default(); + let s2 = S::default(); + let s3 = ::default(); +} +"#), + @r###" + [87; 193) '{ ...t(); }': () + [97; 99) 's1': S + [105; 121) 'Defaul...efault': fn default() -> Self + [105; 123) 'Defaul...ault()': S + [133; 135) 's2': S + [138; 148) 'S::default': fn default() -> Self + [138; 150) 'S::default()': S + [160; 162) 's3': S + [165; 188) '() -> Self + [165; 190) ' { + fn make() -> T; +} +struct S; +impl Trait for S {} +struct G; +impl Trait for G {} +fn test() { + let a = S::make(); + let b = G::::make(); + let c: f64 = G::make(); +} +"#), + @r###" + [127; 211) '{ ...e(); }': () + [137; 138) 'a': u32 + [141; 148) 'S::make': fn make() -> T + [141; 150) 'S::make()': u32 + [160; 161) 'b': u64 + [164; 178) 'G::::make': fn make, u64>() -> T + [164; 180) 'G::, f64>() -> T + [199; 208) 'G::make()': f64 + "### + ); +} + +#[test] +fn infer_trait_assoc_method_generics_2() { + assert_snapshot!( + infer(r#" +trait Trait { + fn make() -> (T, U); +} +struct S; +impl Trait for S {} +struct G; +impl Trait for G {} +fn test() { + let a = S::make::(); + let b: (_, i64) = S::make(); + let c = G::::make::(); + let d: (u32, _) = G::make::(); + let e: (u32, i64) = G::make(); +} +"#), + @r###" + [135; 313) '{ ...e(); }': () + [145; 146) 'a': (u32, i64) + [149; 163) 'S::make::': fn make() -> (T, U) + [149; 165) 'S::mak...i64>()': (u32, i64) + [175; 176) 'b': (u32, i64) + [189; 196) 'S::make': fn make() -> (T, U) + [189; 198) 'S::make()': (u32, i64) + [208; 209) 'c': (u32, i64) + [212; 233) 'G::': fn make, u32, i64>() -> (T, U) + [212; 235) 'G::()': (u32, i64) + [245; 246) 'd': (u32, i64) + [259; 273) 'G::make::': fn make, u32, i64>() -> (T, U) + [259; 275) 'G::mak...i64>()': (u32, i64) + [285; 286) 'e': (u32, i64) + [301; 308) 'G::make': fn make, u32, i64>() -> (T, U) + [301; 310) 'G::make()': (u32, i64) + "### + ); +} + +#[test] +fn infer_trait_assoc_method_generics_3() { + assert_snapshot!( + infer(r#" +trait Trait { + fn make() -> (Self, T); +} +struct S; +impl Trait for S {} +fn test() { + let a = S::make(); +} +"#), + @r###" + [101; 127) '{ ...e(); }': () + [111; 112) 'a': (S, i64) + [115; 122) 'S::make': fn make, i64>() -> (Self, T) + [115; 124) 'S::make()': (S, i64) + "### + ); +} + +#[test] +fn infer_trait_assoc_method_generics_4() { + assert_snapshot!( + infer(r#" +trait Trait { + fn make() -> (Self, T); +} +struct S; +impl Trait for S {} +impl Trait for S {} +fn test() { + let a: (S, _) = S::make(); + let b: (_, i32) = S::make(); +} +"#), + @r###" + [131; 203) '{ ...e(); }': () + [141; 142) 'a': (S, i64) + [158; 165) 'S::make': fn make, i64>() -> (Self, T) + [158; 167) 'S::make()': (S, i64) + [177; 178) 'b': (S, i32) + [191; 198) 'S::make': fn make, i32>() -> (Self, T) + [191; 200) 'S::make()': (S, i32) + "### + ); +} + +#[test] +fn infer_trait_assoc_method_generics_5() { + assert_snapshot!( + infer(r#" +trait Trait { + fn make() -> (Self, T, U); +} +struct S; +impl Trait for S {} +fn test() { + let a = >::make::(); + let b: (S, _, _) = Trait::::make::(); +} +"#), + @r###" + [107; 211) '{ ...>(); }': () + [117; 118) 'a': (S, i64, u8) + [121; 150) '': fn make, i64, u8>() -> (Self, T, U) + [121; 152) '()': (S, i64, u8) + [162; 163) 'b': (S, i64, u8) + [182; 206) 'Trait:...::': fn make, i64, u8>() -> (Self, T, U) + [182; 208) 'Trait:...()': (S, i64, u8) + "### + ); +} + +#[test] +fn infer_call_trait_method_on_generic_param_1() { + assert_snapshot!( + infer(r#" +trait Trait { + fn method(&self) -> u32; +} +fn test(t: T) { + t.method(); +} +"#), + @r###" + [30; 34) 'self': &Self + [64; 65) 't': T + [70; 89) '{ ...d(); }': () + [76; 77) 't': T + [76; 86) 't.method()': u32 + "### + ); +} + +#[test] +fn infer_call_trait_method_on_generic_param_2() { + assert_snapshot!( + infer(r#" +trait Trait { + fn method(&self) -> T; +} +fn test>(t: T) { + t.method(); +} +"#), + @r###" + [33; 37) 'self': &Self + [71; 72) 't': T + [77; 96) '{ ...d(); }': () + [83; 84) 't': T + [83; 93) 't.method()': [missing name] + "### + ); +} + +#[test] +fn infer_with_multiple_trait_impls() { + assert_snapshot!( + infer(r#" +trait Into { + fn into(self) -> T; +} +struct S; +impl Into for S {} +impl Into for S {} +fn test() { + let x: u32 = S.into(); + let y: u64 = S.into(); + let z = Into::::into(S); +} +"#), + @r###" + [29; 33) 'self': Self + [111; 202) '{ ...(S); }': () + [121; 122) 'x': u32 + [130; 131) 'S': S + [130; 138) 'S.into()': u32 + [148; 149) 'y': u64 + [157; 158) 'S': S + [157; 165) 'S.into()': u64 + [175; 176) 'z': u64 + [179; 196) 'Into::...::into': fn into(Self) -> T + [179; 199) 'Into::...nto(S)': u64 + [197; 198) 'S': S + "### + ); +} + +#[test] +fn method_resolution_unify_impl_self_type() { + let t = type_at( + r#" +//- /main.rs +struct S; +impl S { fn foo(&self) -> u8 {} } +impl S { fn foo(&self) -> i8 {} } +fn test() { (S::.foo(), S::.foo())<|>; } +"#, + ); + assert_eq!(t, "(u8, i8)"); +} + +#[test] +fn method_resolution_trait_before_autoref() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl S { fn foo(&self) -> i8 { 0 } } +impl Trait for S { fn foo(self) -> u128 { 0 } } +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn method_resolution_by_value_before_autoref() { + let t = type_at( + r#" +//- /main.rs +trait Clone { fn clone(&self) -> Self; } +struct S; +impl Clone for S {} +impl Clone for &S {} +fn test() { (S.clone(), (&S).clone(), (&&S).clone())<|>; } +"#, + ); + assert_eq!(t, "(S, S, &S)"); +} + +#[test] +fn method_resolution_trait_before_autoderef() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl S { fn foo(self) -> i8 { 0 } } +impl Trait for &S { fn foo(self) -> u128 { 0 } } +fn test() { (&S).foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn method_resolution_impl_before_trait() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl S { fn foo(self) -> i8 { 0 } } +impl Trait for S { fn foo(self) -> u128 { 0 } } +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "i8"); +} + +#[test] +fn method_resolution_impl_ref_before_trait() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl S { fn foo(&self) -> i8 { 0 } } +impl Trait for &S { fn foo(self) -> u128 { 0 } } +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "i8"); +} + +#[test] +fn method_resolution_trait_autoderef() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for S { fn foo(self) -> u128 { 0 } } +fn test() { (&S).foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn method_resolution_trait_from_prelude() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:other_crate +struct S; +impl Clone for S {} + +fn test() { + S.clone()<|>; +} + +//- /lib.rs crate:other_crate +#[prelude_import] use foo::*; + +mod foo { + trait Clone { + fn clone(&self) -> Self; + } +} +"#, + ); + assert_eq!("S", type_at_pos(&db, pos)); +} + +#[test] +fn method_resolution_where_clause_for_unknown_trait() { + // The blanket impl shouldn't apply because we can't even resolve UnknownTrait + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for T where T: UnknownTrait {} +fn test() { (&S).foo()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn method_resolution_where_clause_not_met() { + // The blanket impl shouldn't apply because we can't prove S: Clone + let t = type_at( + r#" +//- /main.rs +trait Clone {} +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for T where T: Clone {} +fn test() { (&S).foo()<|>; } +"#, + ); + // This is also to make sure that we don't resolve to the foo method just + // because that's the only method named foo we can find, which would make + // the below tests not work + assert_eq!(t, "{unknown}"); +} + +#[test] +fn method_resolution_where_clause_inline_not_met() { + // The blanket impl shouldn't apply because we can't prove S: Clone + let t = type_at( + r#" +//- /main.rs +trait Clone {} +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for T {} +fn test() { (&S).foo()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn method_resolution_where_clause_1() { + let t = type_at( + r#" +//- /main.rs +trait Clone {} +trait Trait { fn foo(self) -> u128; } +struct S; +impl Clone for S {} +impl Trait for T where T: Clone {} +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn method_resolution_where_clause_2() { + let t = type_at( + r#" +//- /main.rs +trait Into { fn into(self) -> T; } +trait From { fn from(other: T) -> Self; } +struct S1; +struct S2; +impl From for S1 {} +impl Into for T where U: From {} +fn test() { S2.into()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn method_resolution_where_clause_inline() { + let t = type_at( + r#" +//- /main.rs +trait Into { fn into(self) -> T; } +trait From { fn from(other: T) -> Self; } +struct S1; +struct S2; +impl From for S1 {} +impl> Into for T {} +fn test() { S2.into()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn method_resolution_encountering_fn_type() { + type_at( + r#" +//- /main.rs +fn foo() {} +trait FnOnce { fn call(self); } +fn test() { foo.call()<|>; } +"#, + ); +} + +#[test] +fn method_resolution_slow() { + // this can get quite slow if we set the solver size limit too high + let t = type_at( + r#" +//- /main.rs +trait SendX {} + +struct S1; impl SendX for S1 {} +struct S2; impl SendX for S2 {} +struct U1; + +trait Trait { fn method(self); } + +struct X1 {} +impl SendX for X1 where A: SendX, B: SendX {} + +struct S {} + +trait FnX {} + +impl Trait for S where C: FnX, B: SendX {} + +fn test() { (S {}).method()<|>; } +"#, + ); + assert_eq!(t, "()"); +} diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs new file mode 100644 index 0000000000..cb3890b423 --- /dev/null +++ b/crates/ra_hir_ty/src/tests/patterns.rs @@ -0,0 +1,238 @@ +use super::infer; +use insta::assert_snapshot; +use test_utils::covers; + +#[test] +fn infer_pattern() { + assert_snapshot!( + infer(r#" +fn test(x: &i32) { + let y = x; + let &z = x; + let a = z; + let (c, d) = (1, "hello"); + + for (e, f) in some_iter { + let g = e; + } + + if let [val] = opt { + let h = val; + } + + let lambda = |a: u64, b, c: i32| { a + b; c }; + + let ref ref_to_x = x; + let mut mut_x = x; + let ref mut mut_ref_to_x = x; + let k = mut_ref_to_x; +} +"#), + @r###" + [9; 10) 'x': &i32 + [18; 369) '{ ...o_x; }': () + [28; 29) 'y': &i32 + [32; 33) 'x': &i32 + [43; 45) '&z': &i32 + [44; 45) 'z': i32 + [48; 49) 'x': &i32 + [59; 60) 'a': i32 + [63; 64) 'z': i32 + [74; 80) '(c, d)': (i32, &str) + [75; 76) 'c': i32 + [78; 79) 'd': &str + [83; 95) '(1, "hello")': (i32, &str) + [84; 85) '1': i32 + [87; 94) '"hello"': &str + [102; 152) 'for (e... }': () + [106; 112) '(e, f)': ({unknown}, {unknown}) + [107; 108) 'e': {unknown} + [110; 111) 'f': {unknown} + [116; 125) 'some_iter': {unknown} + [126; 152) '{ ... }': () + [140; 141) 'g': {unknown} + [144; 145) 'e': {unknown} + [158; 205) 'if let... }': () + [165; 170) '[val]': {unknown} + [173; 176) 'opt': {unknown} + [177; 205) '{ ... }': () + [191; 192) 'h': {unknown} + [195; 198) 'val': {unknown} + [215; 221) 'lambda': |u64, u64, i32| -> i32 + [224; 256) '|a: u6...b; c }': |u64, u64, i32| -> i32 + [225; 226) 'a': u64 + [233; 234) 'b': u64 + [236; 237) 'c': i32 + [244; 256) '{ a + b; c }': i32 + [246; 247) 'a': u64 + [246; 251) 'a + b': u64 + [250; 251) 'b': u64 + [253; 254) 'c': i32 + [267; 279) 'ref ref_to_x': &&i32 + [282; 283) 'x': &i32 + [293; 302) 'mut mut_x': &i32 + [305; 306) 'x': &i32 + [316; 336) 'ref mu...f_to_x': &mut &i32 + [339; 340) 'x': &i32 + [350; 351) 'k': &mut &i32 + [354; 366) 'mut_ref_to_x': &mut &i32 + "### + ); +} + +#[test] +fn infer_pattern_match_ergonomics() { + assert_snapshot!( + infer(r#" +struct A(T); + +fn test() { + let A(n) = &A(1); + let A(n) = &mut A(1); +} +"#), + @r###" + [28; 79) '{ ...(1); }': () + [38; 42) 'A(n)': A + [40; 41) 'n': &i32 + [45; 50) '&A(1)': &A + [46; 47) 'A': A(T) -> A + [46; 50) 'A(1)': A + [48; 49) '1': i32 + [60; 64) 'A(n)': A + [62; 63) 'n': &mut i32 + [67; 76) '&mut A(1)': &mut A + [72; 73) 'A': A(T) -> A + [72; 76) 'A(1)': A + [74; 75) '1': i32 + "### + ); +} + +#[test] +fn infer_pattern_match_ergonomics_ref() { + covers!(match_ergonomics_ref); + assert_snapshot!( + infer(r#" +fn test() { + let v = &(1, &2); + let (_, &w) = v; +} +"#), + @r###" + [11; 57) '{ ...= v; }': () + [21; 22) 'v': &(i32, &i32) + [25; 33) '&(1, &2)': &(i32, &i32) + [26; 33) '(1, &2)': (i32, &i32) + [27; 28) '1': i32 + [30; 32) '&2': &i32 + [31; 32) '2': i32 + [43; 50) '(_, &w)': (i32, &i32) + [44; 45) '_': i32 + [47; 49) '&w': &i32 + [48; 49) 'w': i32 + [53; 54) 'v': &(i32, &i32) + "### + ); +} + +#[test] +fn infer_adt_pattern() { + assert_snapshot!( + infer(r#" +enum E { + A { x: usize }, + B +} + +struct S(u32, E); + +fn test() { + let e = E::A { x: 3 }; + + let S(y, z) = foo; + let E::A { x: new_var } = e; + + match e { + E::A { x } => x, + E::B if foo => 1, + E::B => 10, + }; + + let ref d @ E::A { .. } = e; + d; +} +"#), + @r###" + [68; 289) '{ ... d; }': () + [78; 79) 'e': E + [82; 95) 'E::A { x: 3 }': E + [92; 93) '3': usize + [106; 113) 'S(y, z)': S + [108; 109) 'y': u32 + [111; 112) 'z': E + [116; 119) 'foo': S + [129; 148) 'E::A {..._var }': E + [139; 146) 'new_var': usize + [151; 152) 'e': E + [159; 245) 'match ... }': usize + [165; 166) 'e': E + [177; 187) 'E::A { x }': E + [184; 185) 'x': usize + [191; 192) 'x': usize + [202; 206) 'E::B': E + [210; 213) 'foo': bool + [217; 218) '1': usize + [228; 232) 'E::B': E + [236; 238) '10': usize + [256; 275) 'ref d ...{ .. }': &E + [264; 275) 'E::A { .. }': E + [278; 279) 'e': E + [285; 286) 'd': &E + "### + ); +} + +#[test] +fn infer_generics_in_patterns() { + assert_snapshot!( + infer(r#" +struct A { + x: T, +} + +enum Option { + Some(T), + None, +} + +fn test(a1: A, o: Option) { + let A { x: x2 } = a1; + let A:: { x: x3 } = A { x: 1 }; + match o { + Option::Some(t) => t, + _ => 1, + }; +} +"#), + @r###" + [79; 81) 'a1': A + [91; 92) 'o': Option + [107; 244) '{ ... }; }': () + [117; 128) 'A { x: x2 }': A + [124; 126) 'x2': u32 + [131; 133) 'a1': A + [143; 161) 'A:: + [157; 159) 'x3': i64 + [164; 174) 'A { x: 1 }': A + [171; 172) '1': i64 + [180; 241) 'match ... }': u64 + [186; 187) 'o': Option + [198; 213) 'Option::Some(t)': Option + [211; 212) 't': u64 + [217; 218) 't': u64 + [228; 229) '_': Option + [233; 234) '1': u64 + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs new file mode 100644 index 0000000000..09d684ac2a --- /dev/null +++ b/crates/ra_hir_ty/src/tests/regression.rs @@ -0,0 +1,333 @@ +use super::infer; +use insta::assert_snapshot; +use test_utils::covers; + +#[test] +fn bug_484() { + assert_snapshot!( + infer(r#" +fn test() { + let x = if true {}; +} +"#), + @r###" + [11; 37) '{ l... {}; }': () + [20; 21) 'x': () + [24; 34) 'if true {}': () + [27; 31) 'true': bool + [32; 34) '{}': () + "### + ); +} + +#[test] +fn no_panic_on_field_of_enum() { + assert_snapshot!( + infer(r#" +enum X {} + +fn test(x: X) { + x.some_field; +} +"#), + @r###" + [20; 21) 'x': X + [26; 47) '{ ...eld; }': () + [32; 33) 'x': X + [32; 44) 'x.some_field': {unknown} + "### + ); +} + +#[test] +fn bug_585() { + assert_snapshot!( + infer(r#" +fn test() { + X {}; + match x { + A::B {} => (), + A::Y() => (), + } +} +"#), + @r###" + [11; 89) '{ ... } }': () + [17; 21) 'X {}': {unknown} + [27; 87) 'match ... }': () + [33; 34) 'x': {unknown} + [45; 52) 'A::B {}': {unknown} + [56; 58) '()': () + [68; 74) 'A::Y()': {unknown} + [78; 80) '()': () + "### + ); +} + +#[test] +fn bug_651() { + assert_snapshot!( + infer(r#" +fn quux() { + let y = 92; + 1 + y; +} +"#), + @r###" + [11; 41) '{ ...+ y; }': () + [21; 22) 'y': i32 + [25; 27) '92': i32 + [33; 34) '1': i32 + [33; 38) '1 + y': i32 + [37; 38) 'y': i32 + "### + ); +} + +#[test] +fn recursive_vars() { + covers!(type_var_cycles_resolve_completely); + covers!(type_var_cycles_resolve_as_possible); + assert_snapshot!( + infer(r#" +fn test() { + let y = unknown; + [y, &y]; +} +"#), + @r###" + [11; 48) '{ ...&y]; }': () + [21; 22) 'y': &{unknown} + [25; 32) 'unknown': &{unknown} + [38; 45) '[y, &y]': [&&{unknown};_] + [39; 40) 'y': &{unknown} + [42; 44) '&y': &&{unknown} + [43; 44) 'y': &{unknown} + "### + ); +} + +#[test] +fn recursive_vars_2() { + covers!(type_var_cycles_resolve_completely); + covers!(type_var_cycles_resolve_as_possible); + assert_snapshot!( + infer(r#" +fn test() { + let x = unknown; + let y = unknown; + [(x, y), (&y, &x)]; +} +"#), + @r###" + [11; 80) '{ ...x)]; }': () + [21; 22) 'x': &&{unknown} + [25; 32) 'unknown': &&{unknown} + [42; 43) 'y': &&{unknown} + [46; 53) 'unknown': &&{unknown} + [59; 77) '[(x, y..., &x)]': [(&&&{unknown}, &&&{unknown});_] + [60; 66) '(x, y)': (&&&{unknown}, &&&{unknown}) + [61; 62) 'x': &&{unknown} + [64; 65) 'y': &&{unknown} + [68; 76) '(&y, &x)': (&&&{unknown}, &&&{unknown}) + [69; 71) '&y': &&&{unknown} + [70; 71) 'y': &&{unknown} + [73; 75) '&x': &&&{unknown} + [74; 75) 'x': &&{unknown} + "### + ); +} + +#[test] +fn infer_std_crash_1() { + // caused stack overflow, taken from std + assert_snapshot!( + infer(r#" +enum Maybe { + Real(T), + Fake, +} + +fn write() { + match something_unknown { + Maybe::Real(ref mut something) => (), + } +} +"#), + @r###" + [54; 139) '{ ... } }': () + [60; 137) 'match ... }': () + [66; 83) 'someth...nknown': Maybe<{unknown}> + [94; 124) 'Maybe:...thing)': Maybe<{unknown}> + [106; 123) 'ref mu...ething': &mut {unknown} + [128; 130) '()': () + "### + ); +} + +#[test] +fn infer_std_crash_2() { + covers!(type_var_resolves_to_int_var); + // caused "equating two type variables, ...", taken from std + assert_snapshot!( + infer(r#" +fn test_line_buffer() { + &[0, b'\n', 1, b'\n']; +} +"#), + @r###" + [23; 53) '{ ...n']; }': () + [29; 50) '&[0, b...b'\n']': &[u8;_] + [30; 50) '[0, b'...b'\n']': [u8;_] + [31; 32) '0': u8 + [34; 39) 'b'\n'': u8 + [41; 42) '1': u8 + [44; 49) 'b'\n'': u8 + "### + ); +} + +#[test] +fn infer_std_crash_3() { + // taken from rustc + assert_snapshot!( + infer(r#" +pub fn compute() { + match nope!() { + SizeSkeleton::Pointer { non_zero: true, tail } => {} + } +} +"#), + @r###" + [18; 108) '{ ... } }': () + [24; 106) 'match ... }': () + [30; 37) 'nope!()': {unknown} + [48; 94) 'SizeSk...tail }': {unknown} + [82; 86) 'true': {unknown} + [88; 92) 'tail': {unknown} + [98; 100) '{}': () + "### + ); +} + +#[test] +fn infer_std_crash_4() { + // taken from rustc + assert_snapshot!( + infer(r#" +pub fn primitive_type() { + match *self { + BorrowedRef { type_: Primitive(p), ..} => {}, + } +} +"#), + @r###" + [25; 106) '{ ... } }': () + [31; 104) 'match ... }': () + [37; 42) '*self': {unknown} + [38; 42) 'self': {unknown} + [53; 91) 'Borrow...), ..}': {unknown} + [74; 86) 'Primitive(p)': {unknown} + [84; 85) 'p': {unknown} + [95; 97) '{}': () + "### + ); +} + +#[test] +fn infer_std_crash_5() { + // taken from rustc + assert_snapshot!( + infer(r#" +fn extra_compiler_flags() { + for content in doesnt_matter { + let name = if doesnt_matter { + first + } else { + &content + }; + + let content = if ICE_REPORT_COMPILER_FLAGS_STRIP_VALUE.contains(&name) { + name + } else { + content + }; + } +} +"#), + @r###" + [27; 323) '{ ... } }': () + [33; 321) 'for co... }': () + [37; 44) 'content': &{unknown} + [48; 61) 'doesnt_matter': {unknown} + [62; 321) '{ ... }': () + [76; 80) 'name': &&{unknown} + [83; 167) 'if doe... }': &&{unknown} + [86; 99) 'doesnt_matter': bool + [100; 129) '{ ... }': &&{unknown} + [114; 119) 'first': &&{unknown} + [135; 167) '{ ... }': &&{unknown} + [149; 157) '&content': &&{unknown} + [150; 157) 'content': &{unknown} + [182; 189) 'content': &{unknown} + [192; 314) 'if ICE... }': &{unknown} + [195; 232) 'ICE_RE..._VALUE': {unknown} + [195; 248) 'ICE_RE...&name)': bool + [242; 247) '&name': &&&{unknown} + [243; 247) 'name': &&{unknown} + [249; 277) '{ ... }': &&{unknown} + [263; 267) 'name': &&{unknown} + [283; 314) '{ ... }': &{unknown} + [297; 304) 'content': &{unknown} + "### + ); +} + +#[test] +fn infer_nested_generics_crash() { + // another crash found typechecking rustc + assert_snapshot!( + infer(r#" +struct Canonical { + value: V, +} +struct QueryResponse { + value: V, +} +fn test(query_response: Canonical>) { + &query_response.value; +} +"#), + @r###" + [92; 106) 'query_response': Canonical> + [137; 167) '{ ...lue; }': () + [143; 164) '&query....value': &QueryResponse + [144; 158) 'query_response': Canonical> + [144; 164) 'query_....value': QueryResponse + "### + ); +} + +#[test] +fn bug_1030() { + assert_snapshot!(infer(r#" +struct HashSet; +struct FxHasher; +type FxHashSet = HashSet; + +impl HashSet { + fn default() -> HashSet {} +} + +pub fn main_loop() { + FxHashSet::default(); +} +"#), + @r###" + [144; 146) '{}': () + [169; 198) '{ ...t(); }': () + [175; 193) 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet + [175; 195) 'FxHash...ault()': HashSet<{unknown}, FxHasher> + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs new file mode 100644 index 0000000000..18976c9aee --- /dev/null +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -0,0 +1,1608 @@ +use super::{infer, type_at, type_at_pos}; +use crate::test_db::TestDB; +use insta::assert_snapshot; +use ra_db::fixture::WithFixture; + +#[test] +fn infer_box() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +fn test() { + let x = box 1; + let t = (x, box x, box &1, box [1]); + t<|>; +} + +//- /std.rs crate:std +#[prelude_import] use prelude::*; +mod prelude {} + +mod boxed { + pub struct Box { + inner: *mut T, + } +} + +"#, + ); + assert_eq!("(Box, Box>, Box<&i32>, Box<[i32;_]>)", type_at_pos(&db, pos)); +} + +#[test] +fn infer_adt_self() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs +enum Nat { Succ(Self), Demo(Nat), Zero } + +fn test() { + let foo: Nat = Nat::Zero; + if let Nat::Succ(x) = foo { + x<|> + } +} + +"#, + ); + assert_eq!("Nat", type_at_pos(&db, pos)); +} + +#[test] +fn infer_ranges() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std +fn test() { + let a = ..; + let b = 1..; + let c = ..2u32; + let d = 1..2usize; + let e = ..=10; + let f = 'a'..='z'; + + let t = (a, b, c, d, e, f); + t<|>; +} + +//- /std.rs crate:std +#[prelude_import] use prelude::*; +mod prelude {} + +pub mod ops { + pub struct Range { + pub start: Idx, + pub end: Idx, + } + pub struct RangeFrom { + pub start: Idx, + } + struct RangeFull; + pub struct RangeInclusive { + start: Idx, + end: Idx, + is_empty: u8, + } + pub struct RangeTo { + pub end: Idx, + } + pub struct RangeToInclusive { + pub end: Idx, + } +} +"#, + ); + assert_eq!( + "(RangeFull, RangeFrom, RangeTo, Range, RangeToInclusive, RangeInclusive)", + type_at_pos(&db, pos), + ); +} + +#[test] +fn infer_while_let() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs +enum Option { Some(T), None } + +fn test() { + let foo: Option = None; + while let Option::Some(x) = foo { + <|>x + } +} + +"#, + ); + assert_eq!("f32", type_at_pos(&db, pos)); +} + +#[test] +fn infer_basics() { + assert_snapshot!( + infer(r#" +fn test(a: u32, b: isize, c: !, d: &str) { + a; + b; + c; + d; + 1usize; + 1isize; + "test"; + 1.0f32; +}"#), + @r###" + [9; 10) 'a': u32 + [17; 18) 'b': isize + [27; 28) 'c': ! + [33; 34) 'd': &str + [42; 121) '{ ...f32; }': ! + [48; 49) 'a': u32 + [55; 56) 'b': isize + [62; 63) 'c': ! + [69; 70) 'd': &str + [76; 82) '1usize': usize + [88; 94) '1isize': isize + [100; 106) '"test"': &str + [112; 118) '1.0f32': f32 + "### + ); +} + +#[test] +fn infer_let() { + assert_snapshot!( + infer(r#" +fn test() { + let a = 1isize; + let b: usize = 1; + let c = b; + let d: u32; + let e; + let f: i32 = e; +} +"#), + @r###" + [11; 118) '{ ...= e; }': () + [21; 22) 'a': isize + [25; 31) '1isize': isize + [41; 42) 'b': usize + [52; 53) '1': usize + [63; 64) 'c': usize + [67; 68) 'b': usize + [78; 79) 'd': u32 + [94; 95) 'e': i32 + [105; 106) 'f': i32 + [114; 115) 'e': i32 + "### + ); +} + +#[test] +fn infer_paths() { + assert_snapshot!( + infer(r#" +fn a() -> u32 { 1 } + +mod b { + fn c() -> u32 { 1 } +} + +fn test() { + a(); + b::c(); +} +"#), + @r###" + [15; 20) '{ 1 }': u32 + [17; 18) '1': u32 + [48; 53) '{ 1 }': u32 + [50; 51) '1': u32 + [67; 91) '{ ...c(); }': () + [73; 74) 'a': fn a() -> u32 + [73; 76) 'a()': u32 + [82; 86) 'b::c': fn c() -> u32 + [82; 88) 'b::c()': u32 + "### + ); +} + +#[test] +fn infer_path_type() { + assert_snapshot!( + infer(r#" +struct S; + +impl S { + fn foo() -> i32 { 1 } +} + +fn test() { + S::foo(); + ::foo(); +} +"#), + @r###" + [41; 46) '{ 1 }': i32 + [43; 44) '1': i32 + [60; 93) '{ ...o(); }': () + [66; 72) 'S::foo': fn foo() -> i32 + [66; 74) 'S::foo()': i32 + [80; 88) '::foo': fn foo() -> i32 + [80; 90) '::foo()': i32 + "### + ); +} + +#[test] +fn infer_struct() { + assert_snapshot!( + infer(r#" +struct A { + b: B, + c: C, +} +struct B; +struct C(usize); + +fn test() { + let c = C(1); + B; + let a: A = A { b: B, c: C(1) }; + a.b; + a.c; +} +"#), + @r###" + [72; 154) '{ ...a.c; }': () + [82; 83) 'c': C + [86; 87) 'C': C(usize) -> C + [86; 90) 'C(1)': C + [88; 89) '1': usize + [96; 97) 'B': B + [107; 108) 'a': A + [114; 133) 'A { b:...C(1) }': A + [121; 122) 'B': B + [127; 128) 'C': C(usize) -> C + [127; 131) 'C(1)': C + [129; 130) '1': usize + [139; 140) 'a': A + [139; 142) 'a.b': B + [148; 149) 'a': A + [148; 151) 'a.c': C + "### + ); +} + +#[test] +fn infer_enum() { + assert_snapshot!( + infer(r#" +enum E { + V1 { field: u32 }, + V2 +} +fn test() { + E::V1 { field: 1 }; + E::V2; +}"#), + @r###" + [48; 82) '{ E:...:V2; }': () + [52; 70) 'E::V1 ...d: 1 }': E + [67; 68) '1': u32 + [74; 79) 'E::V2': E + "### + ); +} + +#[test] +fn infer_refs() { + assert_snapshot!( + infer(r#" +fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) { + a; + *a; + &a; + &mut a; + b; + *b; + &b; + c; + *c; + d; + *d; +} +"#), + @r###" + [9; 10) 'a': &u32 + [18; 19) 'b': &mut u32 + [31; 32) 'c': *const u32 + [46; 47) 'd': *mut u32 + [59; 150) '{ ... *d; }': () + [65; 66) 'a': &u32 + [72; 74) '*a': u32 + [73; 74) 'a': &u32 + [80; 82) '&a': &&u32 + [81; 82) 'a': &u32 + [88; 94) '&mut a': &mut &u32 + [93; 94) 'a': &u32 + [100; 101) 'b': &mut u32 + [107; 109) '*b': u32 + [108; 109) 'b': &mut u32 + [115; 117) '&b': &&mut u32 + [116; 117) 'b': &mut u32 + [123; 124) 'c': *const u32 + [130; 132) '*c': u32 + [131; 132) 'c': *const u32 + [138; 139) 'd': *mut u32 + [145; 147) '*d': u32 + [146; 147) 'd': *mut u32 + "### + ); +} + +#[test] +fn infer_literals() { + assert_snapshot!( + infer(r##" +fn test() { + 5i32; + 5f32; + 5f64; + "hello"; + b"bytes"; + 'c'; + b'b'; + 3.14; + 5000; + false; + true; + r#" + //! doc + // non-doc + mod foo {} + "#; + br#"yolo"#; +} +"##), + @r###" + [11; 221) '{ ...o"#; }': () + [17; 21) '5i32': i32 + [27; 31) '5f32': f32 + [37; 41) '5f64': f64 + [47; 54) '"hello"': &str + [60; 68) 'b"bytes"': &[u8] + [74; 77) ''c'': char + [83; 87) 'b'b'': u8 + [93; 97) '3.14': f64 + [103; 107) '5000': i32 + [113; 118) 'false': bool + [124; 128) 'true': bool + [134; 202) 'r#" ... "#': &str + [208; 218) 'br#"yolo"#': &[u8] + "### + ); +} + +#[test] +fn infer_unary_op() { + assert_snapshot!( + infer(r#" +enum SomeType {} + +fn test(x: SomeType) { + let b = false; + let c = !b; + let a = 100; + let d: i128 = -a; + let e = -100; + let f = !!!true; + let g = !42; + let h = !10u32; + let j = !a; + -3.14; + !3; + -x; + !x; + -"hello"; + !"hello"; +} +"#), + @r###" + [27; 28) 'x': SomeType + [40; 272) '{ ...lo"; }': () + [50; 51) 'b': bool + [54; 59) 'false': bool + [69; 70) 'c': bool + [73; 75) '!b': bool + [74; 75) 'b': bool + [85; 86) 'a': i128 + [89; 92) '100': i128 + [102; 103) 'd': i128 + [112; 114) '-a': i128 + [113; 114) 'a': i128 + [124; 125) 'e': i32 + [128; 132) '-100': i32 + [129; 132) '100': i32 + [142; 143) 'f': bool + [146; 153) '!!!true': bool + [147; 153) '!!true': bool + [148; 153) '!true': bool + [149; 153) 'true': bool + [163; 164) 'g': i32 + [167; 170) '!42': i32 + [168; 170) '42': i32 + [180; 181) 'h': u32 + [184; 190) '!10u32': u32 + [185; 190) '10u32': u32 + [200; 201) 'j': i128 + [204; 206) '!a': i128 + [205; 206) 'a': i128 + [212; 217) '-3.14': f64 + [213; 217) '3.14': f64 + [223; 225) '!3': i32 + [224; 225) '3': i32 + [231; 233) '-x': {unknown} + [232; 233) 'x': SomeType + [239; 241) '!x': {unknown} + [240; 241) 'x': SomeType + [247; 255) '-"hello"': {unknown} + [248; 255) '"hello"': &str + [261; 269) '!"hello"': {unknown} + [262; 269) '"hello"': &str + "### + ); +} + +#[test] +fn infer_backwards() { + assert_snapshot!( + infer(r#" +fn takes_u32(x: u32) {} + +struct S { i32_field: i32 } + +fn test() -> &mut &f64 { + let a = unknown_function(); + takes_u32(a); + let b = unknown_function(); + S { i32_field: b }; + let c = unknown_function(); + &mut &c +} +"#), + @r###" + [14; 15) 'x': u32 + [22; 24) '{}': () + [78; 231) '{ ...t &c }': &mut &f64 + [88; 89) 'a': u32 + [92; 108) 'unknow...nction': {unknown} + [92; 110) 'unknow...tion()': u32 + [116; 125) 'takes_u32': fn takes_u32(u32) -> () + [116; 128) 'takes_u32(a)': () + [126; 127) 'a': u32 + [138; 139) 'b': i32 + [142; 158) 'unknow...nction': {unknown} + [142; 160) 'unknow...tion()': i32 + [166; 184) 'S { i3...d: b }': S + [181; 182) 'b': i32 + [194; 195) 'c': f64 + [198; 214) 'unknow...nction': {unknown} + [198; 216) 'unknow...tion()': f64 + [222; 229) '&mut &c': &mut &f64 + [227; 229) '&c': &f64 + [228; 229) 'c': f64 + "### + ); +} + +#[test] +fn infer_self() { + assert_snapshot!( + infer(r#" +struct S; + +impl S { + fn test(&self) { + self; + } + fn test2(self: &Self) { + self; + } + fn test3() -> Self { + S {} + } + fn test4() -> Self { + Self {} + } +} +"#), + @r###" + [34; 38) 'self': &S + [40; 61) '{ ... }': () + [50; 54) 'self': &S + [75; 79) 'self': &S + [88; 109) '{ ... }': () + [98; 102) 'self': &S + [133; 153) '{ ... }': S + [143; 147) 'S {}': S + [177; 200) '{ ... }': S + [187; 194) 'Self {}': S + "### + ); +} + +#[test] +fn infer_binary_op() { + assert_snapshot!( + infer(r#" +fn f(x: bool) -> i32 { + 0i32 +} + +fn test() -> bool { + let x = a && b; + let y = true || false; + let z = x == y; + let t = x != y; + let minus_forty: isize = -40isize; + let h = minus_forty <= CONST_2; + let c = f(z || y) + 5; + let d = b; + let g = minus_forty ^= i; + let ten: usize = 10; + let ten_is_eleven = ten == some_num; + + ten < 3 +} +"#), + @r###" + [6; 7) 'x': bool + [22; 34) '{ 0i32 }': i32 + [28; 32) '0i32': i32 + [54; 370) '{ ... < 3 }': bool + [64; 65) 'x': bool + [68; 69) 'a': bool + [68; 74) 'a && b': bool + [73; 74) 'b': bool + [84; 85) 'y': bool + [88; 92) 'true': bool + [88; 101) 'true || false': bool + [96; 101) 'false': bool + [111; 112) 'z': bool + [115; 116) 'x': bool + [115; 121) 'x == y': bool + [120; 121) 'y': bool + [131; 132) 't': bool + [135; 136) 'x': bool + [135; 141) 'x != y': bool + [140; 141) 'y': bool + [151; 162) 'minus_forty': isize + [172; 180) '-40isize': isize + [173; 180) '40isize': isize + [190; 191) 'h': bool + [194; 205) 'minus_forty': isize + [194; 216) 'minus_...ONST_2': bool + [209; 216) 'CONST_2': isize + [226; 227) 'c': i32 + [230; 231) 'f': fn f(bool) -> i32 + [230; 239) 'f(z || y)': i32 + [230; 243) 'f(z || y) + 5': i32 + [232; 233) 'z': bool + [232; 238) 'z || y': bool + [237; 238) 'y': bool + [242; 243) '5': i32 + [253; 254) 'd': {unknown} + [257; 258) 'b': {unknown} + [268; 269) 'g': () + [272; 283) 'minus_forty': isize + [272; 288) 'minus_...y ^= i': () + [287; 288) 'i': isize + [298; 301) 'ten': usize + [311; 313) '10': usize + [323; 336) 'ten_is_eleven': bool + [339; 342) 'ten': usize + [339; 354) 'ten == some_num': bool + [346; 354) 'some_num': usize + [361; 364) 'ten': usize + [361; 368) 'ten < 3': bool + [367; 368) '3': usize + "### + ); +} + +#[test] +fn infer_field_autoderef() { + assert_snapshot!( + infer(r#" +struct A { + b: B, +} +struct B; + +fn test1(a: A) { + let a1 = a; + a1.b; + let a2 = &a; + a2.b; + let a3 = &mut a; + a3.b; + let a4 = &&&&&&&a; + a4.b; + let a5 = &mut &&mut &&mut a; + a5.b; +} + +fn test2(a1: *const A, a2: *mut A) { + a1.b; + a2.b; +} +"#), + @r###" + [44; 45) 'a': A + [50; 213) '{ ...5.b; }': () + [60; 62) 'a1': A + [65; 66) 'a': A + [72; 74) 'a1': A + [72; 76) 'a1.b': B + [86; 88) 'a2': &A + [91; 93) '&a': &A + [92; 93) 'a': A + [99; 101) 'a2': &A + [99; 103) 'a2.b': B + [113; 115) 'a3': &mut A + [118; 124) '&mut a': &mut A + [123; 124) 'a': A + [130; 132) 'a3': &mut A + [130; 134) 'a3.b': B + [144; 146) 'a4': &&&&&&&A + [149; 157) '&&&&&&&a': &&&&&&&A + [150; 157) '&&&&&&a': &&&&&&A + [151; 157) '&&&&&a': &&&&&A + [152; 157) '&&&&a': &&&&A + [153; 157) '&&&a': &&&A + [154; 157) '&&a': &&A + [155; 157) '&a': &A + [156; 157) 'a': A + [163; 165) 'a4': &&&&&&&A + [163; 167) 'a4.b': B + [177; 179) 'a5': &mut &&mut &&mut A + [182; 200) '&mut &...&mut a': &mut &&mut &&mut A + [187; 200) '&&mut &&mut a': &&mut &&mut A + [188; 200) '&mut &&mut a': &mut &&mut A + [193; 200) '&&mut a': &&mut A + [194; 200) '&mut a': &mut A + [199; 200) 'a': A + [206; 208) 'a5': &mut &&mut &&mut A + [206; 210) 'a5.b': B + [224; 226) 'a1': *const A + [238; 240) 'a2': *mut A + [250; 273) '{ ...2.b; }': () + [256; 258) 'a1': *const A + [256; 260) 'a1.b': B + [266; 268) 'a2': *mut A + [266; 270) 'a2.b': B + "### + ); +} + +#[test] +fn infer_argument_autoderef() { + assert_snapshot!( + infer(r#" +#[lang = "deref"] +pub trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct A(T); + +impl A { + fn foo(&self) -> &T { + &self.0 + } +} + +struct B(T); + +impl Deref for B { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn test() { + let t = A::foo(&&B(B(A(42)))); +} +"#), + @r###" + [68; 72) 'self': &Self + [139; 143) 'self': &A + [151; 174) '{ ... }': &T + [161; 168) '&self.0': &T + [162; 166) 'self': &A + [162; 168) 'self.0': T + [255; 259) 'self': &B + [278; 301) '{ ... }': &T + [288; 295) '&self.0': &T + [289; 293) 'self': &B + [289; 295) 'self.0': T + [315; 353) '{ ...))); }': () + [325; 326) 't': &i32 + [329; 335) 'A::foo': fn foo(&A) -> &T + [329; 350) 'A::foo...42))))': &i32 + [336; 349) '&&B(B(A(42)))': &&B>> + [337; 349) '&B(B(A(42)))': &B>> + [338; 339) 'B': B>>(T) -> B + [338; 349) 'B(B(A(42)))': B>> + [340; 341) 'B': B>(T) -> B + [340; 348) 'B(A(42))': B> + [342; 343) 'A': A(T) -> A + [342; 347) 'A(42)': A + [344; 346) '42': i32 + "### + ); +} + +#[test] +fn infer_method_argument_autoderef() { + assert_snapshot!( + infer(r#" +#[lang = "deref"] +pub trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct A(*mut T); + +impl A { + fn foo(&self, x: &A) -> &T { + &*x.0 + } +} + +struct B(T); + +impl Deref for B { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +fn test(a: A) { + let t = A(0 as *mut _).foo(&&B(B(a))); +} +"#), + @r###" + [68; 72) 'self': &Self + [144; 148) 'self': &A + [150; 151) 'x': &A + [166; 187) '{ ... }': &T + [176; 181) '&*x.0': &T + [177; 181) '*x.0': T + [178; 179) 'x': &A + [178; 181) 'x.0': *mut T + [268; 272) 'self': &B + [291; 314) '{ ... }': &T + [301; 308) '&self.0': &T + [302; 306) 'self': &B + [302; 308) 'self.0': T + [326; 327) 'a': A + [337; 383) '{ ...))); }': () + [347; 348) 't': &i32 + [351; 352) 'A': A(*mut T) -> A + [351; 365) 'A(0 as *mut _)': A + [351; 380) 'A(0 as...B(a)))': &i32 + [353; 354) '0': i32 + [353; 364) '0 as *mut _': *mut i32 + [370; 379) '&&B(B(a))': &&B>> + [371; 379) '&B(B(a))': &B>> + [372; 373) 'B': B>>(T) -> B + [372; 379) 'B(B(a))': B>> + [374; 375) 'B': B>(T) -> B + [374; 378) 'B(a)': B> + [376; 377) 'a': A + "### + ); +} + +#[test] +fn infer_in_elseif() { + assert_snapshot!( + infer(r#" +struct Foo { field: i32 } +fn main(foo: Foo) { + if true { + + } else if false { + foo.field + } +} +"#), + @r###" + [35; 38) 'foo': Foo + [45; 109) '{ ... } }': () + [51; 107) 'if tru... }': () + [54; 58) 'true': bool + [59; 67) '{ }': () + [73; 107) 'if fal... }': () + [76; 81) 'false': bool + [82; 107) '{ ... }': i32 + [92; 95) 'foo': Foo + [92; 101) 'foo.field': i32 + "### + ) +} + +#[test] +fn infer_if_match_with_return() { + assert_snapshot!( + infer(r#" +fn foo() { + let _x1 = if true { + 1 + } else { + return; + }; + let _x2 = if true { + 2 + } else { + return + }; + let _x3 = match true { + true => 3, + _ => { + return; + } + }; + let _x4 = match true { + true => 4, + _ => return + }; +}"#), + @r###" + [10; 323) '{ ... }; }': () + [20; 23) '_x1': i32 + [26; 80) 'if tru... }': i32 + [29; 33) 'true': bool + [34; 51) '{ ... }': i32 + [44; 45) '1': i32 + [57; 80) '{ ... }': ! + [67; 73) 'return': ! + [90; 93) '_x2': i32 + [96; 149) 'if tru... }': i32 + [99; 103) 'true': bool + [104; 121) '{ ... }': i32 + [114; 115) '2': i32 + [127; 149) '{ ... }': ! + [137; 143) 'return': ! + [159; 162) '_x3': i32 + [165; 247) 'match ... }': i32 + [171; 175) 'true': bool + [186; 190) 'true': bool + [194; 195) '3': i32 + [205; 206) '_': bool + [210; 241) '{ ... }': ! + [224; 230) 'return': ! + [257; 260) '_x4': i32 + [263; 320) 'match ... }': i32 + [269; 273) 'true': bool + [284; 288) 'true': bool + [292; 293) '4': i32 + [303; 304) '_': bool + [308; 314) 'return': ! + "### + ) +} + +#[test] +fn infer_inherent_method() { + assert_snapshot!( + infer(r#" +struct A; + +impl A { + fn foo(self, x: u32) -> i32 {} +} + +mod b { + impl super::A { + fn bar(&self, x: u64) -> i64 {} + } +} + +fn test(a: A) { + a.foo(1); + (&a).bar(1); + a.bar(1); +} +"#), + @r###" + [32; 36) 'self': A + [38; 39) 'x': u32 + [53; 55) '{}': () + [103; 107) 'self': &A + [109; 110) 'x': u64 + [124; 126) '{}': () + [144; 145) 'a': A + [150; 198) '{ ...(1); }': () + [156; 157) 'a': A + [156; 164) 'a.foo(1)': i32 + [162; 163) '1': u32 + [170; 181) '(&a).bar(1)': i64 + [171; 173) '&a': &A + [172; 173) 'a': A + [179; 180) '1': u64 + [187; 188) 'a': A + [187; 195) 'a.bar(1)': i64 + [193; 194) '1': u64 + "### + ); +} + +#[test] +fn infer_inherent_method_str() { + assert_snapshot!( + infer(r#" +#[lang = "str"] +impl str { + fn foo(&self) -> i32 {} +} + +fn test() { + "foo".foo(); +} +"#), + @r###" + [40; 44) 'self': &str + [53; 55) '{}': () + [69; 89) '{ ...o(); }': () + [75; 80) '"foo"': &str + [75; 86) '"foo".foo()': i32 + "### + ); +} + +#[test] +fn infer_tuple() { + assert_snapshot!( + infer(r#" +fn test(x: &str, y: isize) { + let a: (u32, &str) = (1, "a"); + let b = (a, x); + let c = (y, x); + let d = (c, x); + let e = (1, "e"); + let f = (e, "d"); +} +"#), + @r###" + [9; 10) 'x': &str + [18; 19) 'y': isize + [28; 170) '{ ...d"); }': () + [38; 39) 'a': (u32, &str) + [55; 63) '(1, "a")': (u32, &str) + [56; 57) '1': u32 + [59; 62) '"a"': &str + [73; 74) 'b': ((u32, &str), &str) + [77; 83) '(a, x)': ((u32, &str), &str) + [78; 79) 'a': (u32, &str) + [81; 82) 'x': &str + [93; 94) 'c': (isize, &str) + [97; 103) '(y, x)': (isize, &str) + [98; 99) 'y': isize + [101; 102) 'x': &str + [113; 114) 'd': ((isize, &str), &str) + [117; 123) '(c, x)': ((isize, &str), &str) + [118; 119) 'c': (isize, &str) + [121; 122) 'x': &str + [133; 134) 'e': (i32, &str) + [137; 145) '(1, "e")': (i32, &str) + [138; 139) '1': i32 + [141; 144) '"e"': &str + [155; 156) 'f': ((i32, &str), &str) + [159; 167) '(e, "d")': ((i32, &str), &str) + [160; 161) 'e': (i32, &str) + [163; 166) '"d"': &str + "### + ); +} + +#[test] +fn infer_array() { + assert_snapshot!( + infer(r#" +fn test(x: &str, y: isize) { + let a = [x]; + let b = [a, a]; + let c = [b, b]; + + let d = [y, 1, 2, 3]; + let d = [1, y, 2, 3]; + let e = [y]; + let f = [d, d]; + let g = [e, e]; + + let h = [1, 2]; + let i = ["a", "b"]; + + let b = [a, ["b"]]; + let x: [u8; 0] = []; +} +"#), + @r###" + [9; 10) 'x': &str + [18; 19) 'y': isize + [28; 293) '{ ... []; }': () + [38; 39) 'a': [&str;_] + [42; 45) '[x]': [&str;_] + [43; 44) 'x': &str + [55; 56) 'b': [[&str;_];_] + [59; 65) '[a, a]': [[&str;_];_] + [60; 61) 'a': [&str;_] + [63; 64) 'a': [&str;_] + [75; 76) 'c': [[[&str;_];_];_] + [79; 85) '[b, b]': [[[&str;_];_];_] + [80; 81) 'b': [[&str;_];_] + [83; 84) 'b': [[&str;_];_] + [96; 97) 'd': [isize;_] + [100; 112) '[y, 1, 2, 3]': [isize;_] + [101; 102) 'y': isize + [104; 105) '1': isize + [107; 108) '2': isize + [110; 111) '3': isize + [122; 123) 'd': [isize;_] + [126; 138) '[1, y, 2, 3]': [isize;_] + [127; 128) '1': isize + [130; 131) 'y': isize + [133; 134) '2': isize + [136; 137) '3': isize + [148; 149) 'e': [isize;_] + [152; 155) '[y]': [isize;_] + [153; 154) 'y': isize + [165; 166) 'f': [[isize;_];_] + [169; 175) '[d, d]': [[isize;_];_] + [170; 171) 'd': [isize;_] + [173; 174) 'd': [isize;_] + [185; 186) 'g': [[isize;_];_] + [189; 195) '[e, e]': [[isize;_];_] + [190; 191) 'e': [isize;_] + [193; 194) 'e': [isize;_] + [206; 207) 'h': [i32;_] + [210; 216) '[1, 2]': [i32;_] + [211; 212) '1': i32 + [214; 215) '2': i32 + [226; 227) 'i': [&str;_] + [230; 240) '["a", "b"]': [&str;_] + [231; 234) '"a"': &str + [236; 239) '"b"': &str + [251; 252) 'b': [[&str;_];_] + [255; 265) '[a, ["b"]]': [[&str;_];_] + [256; 257) 'a': [&str;_] + [259; 264) '["b"]': [&str;_] + [260; 263) '"b"': &str + [275; 276) 'x': [u8;_] + [288; 290) '[]': [u8;_] + "### + ); +} + +#[test] +fn infer_struct_generics() { + assert_snapshot!( + infer(r#" +struct A { + x: T, +} + +fn test(a1: A, i: i32) { + a1.x; + let a2 = A { x: i }; + a2.x; + let a3 = A:: { x: 1 }; + a3.x; +} +"#), + @r###" + [36; 38) 'a1': A + [48; 49) 'i': i32 + [56; 147) '{ ...3.x; }': () + [62; 64) 'a1': A + [62; 66) 'a1.x': u32 + [76; 78) 'a2': A + [81; 91) 'A { x: i }': A + [88; 89) 'i': i32 + [97; 99) 'a2': A + [97; 101) 'a2.x': i32 + [111; 113) 'a3': A + [116; 134) 'A:: + [131; 132) '1': i128 + [140; 142) 'a3': A + [140; 144) 'a3.x': i128 + "### + ); +} + +#[test] +fn infer_tuple_struct_generics() { + assert_snapshot!( + infer(r#" +struct A(T); +enum Option { Some(T), None } +use Option::*; + +fn test() { + A(42); + A(42u128); + Some("x"); + Option::Some("x"); + None; + let x: Option = None; +} +"#), + @r###" + [76; 184) '{ ...one; }': () + [82; 83) 'A': A(T) -> A + [82; 87) 'A(42)': A + [84; 86) '42': i32 + [93; 94) 'A': A(T) -> A + [93; 102) 'A(42u128)': A + [95; 101) '42u128': u128 + [108; 112) 'Some': Some<&str>(T) -> Option + [108; 117) 'Some("x")': Option<&str> + [113; 116) '"x"': &str + [123; 135) 'Option::Some': Some<&str>(T) -> Option + [123; 140) 'Option...e("x")': Option<&str> + [136; 139) '"x"': &str + [146; 150) 'None': Option<{unknown}> + [160; 161) 'x': Option + [177; 181) 'None': Option + "### + ); +} + +#[test] +fn infer_function_generics() { + assert_snapshot!( + infer(r#" +fn id(t: T) -> T { t } + +fn test() { + id(1u32); + id::(1); + let x: u64 = id(1); +} +"#), + @r###" + [10; 11) 't': T + [21; 26) '{ t }': T + [23; 24) 't': T + [38; 98) '{ ...(1); }': () + [44; 46) 'id': fn id(T) -> T + [44; 52) 'id(1u32)': u32 + [47; 51) '1u32': u32 + [58; 68) 'id::': fn id(T) -> T + [58; 71) 'id::(1)': i128 + [69; 70) '1': i128 + [81; 82) 'x': u64 + [90; 92) 'id': fn id(T) -> T + [90; 95) 'id(1)': u64 + [93; 94) '1': u64 + "### + ); +} + +#[test] +fn infer_impl_generics() { + assert_snapshot!( + infer(r#" +struct A { + x: T1, + y: T2, +} +impl A { + fn x(self) -> X { + self.x + } + fn y(self) -> Y { + self.y + } + fn z(self, t: T) -> (X, Y, T) { + (self.x, self.y, t) + } +} + +fn test() -> i128 { + let a = A { x: 1u64, y: 1i64 }; + a.x(); + a.y(); + a.z(1i128); + a.z::(1); +} +"#), + @r###" + [74; 78) 'self': A + [85; 107) '{ ... }': X + [95; 99) 'self': A + [95; 101) 'self.x': X + [117; 121) 'self': A + [128; 150) '{ ... }': Y + [138; 142) 'self': A + [138; 144) 'self.y': Y + [163; 167) 'self': A + [169; 170) 't': T + [188; 223) '{ ... }': (X, Y, T) + [198; 217) '(self.....y, t)': (X, Y, T) + [199; 203) 'self': A + [199; 205) 'self.x': X + [207; 211) 'self': A + [207; 213) 'self.y': Y + [215; 216) 't': T + [245; 342) '{ ...(1); }': () + [255; 256) 'a': A + [259; 281) 'A { x:...1i64 }': A + [266; 270) '1u64': u64 + [275; 279) '1i64': i64 + [287; 288) 'a': A + [287; 292) 'a.x()': u64 + [298; 299) 'a': A + [298; 303) 'a.y()': i64 + [309; 310) 'a': A + [309; 319) 'a.z(1i128)': (u64, i64, i128) + [313; 318) '1i128': i128 + [325; 326) 'a': A + [325; 339) 'a.z::(1)': (u64, i64, u128) + [337; 338) '1': u128 + "### + ); +} + +#[test] +fn infer_impl_generics_with_autoderef() { + assert_snapshot!( + infer(r#" +enum Option { + Some(T), + None, +} +impl Option { + fn as_ref(&self) -> Option<&T> {} +} +fn test(o: Option) { + (&o).as_ref(); + o.as_ref(); +} +"#), + @r###" + [78; 82) 'self': &Option + [98; 100) '{}': () + [111; 112) 'o': Option + [127; 165) '{ ...f(); }': () + [133; 146) '(&o).as_ref()': Option<&u32> + [134; 136) '&o': &Option + [135; 136) 'o': Option + [152; 153) 'o': Option + [152; 162) 'o.as_ref()': Option<&u32> + "### + ); +} + +#[test] +fn infer_generic_chain() { + assert_snapshot!( + infer(r#" +struct A { + x: T, +} +impl A { + fn x(self) -> T2 { + self.x + } +} +fn id(t: T) -> T { t } + +fn test() -> i128 { + let x = 1; + let y = id(x); + let a = A { x: id(y) }; + let z = id(a.x); + let b = A { x: z }; + b.x() +} +"#), + @r###" + [53; 57) 'self': A + [65; 87) '{ ... }': T2 + [75; 79) 'self': A + [75; 81) 'self.x': T2 + [99; 100) 't': T + [110; 115) '{ t }': T + [112; 113) 't': T + [135; 261) '{ ....x() }': i128 + [146; 147) 'x': i128 + [150; 151) '1': i128 + [162; 163) 'y': i128 + [166; 168) 'id': fn id(T) -> T + [166; 171) 'id(x)': i128 + [169; 170) 'x': i128 + [182; 183) 'a': A + [186; 200) 'A { x: id(y) }': A + [193; 195) 'id': fn id(T) -> T + [193; 198) 'id(y)': i128 + [196; 197) 'y': i128 + [211; 212) 'z': i128 + [215; 217) 'id': fn id(T) -> T + [215; 222) 'id(a.x)': i128 + [218; 219) 'a': A + [218; 221) 'a.x': i128 + [233; 234) 'b': A + [237; 247) 'A { x: z }': A + [244; 245) 'z': i128 + [254; 255) 'b': A + [254; 259) 'b.x()': i128 + "### + ); +} + +#[test] +fn infer_associated_const() { + assert_snapshot!( + infer(r#" +struct Struct; + +impl Struct { + const FOO: u32 = 1; +} + +enum Enum {} + +impl Enum { + const BAR: u32 = 2; +} + +trait Trait { + const ID: u32; +} + +struct TraitTest; + +impl Trait for TraitTest { + const ID: u32 = 5; +} + +fn test() { + let x = Struct::FOO; + let y = Enum::BAR; + let z = TraitTest::ID; +} +"#), + @r###" + [52; 53) '1': u32 + [105; 106) '2': u32 + [213; 214) '5': u32 + [229; 307) '{ ...:ID; }': () + [239; 240) 'x': u32 + [243; 254) 'Struct::FOO': u32 + [264; 265) 'y': u32 + [268; 277) 'Enum::BAR': u32 + [287; 288) 'z': u32 + [291; 304) 'TraitTest::ID': u32 + "### + ); +} + +#[test] +fn infer_type_alias() { + assert_snapshot!( + infer(r#" +struct A { x: X, y: Y } +type Foo = A; +type Bar = A; +type Baz = A; +fn test(x: Foo, y: Bar<&str>, z: Baz) { + x.x; + x.y; + y.x; + y.y; + z.x; + z.y; +} +"#), + @r###" + [116; 117) 'x': A + [124; 125) 'y': A<&str, u128> + [138; 139) 'z': A + [154; 211) '{ ...z.y; }': () + [160; 161) 'x': A + [160; 163) 'x.x': u32 + [169; 170) 'x': A + [169; 172) 'x.y': i128 + [178; 179) 'y': A<&str, u128> + [178; 181) 'y.x': &str + [187; 188) 'y': A<&str, u128> + [187; 190) 'y.y': u128 + [196; 197) 'z': A + [196; 199) 'z.x': u8 + [205; 206) 'z': A + [205; 208) 'z.y': i8 + "### + ) +} + +#[test] +fn recursive_type_alias() { + assert_snapshot!( + infer(r#" +struct A {} +type Foo = Foo; +type Bar = A; +fn test(x: Foo) {} +"#), + @r###" + [59; 60) 'x': {unknown} + [67; 69) '{}': () + "### + ) +} + +#[test] +fn infer_type_param() { + assert_snapshot!( + infer(r#" +fn id(x: T) -> T { + x +} + +fn clone(x: &T) -> T { + *x +} + +fn test() { + let y = 10u32; + id(y); + let x: bool = clone(z); + id::(1); +} +"#), + @r###" + [10; 11) 'x': T + [21; 30) '{ x }': T + [27; 28) 'x': T + [44; 45) 'x': &T + [56; 66) '{ *x }': T + [62; 64) '*x': T + [63; 64) 'x': &T + [78; 158) '{ ...(1); }': () + [88; 89) 'y': u32 + [92; 97) '10u32': u32 + [103; 105) 'id': fn id(T) -> T + [103; 108) 'id(y)': u32 + [106; 107) 'y': u32 + [118; 119) 'x': bool + [128; 133) 'clone': fn clone(&T) -> T + [128; 136) 'clone(z)': bool + [134; 135) 'z': &bool + [142; 152) 'id::': fn id(T) -> T + [142; 155) 'id::(1)': i128 + [153; 154) '1': i128 + "### + ); +} + +#[test] +fn infer_const() { + assert_snapshot!( + infer(r#" +struct Foo; +impl Foo { const ASSOC_CONST: u32 = 0; } +const GLOBAL_CONST: u32 = 101; +fn test() { + const LOCAL_CONST: u32 = 99; + let x = LOCAL_CONST; + let z = GLOBAL_CONST; + let id = Foo::ASSOC_CONST; +} +"#), + @r###" + [49; 50) '0': u32 + [80; 83) '101': u32 + [95; 213) '{ ...NST; }': () + [138; 139) 'x': {unknown} + [142; 153) 'LOCAL_CONST': {unknown} + [163; 164) 'z': u32 + [167; 179) 'GLOBAL_CONST': u32 + [189; 191) 'id': u32 + [194; 210) 'Foo::A..._CONST': u32 + "### + ); +} + +#[test] +fn infer_static() { + assert_snapshot!( + infer(r#" +static GLOBAL_STATIC: u32 = 101; +static mut GLOBAL_STATIC_MUT: u32 = 101; +fn test() { + static LOCAL_STATIC: u32 = 99; + static mut LOCAL_STATIC_MUT: u32 = 99; + let x = LOCAL_STATIC; + let y = LOCAL_STATIC_MUT; + let z = GLOBAL_STATIC; + let w = GLOBAL_STATIC_MUT; +} +"#), + @r###" + [29; 32) '101': u32 + [70; 73) '101': u32 + [85; 280) '{ ...MUT; }': () + [173; 174) 'x': {unknown} + [177; 189) 'LOCAL_STATIC': {unknown} + [199; 200) 'y': {unknown} + [203; 219) 'LOCAL_...IC_MUT': {unknown} + [229; 230) 'z': u32 + [233; 246) 'GLOBAL_STATIC': u32 + [256; 257) 'w': u32 + [260; 277) 'GLOBAL...IC_MUT': u32 + "### + ); +} + +#[test] +fn shadowing_primitive() { + let t = type_at( + r#" +//- /main.rs +struct i32; +struct Foo; + +impl i32 { fn foo(&self) -> Foo { Foo } } + +fn main() { + let x: i32 = i32; + x.foo()<|>; +}"#, + ); + assert_eq!(t, "Foo"); +} + +#[test] +fn not_shadowing_primitive_by_module() { + let t = type_at( + r#" +//- /str.rs +fn foo() {} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + foo()<|>; +}"#, + ); + assert_eq!(t, "&str"); +} + +#[test] +fn not_shadowing_module_by_primitive() { + let t = type_at( + r#" +//- /str.rs +fn foo() -> u32 {0} + +//- /main.rs +mod str; +fn foo() -> &'static str { "" } + +fn main() { + str::foo()<|>; +}"#, + ); + assert_eq!(t, "u32"); +} diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs new file mode 100644 index 0000000000..93c5f9a15a --- /dev/null +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -0,0 +1,1424 @@ +use super::{infer, type_at, type_at_pos}; +use crate::test_db::TestDB; +use insta::assert_snapshot; +use ra_db::fixture::WithFixture; + +#[test] +fn infer_await() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +struct IntFuture; + +impl Future for IntFuture { + type Output = u64; +} + +fn test() { + let r = IntFuture; + let v = r.await; + v<|>; +} + +//- /std.rs crate:std +#[prelude_import] use future::*; +mod future { + trait Future { + type Output; + } +} + +"#, + ); + assert_eq!("u64", type_at_pos(&db, pos)); +} + +#[test] +fn infer_try() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +fn test() { + let r: Result = Result::Ok(1); + let v = r?; + v<|>; +} + +//- /std.rs crate:std + +#[prelude_import] use ops::*; +mod ops { + trait Try { + type Ok; + type Error; + } +} + +#[prelude_import] use result::*; +mod result { + enum Result { + Ok(O), + Err(E) + } + + impl crate::ops::Try for Result { + type Ok = O; + type Error = E; + } +} + +"#, + ); + assert_eq!("i32", type_at_pos(&db, pos)); +} + +#[test] +fn infer_for_loop() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +use std::collections::Vec; + +fn test() { + let v = Vec::new(); + v.push("foo"); + for x in v { + x<|>; + } +} + +//- /std.rs crate:std + +#[prelude_import] use iter::*; +mod iter { + trait IntoIterator { + type Item; + } +} + +mod collections { + struct Vec {} + impl Vec { + fn new() -> Self { Vec {} } + fn push(&mut self, t: T) { } + } + + impl crate::iter::IntoIterator for Vec { + type Item=T; + } +} +"#, + ); + assert_eq!("&str", type_at_pos(&db, pos)); +} + +#[test] +fn infer_from_bound_1() { + assert_snapshot!( + infer(r#" +trait Trait {} +struct S(T); +impl Trait for S {} +fn foo>(t: T) {} +fn test() { + let s = S(unknown); + foo(s); +} +"#), + @r###" + [86; 87) 't': T + [92; 94) '{}': () + [105; 144) '{ ...(s); }': () + [115; 116) 's': S + [119; 120) 'S': S(T) -> S + [119; 129) 'S(unknown)': S + [121; 128) 'unknown': u32 + [135; 138) 'foo': fn foo>(T) -> () + [135; 141) 'foo(s)': () + [139; 140) 's': S + "### + ); +} + +#[test] +fn infer_from_bound_2() { + assert_snapshot!( + infer(r#" +trait Trait {} +struct S(T); +impl Trait for S {} +fn foo>(t: T) -> U {} +fn test() { + let s = S(unknown); + let x: u32 = foo(s); +} +"#), + @r###" + [87; 88) 't': T + [98; 100) '{}': () + [111; 163) '{ ...(s); }': () + [121; 122) 's': S + [125; 126) 'S': S(T) -> S + [125; 135) 'S(unknown)': S + [127; 134) 'unknown': u32 + [145; 146) 'x': u32 + [154; 157) 'foo': fn foo>(T) -> U + [154; 160) 'foo(s)': u32 + [158; 159) 's': S + "### + ); +} + +#[test] +fn infer_project_associated_type() { + // y, z, a don't yet work because of https://github.com/rust-lang/chalk/issues/234 + assert_snapshot!( + infer(r#" +trait Iterable { + type Item; +} +struct S; +impl Iterable for S { type Item = u32; } +fn test() { + let x: ::Item = 1; + let y: ::Item = no_matter; + let z: T::Item = no_matter; + let a: ::Item = no_matter; +} +"#), + @r###" + [108; 261) '{ ...ter; }': () + [118; 119) 'x': u32 + [145; 146) '1': u32 + [156; 157) 'y': {unknown} + [183; 192) 'no_matter': {unknown} + [202; 203) 'z': {unknown} + [215; 224) 'no_matter': {unknown} + [234; 235) 'a': {unknown} + [249; 258) 'no_matter': {unknown} + "### + ); +} + +#[test] +fn infer_return_associated_type() { + assert_snapshot!( + infer(r#" +trait Iterable { + type Item; +} +struct S; +impl Iterable for S { type Item = u32; } +fn foo1(t: T) -> T::Item {} +fn foo2(t: T) -> ::Item {} +fn foo3(t: T) -> ::Item {} +fn test() { + let x = foo1(S); + let y = foo2(S); + let z = foo3(S); +} +"#), + @r###" + [106; 107) 't': T + [123; 125) '{}': () + [147; 148) 't': T + [178; 180) '{}': () + [202; 203) 't': T + [221; 223) '{}': () + [234; 300) '{ ...(S); }': () + [244; 245) 'x': u32 + [248; 252) 'foo1': fn foo1(T) -> ::Item + [248; 255) 'foo1(S)': u32 + [253; 254) 'S': S + [265; 266) 'y': u32 + [269; 273) 'foo2': fn foo2(T) -> ::Item + [269; 276) 'foo2(S)': u32 + [274; 275) 'S': S + [286; 287) 'z': u32 + [290; 294) 'foo3': fn foo3(T) -> ::Item + [290; 297) 'foo3(S)': u32 + [295; 296) 'S': S + "### + ); +} + +#[test] +fn infer_associated_type_bound() { + assert_snapshot!( + infer(r#" +trait Iterable { + type Item; +} +fn test>() { + let y: T::Item = unknown; +} +"#), + @r###" + [67; 100) '{ ...own; }': () + [77; 78) 'y': {unknown} + [90; 97) 'unknown': {unknown} + "### + ); +} + +#[test] +fn infer_const_body() { + assert_snapshot!( + infer(r#" +const A: u32 = 1 + 1; +static B: u64 = { let x = 1; x }; +"#), + @r###" + [16; 17) '1': u32 + [16; 21) '1 + 1': u32 + [20; 21) '1': u32 + [39; 55) '{ let ...1; x }': u64 + [45; 46) 'x': u64 + [49; 50) '1': u64 + [52; 53) 'x': u64 + "### + ); +} + +#[test] +fn tuple_struct_fields() { + assert_snapshot!( + infer(r#" +struct S(i32, u64); +fn test() -> u64 { + let a = S(4, 6); + let b = a.0; + a.1 +} +"#), + @r###" + [38; 87) '{ ... a.1 }': u64 + [48; 49) 'a': S + [52; 53) 'S': S(i32, u64) -> S + [52; 59) 'S(4, 6)': S + [54; 55) '4': i32 + [57; 58) '6': u64 + [69; 70) 'b': i32 + [73; 74) 'a': S + [73; 76) 'a.0': i32 + [82; 83) 'a': S + [82; 85) 'a.1': u64 + "### + ); +} + +#[test] +fn tuple_struct_with_fn() { + assert_snapshot!( + infer(r#" +struct S(fn(u32) -> u64); +fn test() -> u64 { + let a = S(|i| 2*i); + let b = a.0(4); + a.0(2) +} +"#), + @r###" + [44; 102) '{ ...0(2) }': u64 + [54; 55) 'a': S + [58; 59) 'S': S(fn(u32) -> u64) -> S + [58; 68) 'S(|i| 2*i)': S + [60; 67) '|i| 2*i': |i32| -> i32 + [61; 62) 'i': i32 + [64; 65) '2': i32 + [64; 67) '2*i': i32 + [66; 67) 'i': i32 + [78; 79) 'b': u64 + [82; 83) 'a': S + [82; 85) 'a.0': fn(u32) -> u64 + [82; 88) 'a.0(4)': u64 + [86; 87) '4': u32 + [94; 95) 'a': S + [94; 97) 'a.0': fn(u32) -> u64 + [94; 100) 'a.0(2)': u64 + [98; 99) '2': u32 + "### + ); +} + +#[test] +fn indexing_arrays() { + assert_snapshot!( + infer("fn main() { &mut [9][2]; }"), + @r###" + [10; 26) '{ &mut...[2]; }': () + [12; 23) '&mut [9][2]': &mut {unknown} + [17; 20) '[9]': [i32;_] + [17; 23) '[9][2]': {unknown} + [18; 19) '9': i32 + [21; 22) '2': i32 + "### + ) +} + +#[test] +fn deref_trait() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct Arc; +impl Deref for Arc { + type Target = T; +} + +struct S; +impl S { + fn foo(&self) -> u128 {} +} + +fn test(s: Arc) { + (*s, s.foo())<|>; +} +"#, + ); + assert_eq!(t, "(S, u128)"); +} + +#[test] +fn deref_trait_with_inference_var() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct Arc; +fn new_arc() -> Arc {} +impl Deref for Arc { + type Target = T; +} + +struct S; +fn foo(a: Arc) {} + +fn test() { + let a = new_arc(); + let b = (*a)<|>; + foo(a); +} +"#, + ); + assert_eq!(t, "S"); +} + +#[test] +fn deref_trait_infinite_recursion() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct S; + +impl Deref for S { + type Target = S; +} + +fn test(s: S) { + s.foo()<|>; +} +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn deref_trait_with_question_mark_size() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; + fn deref(&self) -> &Self::Target; +} + +struct Arc; +impl Deref for Arc { + type Target = T; +} + +struct S; +impl S { + fn foo(&self) -> u128 {} +} + +fn test(s: Arc) { + (*s, s.foo())<|>; +} +"#, + ); + assert_eq!(t, "(S, u128)"); +} + +#[test] +fn obligation_from_function_clause() { + let t = type_at( + r#" +//- /main.rs +struct S; + +trait Trait {} +impl Trait for S {} + +fn foo, U>(t: T) -> U {} + +fn test(s: S) { + foo(s)<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + +#[test] +fn obligation_from_method_clause() { + let t = type_at( + r#" +//- /main.rs +struct S; + +trait Trait {} +impl Trait for S {} + +struct O; +impl O { + fn foo, U>(&self, t: T) -> U {} +} + +fn test() { + O.foo(S)<|>; +} +"#, + ); + assert_eq!(t, "isize"); +} + +#[test] +fn obligation_from_self_method_clause() { + let t = type_at( + r#" +//- /main.rs +struct S; + +trait Trait {} +impl Trait for S {} + +impl S { + fn foo(&self) -> U where Self: Trait {} +} + +fn test() { + S.foo()<|>; +} +"#, + ); + assert_eq!(t, "i64"); +} + +#[test] +fn obligation_from_impl_clause() { + let t = type_at( + r#" +//- /main.rs +struct S; + +trait Trait {} +impl Trait<&str> for S {} + +struct O; +impl> O { + fn foo(&self) -> U {} +} + +fn test(o: O) { + o.foo()<|>; +} +"#, + ); + assert_eq!(t, "&str"); +} + +#[test] +fn generic_param_env_1() { + let t = type_at( + r#" +//- /main.rs +trait Clone {} +trait Trait { fn foo(self) -> u128; } +struct S; +impl Clone for S {} +impl Trait for T where T: Clone {} +fn test(t: T) { t.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn generic_param_env_1_not_met() { + let t = type_at( + r#" +//- /main.rs +trait Clone {} +trait Trait { fn foo(self) -> u128; } +struct S; +impl Clone for S {} +impl Trait for T where T: Clone {} +fn test(t: T) { t.foo()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn generic_param_env_2() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for S {} +fn test(t: T) { t.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + +#[test] +fn generic_param_env_2_not_met() { + let t = type_at( + r#" +//- /main.rs +trait Trait { fn foo(self) -> u128; } +struct S; +impl Trait for S {} +fn test(t: T) { t.foo()<|>; } +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn generic_param_env_deref() { + let t = type_at( + r#" +//- /main.rs +#[lang = "deref"] +trait Deref { + type Target; +} +trait Trait {} +impl Deref for T where T: Trait { + type Target = i128; +} +fn test(t: T) { (*t)<|>; } +"#, + ); + assert_eq!(t, "i128"); +} + +#[test] +fn associated_type_placeholder() { + let t = type_at( + r#" +//- /main.rs +pub trait ApplyL { + type Out; +} + +pub struct RefMutL; + +impl ApplyL for RefMutL { + type Out = ::Out; +} + +fn test() { + let y: as ApplyL>::Out = no_matter; + y<|>; +} +"#, + ); + // inside the generic function, the associated type gets normalized to a placeholder `ApplL::Out` [https://rust-lang.github.io/rustc-guide/traits/associated-types.html#placeholder-associated-types]. + // FIXME: fix type parameter names going missing when going through Chalk + assert_eq!(t, "ApplyL::Out<[missing name]>"); +} + +#[test] +fn associated_type_placeholder_2() { + let t = type_at( + r#" +//- /main.rs +pub trait ApplyL { + type Out; +} +fn foo(t: T) -> ::Out; + +fn test(t: T) { + let y = foo(t); + y<|>; +} +"#, + ); + // FIXME here Chalk doesn't normalize the type to a placeholder. I think we + // need to add a rule like Normalize(::Out -> ApplyL::Out) + // to the trait env ourselves here; probably Chalk can't do this by itself. + // assert_eq!(t, "ApplyL::Out<[missing name]>"); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn impl_trait() { + assert_snapshot!( + infer(r#" +trait Trait { + fn foo(&self) -> T; + fn foo2(&self) -> i64; +} +fn bar() -> impl Trait {} + +fn test(x: impl Trait, y: &impl Trait) { + x; + y; + let z = bar(); + x.foo(); + y.foo(); + z.foo(); + x.foo2(); + y.foo2(); + z.foo2(); +} +"#), + @r###" + [30; 34) 'self': &Self + [55; 59) 'self': &Self + [99; 101) '{}': () + [111; 112) 'x': impl Trait + [131; 132) 'y': &impl Trait + [152; 269) '{ ...2(); }': () + [158; 159) 'x': impl Trait + [165; 166) 'y': &impl Trait + [176; 177) 'z': impl Trait + [180; 183) 'bar': fn bar() -> impl Trait + [180; 185) 'bar()': impl Trait + [191; 192) 'x': impl Trait + [191; 198) 'x.foo()': u64 + [204; 205) 'y': &impl Trait + [204; 211) 'y.foo()': u64 + [217; 218) 'z': impl Trait + [217; 224) 'z.foo()': u64 + [230; 231) 'x': impl Trait + [230; 238) 'x.foo2()': i64 + [244; 245) 'y': &impl Trait + [244; 252) 'y.foo2()': i64 + [258; 259) 'z': impl Trait + [258; 266) 'z.foo2()': i64 + "### + ); +} + +#[test] +fn dyn_trait() { + assert_snapshot!( + infer(r#" +trait Trait { + fn foo(&self) -> T; + fn foo2(&self) -> i64; +} +fn bar() -> dyn Trait {} + +fn test(x: dyn Trait, y: &dyn Trait) { + x; + y; + let z = bar(); + x.foo(); + y.foo(); + z.foo(); + x.foo2(); + y.foo2(); + z.foo2(); +} +"#), + @r###" + [30; 34) 'self': &Self + [55; 59) 'self': &Self + [98; 100) '{}': () + [110; 111) 'x': dyn Trait + [129; 130) 'y': &dyn Trait + [149; 266) '{ ...2(); }': () + [155; 156) 'x': dyn Trait + [162; 163) 'y': &dyn Trait + [173; 174) 'z': dyn Trait + [177; 180) 'bar': fn bar() -> dyn Trait + [177; 182) 'bar()': dyn Trait + [188; 189) 'x': dyn Trait + [188; 195) 'x.foo()': u64 + [201; 202) 'y': &dyn Trait + [201; 208) 'y.foo()': u64 + [214; 215) 'z': dyn Trait + [214; 221) 'z.foo()': u64 + [227; 228) 'x': dyn Trait + [227; 235) 'x.foo2()': i64 + [241; 242) 'y': &dyn Trait + [241; 249) 'y.foo2()': i64 + [255; 256) 'z': dyn Trait + [255; 263) 'z.foo2()': i64 + "### + ); +} + +#[test] +fn dyn_trait_bare() { + assert_snapshot!( + infer(r#" +trait Trait { + fn foo(&self) -> u64; +} +fn bar() -> Trait {} + +fn test(x: Trait, y: &Trait) -> u64 { + x; + y; + let z = bar(); + x.foo(); + y.foo(); + z.foo(); +} +"#), + @r###" + [27; 31) 'self': &Self + [61; 63) '{}': () + [73; 74) 'x': dyn Trait + [83; 84) 'y': &dyn Trait + [101; 176) '{ ...o(); }': () + [107; 108) 'x': dyn Trait + [114; 115) 'y': &dyn Trait + [125; 126) 'z': dyn Trait + [129; 132) 'bar': fn bar() -> dyn Trait + [129; 134) 'bar()': dyn Trait + [140; 141) 'x': dyn Trait + [140; 147) 'x.foo()': u64 + [153; 154) 'y': &dyn Trait + [153; 160) 'y.foo()': u64 + [166; 167) 'z': dyn Trait + [166; 173) 'z.foo()': u64 + "### + ); +} + +#[test] +fn weird_bounds() { + assert_snapshot!( + infer(r#" +trait Trait {} +fn test() { + let a: impl Trait + 'lifetime = foo; + let b: impl 'lifetime = foo; + let b: impl (Trait) = foo; + let b: impl ('lifetime) = foo; + let d: impl ?Sized = foo; + let e: impl Trait + ?Sized = foo; +} +"#), + @r###" + [26; 237) '{ ...foo; }': () + [36; 37) 'a': impl Trait + {error} + [64; 67) 'foo': impl Trait + {error} + [77; 78) 'b': impl {error} + [97; 100) 'foo': impl {error} + [110; 111) 'b': impl Trait + [128; 131) 'foo': impl Trait + [141; 142) 'b': impl {error} + [163; 166) 'foo': impl {error} + [176; 177) 'd': impl {error} + [193; 196) 'foo': impl {error} + [206; 207) 'e': impl Trait + {error} + [231; 234) 'foo': impl Trait + {error} + "### + ); +} + +#[test] +fn assoc_type_bindings() { + assert_snapshot!( + infer(r#" +trait Trait { + type Type; +} + +fn get(t: T) -> ::Type {} +fn get2>(t: T) -> U {} +fn set>(t: T) -> T {t} + +struct S; +impl Trait for S { type Type = T; } + +fn test>(x: T, y: impl Trait) { + get(x); + get2(x); + get(y); + get2(y); + get(set(S)); + get2(set(S)); + get2(S::); +} +"#), + @r###" + [50; 51) 't': T + [78; 80) '{}': () + [112; 113) 't': T + [123; 125) '{}': () + [155; 156) 't': T + [166; 169) '{t}': T + [167; 168) 't': T + [257; 258) 'x': T + [263; 264) 'y': impl Trait + [290; 398) '{ ...r>); }': () + [296; 299) 'get': fn get(T) -> ::Type + [296; 302) 'get(x)': {unknown} + [300; 301) 'x': T + [308; 312) 'get2': fn get2<{unknown}, T>(T) -> U + [308; 315) 'get2(x)': {unknown} + [313; 314) 'x': T + [321; 324) 'get': fn get>(T) -> ::Type + [321; 327) 'get(y)': {unknown} + [325; 326) 'y': impl Trait + [333; 337) 'get2': fn get2<{unknown}, impl Trait>(T) -> U + [333; 340) 'get2(y)': {unknown} + [338; 339) 'y': impl Trait + [346; 349) 'get': fn get>(T) -> ::Type + [346; 357) 'get(set(S))': u64 + [350; 353) 'set': fn set>(T) -> T + [350; 356) 'set(S)': S + [354; 355) 'S': S + [363; 367) 'get2': fn get2>(T) -> U + [363; 375) 'get2(set(S))': u64 + [368; 371) 'set': fn set>(T) -> T + [368; 374) 'set(S)': S + [372; 373) 'S': S + [381; 385) 'get2': fn get2>(T) -> U + [381; 395) 'get2(S::)': str + [386; 394) 'S::': S + "### + ); +} + +#[test] +fn impl_trait_assoc_binding_projection_bug() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std +pub trait Language { + type Kind; +} +pub enum RustLanguage {} +impl Language for RustLanguage { + type Kind = SyntaxKind; +} +struct SyntaxNode {} +fn foo() -> impl Iterator> {} + +trait Clone { + fn clone(&self) -> Self; +} + +fn api_walkthrough() { + for node in foo() { + node.clone()<|>; + } +} + +//- /std.rs crate:std +#[prelude_import] use iter::*; +mod iter { + trait IntoIterator { + type Item; + } + trait Iterator { + type Item; + } + impl IntoIterator for T { + type Item = ::Item; + } +} +"#, + ); + assert_eq!("{unknown}", type_at_pos(&db, pos)); +} + +#[test] +fn projection_eq_within_chalk() { + // std::env::set_var("CHALK_DEBUG", "1"); + assert_snapshot!( + infer(r#" +trait Trait1 { + type Type; +} +trait Trait2 { + fn foo(self) -> T; +} +impl Trait2 for U where U: Trait1 {} + +fn test>(x: T) { + x.foo(); +} +"#), + @r###" + [62; 66) 'self': Self + [164; 165) 'x': T + [170; 186) '{ ...o(); }': () + [176; 177) 'x': T + [176; 183) 'x.foo()': {unknown} + "### + ); +} + +#[test] +fn where_clause_trait_in_scope_for_method_resolution() { + let t = type_at( + r#" +//- /main.rs +mod foo { + trait Trait { + fn foo(&self) -> u32 {} + } +} + +fn test(x: T) { + x.foo()<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + +#[test] +fn super_trait_method_resolution() { + assert_snapshot!( + infer(r#" +mod foo { + trait SuperTrait { + fn foo(&self) -> u32 {} + } +} +trait Trait1: foo::SuperTrait {} +trait Trait2 where Self: foo::SuperTrait {} + +fn test(x: T, y: U) { + x.foo(); + y.foo(); +} +"#), + @r###" + [50; 54) 'self': &Self + [63; 65) '{}': () + [182; 183) 'x': T + [188; 189) 'y': U + [194; 223) '{ ...o(); }': () + [200; 201) 'x': T + [200; 207) 'x.foo()': u32 + [213; 214) 'y': U + [213; 220) 'y.foo()': u32 + "### + ); +} + +#[test] +fn super_trait_cycle() { + // This just needs to not crash + assert_snapshot!( + infer(r#" +trait A: B {} +trait B: A {} + +fn test(x: T) { + x.foo(); +} +"#), + @r###" + [44; 45) 'x': T + [50; 66) '{ ...o(); }': () + [56; 57) 'x': T + [56; 63) 'x.foo()': {unknown} + "### + ); +} + +#[test] +fn super_trait_assoc_type_bounds() { + assert_snapshot!( + infer(r#" +trait SuperTrait { type Type; } +trait Trait where Self: SuperTrait {} + +fn get2>(t: T) -> U {} +fn set>(t: T) -> T {t} + +struct S; +impl SuperTrait for S { type Type = T; } +impl Trait for S {} + +fn test() { + get2(set(S)); +} +"#), + @r###" + [103; 104) 't': T + [114; 116) '{}': () + [146; 147) 't': T + [157; 160) '{t}': T + [158; 159) 't': T + [259; 280) '{ ...S)); }': () + [265; 269) 'get2': fn get2>(T) -> U + [265; 277) 'get2(set(S))': u64 + [270; 273) 'set': fn set>(T) -> T + [270; 276) 'set(S)': S + [274; 275) 'S': S + "### + ); +} + +#[test] +fn fn_trait() { + assert_snapshot!( + infer(r#" +trait FnOnce { + type Output; + + fn call_once(self, args: Args) -> >::Output; +} + +fn test u128>(f: F) { + f.call_once((1, 2)); +} +"#), + @r###" + [57; 61) 'self': Self + [63; 67) 'args': Args + [150; 151) 'f': F + [156; 184) '{ ...2)); }': () + [162; 163) 'f': F + [162; 181) 'f.call...1, 2))': {unknown} + [174; 180) '(1, 2)': (u32, u64) + [175; 176) '1': u32 + [178; 179) '2': u64 + "### + ); +} + +#[test] +fn closure_1() { + assert_snapshot!( + infer(r#" +#[lang = "fn_once"] +trait FnOnce { + type Output; +} + +enum Option { Some(T), None } +impl Option { + fn map U>(self, f: F) -> Option {} +} + +fn test() { + let x = Option::Some(1u32); + x.map(|v| v + 1); + x.map(|_v| 1u64); + let y: Option = x.map(|_v| 1); +} +"#), + @r###" + [148; 152) 'self': Option + [154; 155) 'f': F + [173; 175) '{}': () + [189; 308) '{ ... 1); }': () + [199; 200) 'x': Option + [203; 215) 'Option::Some': Some(T) -> Option + [203; 221) 'Option...(1u32)': Option + [216; 220) '1u32': u32 + [227; 228) 'x': Option + [227; 243) 'x.map(...v + 1)': Option + [233; 242) '|v| v + 1': |u32| -> u32 + [234; 235) 'v': u32 + [237; 238) 'v': u32 + [237; 242) 'v + 1': u32 + [241; 242) '1': u32 + [249; 250) 'x': Option + [249; 265) 'x.map(... 1u64)': Option + [255; 264) '|_v| 1u64': |u32| -> u64 + [256; 258) '_v': u32 + [260; 264) '1u64': u64 + [275; 276) 'y': Option + [292; 293) 'x': Option + [292; 305) 'x.map(|_v| 1)': Option + [298; 304) '|_v| 1': |u32| -> i64 + [299; 301) '_v': u32 + [303; 304) '1': i64 + "### + ); +} + +#[test] +fn closure_2() { + assert_snapshot!( + infer(r#" +trait FnOnce { + type Output; +} + +fn test u64>(f: F) { + f(1); + let g = |v| v + 1; + g(1u64); + let h = |v| 1u128 + v; +} +"#), + @r###" + [73; 74) 'f': F + [79; 155) '{ ...+ v; }': () + [85; 86) 'f': F + [85; 89) 'f(1)': {unknown} + [87; 88) '1': i32 + [99; 100) 'g': |u64| -> i32 + [103; 112) '|v| v + 1': |u64| -> i32 + [104; 105) 'v': u64 + [107; 108) 'v': u64 + [107; 112) 'v + 1': i32 + [111; 112) '1': i32 + [118; 119) 'g': |u64| -> i32 + [118; 125) 'g(1u64)': i32 + [120; 124) '1u64': u64 + [135; 136) 'h': |u128| -> u128 + [139; 152) '|v| 1u128 + v': |u128| -> u128 + [140; 141) 'v': u128 + [143; 148) '1u128': u128 + [143; 152) '1u128 + v': u128 + [151; 152) 'v': u128 + "### + ); +} + +#[test] +fn closure_as_argument_inference_order() { + assert_snapshot!( + infer(r#" +#[lang = "fn_once"] +trait FnOnce { + type Output; +} + +fn foo1 U>(x: T, f: F) -> U {} +fn foo2 U>(f: F, x: T) -> U {} + +struct S; +impl S { + fn method(self) -> u64; + + fn foo1 U>(self, x: T, f: F) -> U {} + fn foo2 U>(self, f: F, x: T) -> U {} +} + +fn test() { + let x1 = foo1(S, |s| s.method()); + let x2 = foo2(|s| s.method(), S); + let x3 = S.foo1(S, |s| s.method()); + let x4 = S.foo2(|s| s.method(), S); +} +"#), + @r###" + [95; 96) 'x': T + [101; 102) 'f': F + [112; 114) '{}': () + [148; 149) 'f': F + [154; 155) 'x': T + [165; 167) '{}': () + [202; 206) 'self': S + [254; 258) 'self': S + [260; 261) 'x': T + [266; 267) 'f': F + [277; 279) '{}': () + [317; 321) 'self': S + [323; 324) 'f': F + [329; 330) 'x': T + [340; 342) '{}': () + [356; 515) '{ ... S); }': () + [366; 368) 'x1': u64 + [371; 375) 'foo1': fn foo1 u64>(T, F) -> U + [371; 394) 'foo1(S...hod())': u64 + [376; 377) 'S': S + [379; 393) '|s| s.method()': |S| -> u64 + [380; 381) 's': S + [383; 384) 's': S + [383; 393) 's.method()': u64 + [404; 406) 'x2': u64 + [409; 413) 'foo2': fn foo2 u64>(F, T) -> U + [409; 432) 'foo2(|...(), S)': u64 + [414; 428) '|s| s.method()': |S| -> u64 + [415; 416) 's': S + [418; 419) 's': S + [418; 428) 's.method()': u64 + [430; 431) 'S': S + [442; 444) 'x3': u64 + [447; 448) 'S': S + [447; 472) 'S.foo1...hod())': u64 + [454; 455) 'S': S + [457; 471) '|s| s.method()': |S| -> u64 + [458; 459) 's': S + [461; 462) 's': S + [461; 471) 's.method()': u64 + [482; 484) 'x4': u64 + [487; 488) 'S': S + [487; 512) 'S.foo2...(), S)': u64 + [494; 508) '|s| s.method()': |S| -> u64 + [495; 496) 's': S + [498; 499) 's': S + [498; 508) 's.method()': u64 + [510; 511) 'S': S + "### + ); +} + +#[test] +fn unselected_projection_in_trait_env_1() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + type Item; +} + +trait Trait2 { + fn foo(&self) -> u32; +} + +fn test() where T::Item: Trait2 { + let x: T::Item = no_matter; + x.foo()<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + +#[test] +fn unselected_projection_in_trait_env_2() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + type Item; +} + +trait Trait2 { + fn foo(&self) -> u32; +} + +fn test() where T::Item: Trait2, T: Trait, U: Trait<()> { + let x: T::Item = no_matter; + x.foo()<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + +#[test] +fn trait_impl_self_ty() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo()<|>; +} +"#, + ); + assert_eq!(t, "()"); +} + +#[test] +fn trait_impl_self_ty_cycle() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + fn foo(&self); +} + +struct S; + +impl Trait for S {} + +fn test() { + S.foo()<|>; +} +"#, + ); + assert_eq!(t, "{unknown}"); +} + +#[test] +fn unselected_projection_in_trait_env_cycle_1() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + type Item; +} + +trait Trait2 {} + +fn test() where T: Trait2 { + let x: T::Item = no_matter<|>; +} +"#, + ); + // this is a legitimate cycle + assert_eq!(t, "{unknown}"); +} + +#[test] +fn unselected_projection_in_trait_env_cycle_2() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + type Item; +} + +fn test() where T: Trait, U: Trait { + let x: T::Item = no_matter<|>; +} +"#, + ); + // this is a legitimate cycle + assert_eq!(t, "{unknown}"); +} From 379482068d6ef985df5260473cac9d42331a6104 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 12:03:35 -0500 Subject: [PATCH 039/312] Add `ModuleItemsOwner` to `Block` --- crates/ra_syntax/src/ast/generated.rs | 1 + crates/ra_syntax/src/grammar.ron | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index c06076e3d7..9dd6bd3eac 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -312,6 +312,7 @@ impl AstNode for Block { } } impl ast::AttrsOwner for Block {} +impl ast::ModuleItemOwner for Block {} impl Block { pub fn statements(&self) -> AstChildren { AstChildren::new(&self.syntax) diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index d1be40abeb..9ffa9095bc 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -653,6 +653,7 @@ Grammar( ], traits: [ "AttrsOwner", + "ModuleItemOwner", ] ), "ParamList": ( @@ -664,14 +665,14 @@ Grammar( "SelfParam": ( traits: [ "TypeAscriptionOwner", - "AttrsOwner", + "AttrsOwner", ] ), "Param": ( options: [ "Pat" ], traits: [ "TypeAscriptionOwner", - "AttrsOwner", + "AttrsOwner", ] ), "UseItem": ( From a863298314ac730ac8a357bdded6262d84baefd1 Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Wed, 4 Dec 2019 10:48:03 -0500 Subject: [PATCH 040/312] fix outdated link to ra-emacs-lsp.el --- docs/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index adacead52c..f95bed8ec1 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -129,7 +129,7 @@ Prerequisites: Installation: * add -[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el) +[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/master/editors/emacs/ra-emacs-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer * (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints From 00d5fb44abf5af4ec543db8386cfc41b1c07b45a Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Wed, 4 Dec 2019 11:00:51 -0500 Subject: [PATCH 041/312] use relative link --- docs/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index f95bed8ec1..7b86c5e53f 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -129,7 +129,7 @@ Prerequisites: Installation: * add -[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/master/editors/emacs/ra-emacs-lsp.el) +[ra-emacs-lsp.el](../../../editors/emacs/ra-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer * (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints From 62cadecc89d5ce8c8589f2730814550877d3358d Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Wed, 4 Dec 2019 11:02:03 -0500 Subject: [PATCH 042/312] fix link --- docs/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index 7b86c5e53f..668af293a0 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -129,7 +129,7 @@ Prerequisites: Installation: * add -[ra-emacs-lsp.el](../../../editors/emacs/ra-lsp.el) +[ra-emacs-lsp.el](../../editors/emacs/ra-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer * (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints From 956ce1d10ae04ef4d6a1530c948d74901ae8cc9e Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Wed, 4 Dec 2019 11:07:37 -0500 Subject: [PATCH 043/312] fix file name --- docs/user/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user/README.md b/docs/user/README.md index 668af293a0..5ec8fb25d1 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -129,7 +129,7 @@ Prerequisites: Installation: * add -[ra-emacs-lsp.el](../../editors/emacs/ra-lsp.el) +[ra-emacs-lsp.el](../../editors/emacs/ra-emacs-lsp.el) to load path and require it in `init.el` * run `lsp` in a rust buffer * (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints From 193b1a7437c97064a51f0c30a175665b5d6c9895 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 4 Dec 2019 17:15:55 +0100 Subject: [PATCH 044/312] :arrow_up: rowan --- Cargo.lock | 6 +++--- Cargo.toml | 1 + crates/ra_syntax/Cargo.toml | 2 +- crates/ra_syntax/src/algo.rs | 12 ++++++------ crates/ra_syntax/src/syntax_node.rs | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 23c9e25436..2cb9ae76db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1121,7 +1121,7 @@ dependencies = [ "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_parser 0.1.0", "ra_text_edit 0.1.0", - "rowan 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rowan 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1386,7 +1386,7 @@ dependencies = [ [[package]] name = "rowan" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1903,7 +1903,7 @@ dependencies = [ "checksum relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bedde000f40f2921ce439ea165c9c53fd629bfa115140c72e22aceacb4a21954" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" -"checksum rowan 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ca620bbf9c48c92b5cef19f96354a309ac36b7d8ef7c591e66117335c8b1988b" +"checksum rowan 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2662e5d6084ef5367e7410e730b4ad7393ccfaa57974e9734c73e1669db935c0" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" diff --git a/Cargo.toml b/Cargo.toml index 92e3228f05..97508c57b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ incremental = true debug = 0 # set this to 1 or 2 to get more useful backtraces in debugger [patch.'crates-io'] +# rowan = { path = "../rowan" } \ No newline at end of file diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 5db2b58c0b..1c0b184e1f 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml @@ -12,7 +12,7 @@ doctest = false [dependencies] itertools = "0.8.0" -rowan = "0.7.0" +rowan = "0.8.0" rustc_lexer = "0.1.0" rustc-hash = "1.0.1" arrayvec = "0.5.1" diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index 1c075082a4..e4061e9947 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs @@ -140,13 +140,13 @@ pub fn insert_children( }); let new_children = match &position { - InsertPosition::First => to_insert.chain(old_children).collect::>(), - InsertPosition::Last => old_children.chain(to_insert).collect::>(), + InsertPosition::First => to_insert.chain(old_children).collect::>(), + InsertPosition::Last => old_children.chain(to_insert).collect::>(), InsertPosition::Before(anchor) | InsertPosition::After(anchor) => { let take_anchor = if let InsertPosition::After(_) = position { 1 } else { 0 }; let split_at = position_of_child(parent, anchor.clone()) + take_anchor; let before = old_children.by_ref().take(split_at).collect::>(); - before.into_iter().chain(to_insert).chain(old_children).collect::>() + before.into_iter().chain(to_insert).chain(old_children).collect::>() } }; @@ -174,7 +174,7 @@ pub fn replace_children( .into_iter() .chain(to_insert.map(to_green_element)) .chain(old_children.skip(end + 1 - start)) - .collect::>(); + .collect::>(); with_children(parent, new_children) } @@ -187,7 +187,7 @@ pub fn replace_descendants( map: &FxHashMap, ) -> SyntaxNode { // FIXME: this could be made much faster. - let new_children = parent.children_with_tokens().map(|it| go(map, it)).collect::>(); + let new_children = parent.children_with_tokens().map(|it| go(map, it)).collect::>(); return with_children(parent, new_children); fn go( @@ -211,7 +211,7 @@ pub fn replace_descendants( fn with_children( parent: &SyntaxNode, - new_children: Box<[NodeOrToken]>, + new_children: Vec>, ) -> SyntaxNode { let len = new_children.iter().map(|it| it.text_len()).sum::(); let new_node = diff --git a/crates/ra_syntax/src/syntax_node.rs b/crates/ra_syntax/src/syntax_node.rs index b2f5b8c646..041c6ea8d6 100644 --- a/crates/ra_syntax/src/syntax_node.rs +++ b/crates/ra_syntax/src/syntax_node.rs @@ -40,7 +40,7 @@ pub use rowan::{Direction, NodeOrToken}; pub struct SyntaxTreeBuilder { errors: Vec, - inner: GreenNodeBuilder, + inner: GreenNodeBuilder<'static>, } impl Default for SyntaxTreeBuilder { From 46ad914d7dd2f03198a57fe44b6a4bad61e4d303 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 4 Dec 2019 23:03:42 +0100 Subject: [PATCH 045/312] :arrow_up: rowan --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2cb9ae76db..0e7594f807 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1121,7 +1121,7 @@ dependencies = [ "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_parser 0.1.0", "ra_text_edit 0.1.0", - "rowan 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1386,7 +1386,7 @@ dependencies = [ [[package]] name = "rowan" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1903,7 +1903,7 @@ dependencies = [ "checksum relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bedde000f40f2921ce439ea165c9c53fd629bfa115140c72e22aceacb4a21954" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" -"checksum rowan 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2662e5d6084ef5367e7410e730b4ad7393ccfaa57974e9734c73e1669db935c0" +"checksum rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "769d42f547015b761f70c3086ccb3f7bff355124d52e9bf96d17de41774ede4b" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" From b437dca4bd100c0a7a498d5960d566a0ccd92432 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Rouill=C3=A9?= Date: Wed, 4 Dec 2019 23:05:01 +0100 Subject: [PATCH 046/312] Run rustfmt with respect to Cargo.toml edition --- crates/ra_db/src/input.rs | 9 +++ crates/ra_ide/src/lib.rs | 5 ++ .../ra_lsp_server/src/main_loop/handlers.rs | 6 ++ .../ra_lsp_server/tests/heavy_tests/main.rs | 58 +++++++++++++++++++ 4 files changed, 78 insertions(+) diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index b6d8517761..2a7ed20d1c 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs @@ -235,6 +235,15 @@ impl FromStr for Edition { } } +impl fmt::Display for Edition { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Edition::Edition2015 => "2015", + Edition::Edition2018 => "2018", + }) + } +} + impl Dependency { pub fn crate_id(&self) -> CrateId { self.crate_id diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index d1bff4a761..779a81b2c0 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -422,6 +422,11 @@ impl Analysis { self.with_db(|db| parent_module::crate_for(db, file_id)) } + /// Returns the edition of the given crate. + pub fn crate_edition(&self, crate_id: CrateId) -> Cancelable { + self.with_db(|db| db.crate_graph().edition(crate_id)) + } + /// Returns the root file of the given crate. pub fn crate_root(&self, crate_id: CrateId) -> Cancelable { self.with_db(|db| db.crate_graph().crate_root(crate_id)) diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index ca47ff5e16..4095836344 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -555,12 +555,18 @@ pub fn handle_formatting( let _p = profile("handle_formatting"); let file_id = params.text_document.try_conv_with(&world)?; let file = world.analysis().file_text(file_id)?; + let crate_ids = world.analysis().crate_for(file_id)?; let file_line_index = world.analysis().file_line_index(file_id)?; let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); use std::process; let mut rustfmt = process::Command::new("rustfmt"); + if let Some(&crate_id) = crate_ids.first() { + // Assume all crates are in the same edition + let edition = world.analysis().crate_edition(crate_id)?; + rustfmt.args(&["--edition", &edition.to_string()]); + } rustfmt.stdin(process::Stdio::piped()).stdout(process::Stdio::piped()); if let Ok(path) = params.text_document.uri.to_file_path() { diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index 29224cbe8e..fec50bd25c 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -172,6 +172,7 @@ fn main() {} fn test_format_document() { let server = project( r#" +//- Cargo.toml [package] name = "foo" version = "0.0.0" @@ -219,6 +220,63 @@ pub use std::collections::HashMap; ); } +#[test] +fn test_format_document_2018() { + let server = project( + r#" +//- Cargo.toml +[package] +name = "foo" +version = "0.0.0" +edition = "2018" + +//- src/lib.rs +mod bar; + +async fn test() { +} + +fn main() { +} + +pub use std::collections::HashMap; +"#, + ); + server.wait_until_workspace_is_loaded(); + + server.request::( + DocumentFormattingParams { + text_document: server.doc_id("src/lib.rs"), + options: FormattingOptions { + tab_size: 4, + insert_spaces: false, + properties: HashMap::new(), + }, + }, + json!([ + { + "newText": r#"mod bar; + +async fn test() {} + +fn main() {} + +pub use std::collections::HashMap; +"#, + "range": { + "end": { + "character": 0, + "line": 10 + }, + "start": { + "character": 0, + "line": 0 + } + } + } + ]), + ); +} #[test] fn test_missing_module_code_action() { let server = project( From 1bb59a7d08d10d247da265ef58835f9979ec36b7 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 14:58:29 -0500 Subject: [PATCH 047/312] Three-state enum for module origin --- crates/ra_hir_def/src/nameres.rs | 91 ++++++++++++++++++---- crates/ra_hir_def/src/nameres/collector.rs | 7 +- 2 files changed, 78 insertions(+), 20 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index faf3566f44..cf2a831913 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -100,19 +100,83 @@ impl std::ops::Index for CrateDefMap { } } +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +pub enum ModuleOrigin { + /// It should not be `None` after collecting definitions. + Root(Option), + /// Note that non-inline modules, by definition, live inside non-macro file. + File(AstId, FileId), + Inline(AstId), + Block(AstId), +} + +impl Default for ModuleOrigin { + fn default() -> Self { + ModuleOrigin::Root(None) + } +} + +impl ModuleOrigin { + pub fn root(file_id: FileId) -> Self { + ModuleOrigin::Root(Some(file_id)) + } + + pub fn not_sure_file(file: Option, module: AstId) -> Self { + match file { + None => ModuleOrigin::Inline(module), + Some(file) => ModuleOrigin::File(module, file), + } + } + + pub fn not_sure_mod(file: FileId, module: Option>) -> Self { + match module { + None => ModuleOrigin::root(file), + Some(module) => ModuleOrigin::File(module, file), + } + } + + pub fn declaration(&self) -> Option> { + match self { + ModuleOrigin::File(m, _) | ModuleOrigin::Inline(m) => Some(*m), + ModuleOrigin::Root(_) | ModuleOrigin::Block(_) => None, + } + } + + pub fn file_id(&self) -> Option { + match self { + ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => Some(*file_id), + _ => None, + } + } + + /// Returns a node which defines this module. + /// That is, a file or a `mod foo {}` with items. + pub fn definition_source( + &self, + db: &impl DefDatabase, + ) -> InFile> { + match self { + ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => { + let file_id = *file_id; + let sf = db.parse(file_id).tree(); + return InFile::new(file_id.into(), Either::Left(sf)); + } + ModuleOrigin::Root(None) => unreachable!(), + ModuleOrigin::Inline(m) => InFile::new(m.file_id, Either::Right(m.to_node(db))), + // FIXME: right now it's never constructed, so it's fine to omit + ModuleOrigin::Block(b) => unimplemented!(), + } + } +} + #[derive(Default, Debug, PartialEq, Eq)] pub struct ModuleData { pub parent: Option, pub children: FxHashMap, pub scope: ModuleScope, - // FIXME: these can't be both null, we need a three-state enum here. - /// None for root - pub declaration: Option>, - /// None for inline modules. - /// - /// Note that non-inline modules, by definition, live inside non-macro file. - pub definition: Option, + /// Where does this module come from? + pub origin: ModuleOrigin, pub impls: Vec, } @@ -262,7 +326,7 @@ impl CrateDefMap { pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator + '_ { self.modules .iter() - .filter(move |(_id, data)| data.definition == Some(file_id)) + .filter(move |(_id, data)| data.origin.file_id() == Some(file_id)) .map(|(id, _data)| id) } @@ -285,18 +349,13 @@ impl ModuleData { &self, db: &impl DefDatabase, ) -> InFile> { - if let Some(file_id) = self.definition { - let sf = db.parse(file_id).tree(); - return InFile::new(file_id.into(), Either::Left(sf)); - } - let decl = self.declaration.unwrap(); - InFile::new(decl.file_id, Either::Right(decl.to_node(db))) + self.origin.definition_source(db) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. - /// `None` for the crate root. + /// `None` for the crate root or block. pub fn declaration_source(&self, db: &impl DefDatabase) -> Option> { - let decl = self.declaration?; + let decl = self.origin.declaration()?; let value = decl.to_node(db); Some(InFile { file_id: decl.file_id, value }) } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d4bfcae1d2..6f4a3e42e3 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -19,7 +19,7 @@ use crate::{ db::DefDatabase, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, - raw, BuiltinShadowMode, CrateDefMap, ModuleData, Resolution, ResolveMode, + raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, }, path::{Path, PathKind}, per_ns::PerNs, @@ -131,7 +131,7 @@ where let file_id = crate_graph.crate_root(self.def_map.krate); let raw_items = self.db.raw_items(file_id.into()); let module_id = self.def_map.root; - self.def_map.modules[module_id].definition = Some(file_id); + self.def_map.modules[module_id].origin = ModuleOrigin::root(file_id); ModCollector { def_collector: &mut *self, module_id, @@ -669,8 +669,7 @@ where let modules = &mut self.def_collector.def_map.modules; let res = modules.alloc(ModuleData::default()); modules[res].parent = Some(self.module_id); - modules[res].declaration = Some(declaration); - modules[res].definition = definition; + modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { From 7cbedc50bcf048c87f141a85418581076d67fc7a Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 15:23:21 -0500 Subject: [PATCH 048/312] Fix test compilation --- crates/ra_hir_def/src/nameres.rs | 2 +- crates/ra_hir_ty/src/test_db.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index cf2a831913..ca8cbcd42b 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -164,7 +164,7 @@ impl ModuleOrigin { ModuleOrigin::Root(None) => unreachable!(), ModuleOrigin::Inline(m) => InFile::new(m.file_id, Either::Right(m.to_node(db))), // FIXME: right now it's never constructed, so it's fine to omit - ModuleOrigin::Block(b) => unimplemented!(), + ModuleOrigin::Block(_b) => unimplemented!(), } } } diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 1dc9793f95..476f6df52a 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -74,7 +74,7 @@ impl TestDB { for &krate in self.relevant_crates(file_id).iter() { let crate_def_map = self.crate_def_map(krate); for (local_id, data) in crate_def_map.modules.iter() { - if data.definition == Some(file_id) { + if data.origin.file_id() == Some(file_id) { return ModuleId { krate, local_id }; } } From 38853459e3d964cc7f635829cdc66f5faee33d85 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 15:24:02 -0500 Subject: [PATCH 049/312] Add `ModuleSource::Block` --- crates/ra_hir/src/code_model.rs | 65 ++---------------- crates/ra_hir/src/code_model/src.rs | 3 +- crates/ra_hir/src/from_source.rs | 8 +-- crates/ra_hir/src/lib.rs | 5 +- crates/ra_hir/src/source_binder.rs | 3 +- crates/ra_hir_def/src/nameres.rs | 68 ++++++++++++++++++- .../ra_ide/src/display/navigation_target.rs | 43 ++++-------- crates/ra_ide/src/references/rename.rs | 2 +- crates/ra_ide/src/references/search_scope.rs | 5 ++ 9 files changed, 102 insertions(+), 100 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 5877afefa2..7706399ae5 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,6 +11,7 @@ use hir_def::{ builtin_type::BuiltinType, docs::Documentation, expr::{BindingAnnotation, Pat, PatId}, + nameres::ModuleSource, per_ns::PerNs, resolver::HasResolver, type_ref::{Mutability, TypeRef}, @@ -21,11 +22,11 @@ use hir_def::{ use hir_expand::{ diagnostics::DiagnosticSink, name::{self, AsName}, - AstId, MacroDefId, + MacroDefId, }; use hir_ty::expr::ExprValidator; -use ra_db::{CrateId, Edition, FileId, FilePosition}; -use ra_syntax::{ast, AstNode, SyntaxNode}; +use ra_db::{CrateId, Edition}; +use ra_syntax::ast; use crate::{ db::{DefDatabase, HirDatabase}, @@ -79,64 +80,6 @@ impl Crate { } } -pub enum ModuleSource { - SourceFile(ast::SourceFile), - Module(ast::Module), -} - -impl ModuleSource { - pub fn new( - db: &impl DefDatabase, - file_id: Option, - decl_id: Option>, - ) -> ModuleSource { - match (file_id, decl_id) { - (Some(file_id), _) => { - let source_file = db.parse(file_id).tree(); - ModuleSource::SourceFile(source_file) - } - (None, Some(item_id)) => { - let module = item_id.to_node(db); - assert!(module.item_list().is_some(), "expected inline module"); - ModuleSource::Module(module) - } - (None, None) => panic!(), - } - } - - // FIXME: this methods do not belong here - pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { - let parse = db.parse(position.file_id); - match &ra_syntax::algo::find_node_at_offset::( - parse.tree().syntax(), - position.offset, - ) { - Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), - _ => { - let source_file = parse.tree(); - ModuleSource::SourceFile(source_file) - } - } - } - - pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource { - if let Some(m) = - child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) - { - ModuleSource::Module(m) - } else { - let file_id = child.file_id.original_file(db); - let source_file = db.parse(file_id).tree(); - ModuleSource::SourceFile(source_file) - } - } - - pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource { - let source_file = db.parse(file_id).tree(); - ModuleSource::SourceFile(source_file) - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Module { pub(crate) id: ModuleId, diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 36cfbc8f12..083946729f 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -2,6 +2,7 @@ use either::Either; use hir_def::{ + nameres::ModuleSource, src::{HasChildSource, HasSource as _}, AstItemDef, Lookup, VariantId, }; @@ -9,7 +10,7 @@ use ra_syntax::ast; use crate::{ db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, - Module, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, + Module, Static, Struct, StructField, Trait, TypeAlias, Union, }; pub use hir_expand::InFile; diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 82bf641dca..94a5e0b0d5 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use hir_def::{AstItemDef, LocationCtx, ModuleId}; +use hir_def::{nameres::ModuleSource, AstItemDef, LocationCtx, ModuleId}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, @@ -10,8 +10,8 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, - InFile, Local, MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, - TypeAlias, Union, VariantDef, + InFile, Local, MacroDef, Module, ModuleDef, Static, Struct, StructField, Trait, TypeAlias, + Union, VariantDef, }; pub trait FromSource: Sized { @@ -257,7 +257,7 @@ impl Module { InFile { file_id: src.file_id, value: module.clone() }, ); } - ModuleSource::SourceFile(_) => (), + ModuleSource::SourceFile(_) | ModuleSource::Block(_) => (), }; let original_file = src.file_id.original_file(db); diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 853760cb1a..f12e4ca3f2 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -43,8 +43,8 @@ pub use crate::{ code_model::{ src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, - HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, - Static, Struct, StructField, Trait, Type, TypeAlias, Union, VariantDef, + HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, + StructField, Trait, Type, TypeAlias, Union, VariantDef, }, from_source::FromSource, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, @@ -59,6 +59,7 @@ pub use hir_def::{ body::scope::ExprScopes, builtin_type::BuiltinType, docs::Documentation, + nameres::ModuleSource, path::{Path, PathKind}, type_ref::Mutability, }; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 28d41b6474..db0451059e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -14,6 +14,7 @@ use hir_def::{ BodySourceMap, }, expr::{ExprId, PatId}, + nameres::ModuleSource, path::known, resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, AssocItemId, DefWithBodyId, @@ -46,7 +47,7 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) - Some(crate::Module::from_declaration(db, src)?.id.resolver(db)) }, ast::SourceFile(it) => { - let src = node.with_value(crate::ModuleSource::SourceFile(it)); + let src = node.with_value(ModuleSource::SourceFile(it)); Some(crate::Module::from_definition(db, src)?.id.resolver(db)) }, ast::StructDef(it) => { diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index ca8cbcd42b..feb2a4d32b 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -63,9 +63,12 @@ use hir_expand::{ }; use once_cell::sync::Lazy; use ra_arena::Arena; -use ra_db::{CrateId, Edition, FileId}; +use ra_db::{CrateId, Edition, FileId, FilePosition}; use ra_prof::profile; -use ra_syntax::ast; +use ra_syntax::{ + ast::{self, AstNode}, + SyntaxNode, +}; use rustc_hash::FxHashMap; use crate::{ @@ -361,6 +364,67 @@ impl ModuleData { } } +pub enum ModuleSource { + SourceFile(ast::SourceFile), + Module(ast::Module), + Block(ast::Block), +} + +impl ModuleSource { + pub fn new( + db: &impl DefDatabase, + file_id: Option, + decl_id: Option>, + ) -> ModuleSource { + match (file_id, decl_id) { + (Some(file_id), _) => { + let source_file = db.parse(file_id).tree(); + ModuleSource::SourceFile(source_file) + } + (None, Some(item_id)) => { + let module = item_id.to_node(db); + assert!(module.item_list().is_some(), "expected inline module"); + ModuleSource::Module(module) + } + (None, None) => panic!(), + } + } + + // FIXME: this methods do not belong here + pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { + let parse = db.parse(position.file_id); + match &ra_syntax::algo::find_node_at_offset::( + parse.tree().syntax(), + position.offset, + ) { + Some(m) if !m.has_semi() => ModuleSource::Module(m.clone()), + _ => { + let source_file = parse.tree(); + ModuleSource::SourceFile(source_file) + } + } + } + + pub fn from_child_node(db: &impl DefDatabase, child: InFile<&SyntaxNode>) -> ModuleSource { + if let Some(m) = + child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) + { + ModuleSource::Module(m) + } else if let Some(b) = child.value.ancestors().filter_map(ast::Block::cast).next() { + ModuleSource::Block(b) + } else { + let file_id = child.file_id.original_file(db); + let source_file = db.parse(file_id).tree(); + ModuleSource::SourceFile(source_file) + } + } + + pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource { + let source_file = db.parse(file_id).tree(); + ModuleSource::SourceFile(source_file) + } +} + mod diagnostics { use hir_expand::diagnostics::DiagnosticSink; use ra_db::RelativePathBuf; diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index f920d3db62..b376fcdaef 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -231,34 +231,21 @@ impl ToNav for hir::Module { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.definition_source(db); let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); - match &src.value { - ModuleSource::SourceFile(node) => { - let frange = original_range(db, src.with_value(node.syntax())); - - NavigationTarget::from_syntax( - frange.file_id, - name, - None, - frange.range, - node.syntax().kind(), - None, - None, - ) - } - ModuleSource::Module(node) => { - let frange = original_range(db, src.with_value(node.syntax())); - - NavigationTarget::from_syntax( - frange.file_id, - name, - None, - frange.range, - node.syntax().kind(), - node.doc_comment_text(), - node.short_label(), - ) - } - } + let syntax = match &src.value { + ModuleSource::SourceFile(node) => node.syntax(), + ModuleSource::Module(node) => node.syntax(), + ModuleSource::Block(node) => node.syntax(), + }; + let frange = original_range(db, src.with_value(syntax)); + NavigationTarget::from_syntax( + frange.file_id, + name, + None, + frange.range, + syntax.kind(), + None, + None, + ) } } diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index b804d5f6da..1abf202151 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -88,7 +88,7 @@ fn rename_mod( file_system_edits.push(move_file); } } - ModuleSource::Module(..) => {} + ModuleSource::Module(..) | ModuleSource::Block(..) => {} } } diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index f5c9589f4d..92eb2015b6 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs @@ -96,6 +96,10 @@ impl NameDefinition { let range = Some(m.syntax().text_range()); res.insert(file_id, range); } + ModuleSource::Block(b) => { + let range = Some(b.syntax().text_range()); + res.insert(file_id, range); + } ModuleSource::SourceFile(_) => { res.insert(file_id, None); res.extend(parent_module.children(db).map(|m| { @@ -137,6 +141,7 @@ impl NameDefinition { let mut res = FxHashMap::default(); let range = match module_src.value { ModuleSource::Module(m) => Some(m.syntax().text_range()), + ModuleSource::Block(b) => Some(b.syntax().text_range()), ModuleSource::SourceFile(_) => None, }; res.insert(file_id, range); From 5c5f90ba57c83499a44af33bf8b91b24254fb685 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 15:28:40 -0500 Subject: [PATCH 050/312] Confluent `ModuleSource` usage --- crates/ra_hir/src/code_model/src.rs | 6 +----- crates/ra_hir_def/src/nameres.rs | 18 +++++------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 083946729f..d9bccd902f 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -26,11 +26,7 @@ impl Module { /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. pub fn definition_source(self, db: &impl DefDatabase) -> InFile { let def_map = db.crate_def_map(self.id.krate); - let src = def_map[self.id.local_id].definition_source(db); - src.map(|it| match it { - Either::Left(it) => ModuleSource::SourceFile(it), - Either::Right(it) => ModuleSource::Module(it), - }) + def_map[self.id.local_id].definition_source(db) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index feb2a4d32b..e356515cb0 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -57,7 +57,6 @@ mod tests; use std::sync::Arc; -use either::Either; use hir_expand::{ ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId, }; @@ -154,20 +153,16 @@ impl ModuleOrigin { /// Returns a node which defines this module. /// That is, a file or a `mod foo {}` with items. - pub fn definition_source( - &self, - db: &impl DefDatabase, - ) -> InFile> { + pub fn definition_source(&self, db: &impl DefDatabase) -> InFile { match self { ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => { let file_id = *file_id; let sf = db.parse(file_id).tree(); - return InFile::new(file_id.into(), Either::Left(sf)); + return InFile::new(file_id.into(), ModuleSource::SourceFile(sf)); } ModuleOrigin::Root(None) => unreachable!(), - ModuleOrigin::Inline(m) => InFile::new(m.file_id, Either::Right(m.to_node(db))), - // FIXME: right now it's never constructed, so it's fine to omit - ModuleOrigin::Block(_b) => unimplemented!(), + ModuleOrigin::Inline(m) => InFile::new(m.file_id, ModuleSource::Module(m.to_node(db))), + ModuleOrigin::Block(b) => InFile::new(b.file_id, ModuleSource::Block(b.to_node(db))), } } } @@ -348,10 +343,7 @@ impl CrateDefMap { impl ModuleData { /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. - pub fn definition_source( - &self, - db: &impl DefDatabase, - ) -> InFile> { + pub fn definition_source(&self, db: &impl DefDatabase) -> InFile { self.origin.definition_source(db) } From 032eb3d68e07f087ac531d48f956a79948baa4b9 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Tue, 3 Dec 2019 15:58:38 -0500 Subject: [PATCH 051/312] Remove almost unused `ModuleSource::new` --- crates/ra_hir/src/from_source.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 20 +------------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 94a5e0b0d5..67b127ba57 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -238,7 +238,7 @@ impl Module { _ => { let src_parent = InFile { file_id: src.file_id, - value: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), + value: ModuleSource::from_file_id(db, src.file_id.original_file(db)), }; Module::from_definition(db, src_parent) } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index e356515cb0..ce318571c6 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -356,6 +356,7 @@ impl ModuleData { } } +#[derive(Debug, Clone, PartialEq, Eq)] pub enum ModuleSource { SourceFile(ast::SourceFile), Module(ast::Module), @@ -363,25 +364,6 @@ pub enum ModuleSource { } impl ModuleSource { - pub fn new( - db: &impl DefDatabase, - file_id: Option, - decl_id: Option>, - ) -> ModuleSource { - match (file_id, decl_id) { - (Some(file_id), _) => { - let source_file = db.parse(file_id).tree(); - ModuleSource::SourceFile(source_file) - } - (None, Some(item_id)) => { - let module = item_id.to_node(db); - assert!(module.item_list().is_some(), "expected inline module"); - ModuleSource::Module(module) - } - (None, None) => panic!(), - } - } - // FIXME: this methods do not belong here pub fn from_position(db: &impl DefDatabase, position: FilePosition) -> ModuleSource { let parse = db.parse(position.file_id); From 088f50c0ab351d5ac072547a47c1ce7eeae029f3 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Wed, 4 Dec 2019 13:35:24 -0500 Subject: [PATCH 052/312] No block at the moment --- crates/ra_hir/src/from_source.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 7 +------ crates/ra_ide/src/display/navigation_target.rs | 1 - crates/ra_ide/src/references/rename.rs | 2 +- crates/ra_ide/src/references/search_scope.rs | 5 ----- 5 files changed, 3 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 67b127ba57..a46bba4f20 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -257,7 +257,7 @@ impl Module { InFile { file_id: src.file_id, value: module.clone() }, ); } - ModuleSource::SourceFile(_) | ModuleSource::Block(_) => (), + ModuleSource::SourceFile(_) => (), }; let original_file = src.file_id.original_file(db); diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index ce318571c6..f70235c99b 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -109,7 +109,6 @@ pub enum ModuleOrigin { /// Note that non-inline modules, by definition, live inside non-macro file. File(AstId, FileId), Inline(AstId), - Block(AstId), } impl Default for ModuleOrigin { @@ -140,7 +139,7 @@ impl ModuleOrigin { pub fn declaration(&self) -> Option> { match self { ModuleOrigin::File(m, _) | ModuleOrigin::Inline(m) => Some(*m), - ModuleOrigin::Root(_) | ModuleOrigin::Block(_) => None, + ModuleOrigin::Root(_) => None, } } @@ -162,7 +161,6 @@ impl ModuleOrigin { } ModuleOrigin::Root(None) => unreachable!(), ModuleOrigin::Inline(m) => InFile::new(m.file_id, ModuleSource::Module(m.to_node(db))), - ModuleOrigin::Block(b) => InFile::new(b.file_id, ModuleSource::Block(b.to_node(db))), } } } @@ -360,7 +358,6 @@ impl ModuleData { pub enum ModuleSource { SourceFile(ast::SourceFile), Module(ast::Module), - Block(ast::Block), } impl ModuleSource { @@ -384,8 +381,6 @@ impl ModuleSource { child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) { ModuleSource::Module(m) - } else if let Some(b) = child.value.ancestors().filter_map(ast::Block::cast).next() { - ModuleSource::Block(b) } else { let file_id = child.file_id.original_file(db); let source_file = db.parse(file_id).tree(); diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index b376fcdaef..add11fbc36 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -234,7 +234,6 @@ impl ToNav for hir::Module { let syntax = match &src.value { ModuleSource::SourceFile(node) => node.syntax(), ModuleSource::Module(node) => node.syntax(), - ModuleSource::Block(node) => node.syntax(), }; let frange = original_range(db, src.with_value(syntax)); NavigationTarget::from_syntax( diff --git a/crates/ra_ide/src/references/rename.rs b/crates/ra_ide/src/references/rename.rs index 1abf202151..b804d5f6da 100644 --- a/crates/ra_ide/src/references/rename.rs +++ b/crates/ra_ide/src/references/rename.rs @@ -88,7 +88,7 @@ fn rename_mod( file_system_edits.push(move_file); } } - ModuleSource::Module(..) | ModuleSource::Block(..) => {} + ModuleSource::Module(..) => {} } } diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index 92eb2015b6..f5c9589f4d 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs @@ -96,10 +96,6 @@ impl NameDefinition { let range = Some(m.syntax().text_range()); res.insert(file_id, range); } - ModuleSource::Block(b) => { - let range = Some(b.syntax().text_range()); - res.insert(file_id, range); - } ModuleSource::SourceFile(_) => { res.insert(file_id, None); res.extend(parent_module.children(db).map(|m| { @@ -141,7 +137,6 @@ impl NameDefinition { let mut res = FxHashMap::default(); let range = match module_src.value { ModuleSource::Module(m) => Some(m.syntax().text_range()), - ModuleSource::Block(b) => Some(b.syntax().text_range()), ModuleSource::SourceFile(_) => None, }; res.insert(file_id, range); From 762915826ac6893036f8b5cd5e63677ed862f6d9 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Thu, 5 Dec 2019 08:19:27 -0500 Subject: [PATCH 053/312] Reduce visibility, use struct instead of tuples --- crates/ra_hir_def/src/nameres.rs | 43 +++++++++++++++++--------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index f70235c99b..01d67777d6 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -107,8 +107,13 @@ pub enum ModuleOrigin { /// It should not be `None` after collecting definitions. Root(Option), /// Note that non-inline modules, by definition, live inside non-macro file. - File(AstId, FileId), - Inline(AstId), + File { + declaration: AstId, + definition: FileId, + }, + Inline { + definition: AstId, + }, } impl Default for ModuleOrigin { @@ -118,49 +123,47 @@ impl Default for ModuleOrigin { } impl ModuleOrigin { - pub fn root(file_id: FileId) -> Self { + fn root(file_id: FileId) -> Self { ModuleOrigin::Root(Some(file_id)) } - pub fn not_sure_file(file: Option, module: AstId) -> Self { + pub(crate) fn not_sure_file(file: Option, declaration: AstId) -> Self { match file { - None => ModuleOrigin::Inline(module), - Some(file) => ModuleOrigin::File(module, file), + None => ModuleOrigin::Inline { definition: declaration }, + Some(definition) => ModuleOrigin::File { declaration, definition }, } } - pub fn not_sure_mod(file: FileId, module: Option>) -> Self { - match module { - None => ModuleOrigin::root(file), - Some(module) => ModuleOrigin::File(module, file), - } - } - - pub fn declaration(&self) -> Option> { + fn declaration(&self) -> Option> { match self { - ModuleOrigin::File(m, _) | ModuleOrigin::Inline(m) => Some(*m), + ModuleOrigin::File { declaration: module, .. } + | ModuleOrigin::Inline { definition: module, .. } => Some(*module), ModuleOrigin::Root(_) => None, } } - pub fn file_id(&self) -> Option { + pub(crate) fn file_id(&self) -> Option { match self { - ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => Some(*file_id), + ModuleOrigin::File { definition: file_id, .. } | ModuleOrigin::Root(Some(file_id)) => { + Some(*file_id) + } _ => None, } } /// Returns a node which defines this module. /// That is, a file or a `mod foo {}` with items. - pub fn definition_source(&self, db: &impl DefDatabase) -> InFile { + fn definition_source(&self, db: &impl DefDatabase) -> InFile { match self { - ModuleOrigin::File(_, file_id) | ModuleOrigin::Root(Some(file_id)) => { + ModuleOrigin::File { definition: file_id, .. } | ModuleOrigin::Root(Some(file_id)) => { let file_id = *file_id; let sf = db.parse(file_id).tree(); return InFile::new(file_id.into(), ModuleSource::SourceFile(sf)); } ModuleOrigin::Root(None) => unreachable!(), - ModuleOrigin::Inline(m) => InFile::new(m.file_id, ModuleSource::Module(m.to_node(db))), + ModuleOrigin::Inline { definition } => { + InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db))) + } } } } From 7702f690a9592605be71104ec9d0b732af940fcc Mon Sep 17 00:00:00 2001 From: ice1000 Date: Thu, 5 Dec 2019 08:28:31 -0500 Subject: [PATCH 054/312] One pub function less is good! --- crates/ra_hir/src/from_source.rs | 9 ++++----- crates/ra_hir_def/src/nameres.rs | 5 ----- crates/ra_ide/src/parent_module.rs | 5 +++-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index a46bba4f20..18d87f6d70 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -235,11 +235,10 @@ impl Module { let src_parent = InFile { file_id: src.file_id, value: parent_declaration }; Module::from_declaration(db, src_parent) } - _ => { - let src_parent = InFile { - file_id: src.file_id, - value: ModuleSource::from_file_id(db, src.file_id.original_file(db)), - }; + None => { + let source_file = db.parse(src.file_id.original_file(db)).tree(); + let src_parent = + InFile { file_id: src.file_id, value: ModuleSource::SourceFile(source_file) }; Module::from_definition(db, src_parent) } }?; diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 01d67777d6..0a2b32bbde 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -390,11 +390,6 @@ impl ModuleSource { ModuleSource::SourceFile(source_file) } } - - pub fn from_file_id(db: &impl DefDatabase, file_id: FileId) -> ModuleSource { - let source_file = db.parse(file_id).tree(); - ModuleSource::SourceFile(source_file) - } } mod diagnostics { diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index 616d69fce2..aef3fa3df0 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs @@ -1,6 +1,6 @@ //! FIXME: write short doc here -use ra_db::{CrateId, FileId, FilePosition}; +use ra_db::{CrateId, FileId, FilePosition, SourceDatabase}; use crate::{db::RootDatabase, NavigationTarget}; @@ -21,7 +21,8 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec Vec { - let src = hir::ModuleSource::from_file_id(db, file_id); + let source_file = db.parse(file_id).tree(); + let src = hir::ModuleSource::SourceFile(source_file); let module = match hir::Module::from_definition(db, hir::InFile { file_id: file_id.into(), value: src }) { From 006a583381ab66f229c4d49531cb50687343eea3 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Thu, 5 Dec 2019 08:33:29 -0500 Subject: [PATCH 055/312] Use placeholder instead of `Option` --- crates/ra_hir_def/src/nameres.rs | 22 +++++++++------------- crates/ra_hir_def/src/nameres/collector.rs | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 0a2b32bbde..98bab1bfed 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -104,8 +104,9 @@ impl std::ops::Index for CrateDefMap { #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum ModuleOrigin { - /// It should not be `None` after collecting definitions. - Root(Option), + CrateRoot { + definition: FileId, + }, /// Note that non-inline modules, by definition, live inside non-macro file. File { declaration: AstId, @@ -118,15 +119,11 @@ pub enum ModuleOrigin { impl Default for ModuleOrigin { fn default() -> Self { - ModuleOrigin::Root(None) + ModuleOrigin::CrateRoot { definition: FileId(0) } } } impl ModuleOrigin { - fn root(file_id: FileId) -> Self { - ModuleOrigin::Root(Some(file_id)) - } - pub(crate) fn not_sure_file(file: Option, declaration: AstId) -> Self { match file { None => ModuleOrigin::Inline { definition: declaration }, @@ -138,14 +135,14 @@ impl ModuleOrigin { match self { ModuleOrigin::File { declaration: module, .. } | ModuleOrigin::Inline { definition: module, .. } => Some(*module), - ModuleOrigin::Root(_) => None, + ModuleOrigin::CrateRoot { .. } => None, } } pub(crate) fn file_id(&self) -> Option { match self { - ModuleOrigin::File { definition: file_id, .. } | ModuleOrigin::Root(Some(file_id)) => { - Some(*file_id) + ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { + Some(*definition) } _ => None, } @@ -155,12 +152,11 @@ impl ModuleOrigin { /// That is, a file or a `mod foo {}` with items. fn definition_source(&self, db: &impl DefDatabase) -> InFile { match self { - ModuleOrigin::File { definition: file_id, .. } | ModuleOrigin::Root(Some(file_id)) => { - let file_id = *file_id; + ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { + let file_id = *definition; let sf = db.parse(file_id).tree(); return InFile::new(file_id.into(), ModuleSource::SourceFile(sf)); } - ModuleOrigin::Root(None) => unreachable!(), ModuleOrigin::Inline { definition } => { InFile::new(definition.file_id, ModuleSource::Module(definition.to_node(db))) } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 6f4a3e42e3..9d948d4f43 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -131,7 +131,7 @@ where let file_id = crate_graph.crate_root(self.def_map.krate); let raw_items = self.db.raw_items(file_id.into()); let module_id = self.def_map.root; - self.def_map.modules[module_id].origin = ModuleOrigin::root(file_id); + self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; ModCollector { def_collector: &mut *self, module_id, From d15f300268fa955f8e9c04d51ca1dc528766f742 Mon Sep 17 00:00:00 2001 From: ice1000 Date: Thu, 5 Dec 2019 08:37:39 -0500 Subject: [PATCH 056/312] Publicize `file_id` to make `test_db` compile --- crates/ra_hir_def/src/nameres.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 98bab1bfed..bd237a7b3b 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -139,7 +139,7 @@ impl ModuleOrigin { } } - pub(crate) fn file_id(&self) -> Option { + pub fn file_id(&self) -> Option { match self { ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => { Some(*definition) From 0c0ce1ae418a2f3f4fc125bd701cdb327f607002 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Dec 2019 15:16:59 +0100 Subject: [PATCH 057/312] Introduce ChildFromSource --- crates/ra_hir/src/from_source.rs | 141 +++-------- crates/ra_hir_def/src/child_from_source.rs | 276 +++++++++++++++++++++ crates/ra_hir_def/src/lib.rs | 1 + 3 files changed, 317 insertions(+), 101 deletions(-) create mode 100644 crates/ra_hir_def/src/child_from_source.rs diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 18d87f6d70..58203c721b 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,17 +1,20 @@ //! FIXME: write short doc here +use either::Either; -use hir_def::{nameres::ModuleSource, AstItemDef, LocationCtx, ModuleId}; +use hir_def::{ + child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, + LocationCtx, ModuleId, VariantId, +}; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ ast::{self, AstNode, NameOwner}, - match_ast, AstPtr, SyntaxNode, + match_ast, SyntaxNode, }; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasSource, ImplBlock, - InFile, Local, MacroDef, Module, ModuleDef, Static, Struct, StructField, Trait, TypeAlias, - Union, VariantDef, + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, + MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, }; pub trait FromSource: Sized { @@ -50,98 +53,45 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.items(db), - Container::ImplBlock(it) => it.items(db), - Container::Module(m) => { - return m - .declarations(db) - .into_iter() - .filter_map(|it| match it { - ModuleDef::Function(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) - } - }; - items - .into_iter() - .filter_map(|it| match it { - AssocItem::Function(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.id.child_from_source(db, src), + Container::ImplBlock(it) => it.id.child_from_source(db, src), + Container::Module(it) => it.id.child_from_source(db, src), + } + .map(Function::from) } } impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.items(db), - Container::ImplBlock(it) => it.items(db), - Container::Module(m) => { - return m - .declarations(db) - .into_iter() - .filter_map(|it| match it { - ModuleDef::Const(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) - } - }; - items - .into_iter() - .filter_map(|it| match it { - AssocItem::Const(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.id.child_from_source(db, src), + Container::ImplBlock(it) => it.id.child_from_source(db, src), + Container::Module(it) => it.id.child_from_source(db, src), + } + .map(Const::from) } } impl FromSource for Static { type Ast = ast::StaticDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let module = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Module(it) => it, - Container::Trait(_) | Container::ImplBlock(_) => return None, - }; - module - .declarations(db) - .into_iter() - .filter_map(|it| match it { - ModuleDef::Static(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Module(it) => it.id.child_from_source(db, src).map(Static::from), + Container::Trait(_) | Container::ImplBlock(_) => None, + } } } impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.items(db), - Container::ImplBlock(it) => it.items(db), - Container::Module(m) => { - return m - .declarations(db) - .into_iter() - .filter_map(|it| match it { - ModuleDef::TypeAlias(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) - } - }; - items - .into_iter() - .filter_map(|it| match it { - AssocItem::TypeAlias(it) => Some(it), - _ => None, - }) - .find(|it| same_source(&it.source(db), &src)) + match Container::find(db, src.as_ref().map(|it| it.syntax()))? { + Container::Trait(it) => it.id.child_from_source(db, src), + Container::ImplBlock(it) => it.id.child_from_source(db, src), + Container::Module(it) => it.id.child_from_source(db, src), + } + .map(TypeAlias::from) } } @@ -174,34 +124,33 @@ impl FromSource for EnumVariant { fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { let parent_enum = src.value.parent_enum(); let src_enum = InFile { file_id: src.file_id, value: parent_enum }; - let variants = Enum::from_source(db, src_enum)?.variants(db); - variants.into_iter().find(|v| same_source(&v.source(db), &src)) + let parent_enum = Enum::from_source(db, src_enum)?; + parent_enum.id.child_from_source(db, src).map(EnumVariant::from) } } impl FromSource for StructField { type Ast = FieldSource; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let variant_def: VariantDef = match src.value { + let variant_id: VariantId = match src.value { FieldSource::Named(ref field) => { let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; let src = InFile { file_id: src.file_id, value }; let def = Struct::from_source(db, src)?; - VariantDef::from(def) + def.id.into() } FieldSource::Pos(ref field) => { let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; let src = InFile { file_id: src.file_id, value }; let def = EnumVariant::from_source(db, src)?; - VariantDef::from(def) + EnumVariantId::from(def).into() } }; - variant_def - .variant_data(db) - .fields() - .iter() - .map(|(id, _)| StructField { parent: variant_def, id }) - .find(|f| f.source(db) == src) + let src = src.map(|field_source| match field_source { + FieldSource::Pos(it) => Either::Left(it), + FieldSource::Named(it) => Either::Right(it), + }); + variant_id.child_from_source(db, src).map(StructField::from) } } @@ -314,13 +263,3 @@ impl Container { Some(Container::Module(c)) } } - -/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are -/// equal if they point to exactly the same object. -/// -/// In general, we do not guarantee that we have exactly one instance of a -/// syntax tree for each file. We probably should add such guarantee, but, for -/// the time being, we will use identity-less AstPtr comparison. -fn same_source(s1: &InFile, s2: &InFile) -> bool { - s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) -} diff --git a/crates/ra_hir_def/src/child_from_source.rs b/crates/ra_hir_def/src/child_from_source.rs new file mode 100644 index 0000000000..37d4b78706 --- /dev/null +++ b/crates/ra_hir_def/src/child_from_source.rs @@ -0,0 +1,276 @@ +//! When *constructing* `hir`, we start at some parent syntax node and recursively +//! lower the children. +//! +//! This modules allows one to go in the opposite direction: start with a syntax +//! node for a *child*, and get its hir. + +use either::Either; +use hir_expand::InFile; +use ra_syntax::{ast, AstNode, AstPtr}; + +use crate::{ + db::DefDatabase, + src::{HasChildSource, HasSource}, + AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, ImplId, Lookup, ModuleDefId, ModuleId, + StaticId, StructFieldId, TraitId, TypeAliasId, VariantId, +}; + +pub trait ChildFromSource { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option; +} + +impl ChildFromSource for TraitId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.trait_data(*self); + data.items + .iter() + .filter_map(|(_, item)| match item { + AssocItemId::FunctionId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ImplId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.impl_data(*self); + data.items + .iter() + .filter_map(|item| match item { + AssocItemId::FunctionId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ModuleId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let crate_def_map = db.crate_def_map(self.krate); + let res = crate_def_map[self.local_id] + .scope + .declarations() + .filter_map(|item| match item { + ModuleDefId::FunctionId(it) => Some(it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }); + res + } +} + +impl ChildFromSource for TraitId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.trait_data(*self); + data.items + .iter() + .filter_map(|(_, item)| match item { + AssocItemId::ConstId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ImplId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.impl_data(*self); + data.items + .iter() + .filter_map(|item| match item { + AssocItemId::ConstId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ModuleId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let crate_def_map = db.crate_def_map(self.krate); + let res = crate_def_map[self.local_id] + .scope + .declarations() + .filter_map(|item| match item { + ModuleDefId::ConstId(it) => Some(it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }); + res + } +} + +impl ChildFromSource for TraitId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.trait_data(*self); + data.items + .iter() + .filter_map(|(_, item)| match item { + AssocItemId::TypeAliasId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ImplId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let data = db.impl_data(*self); + data.items + .iter() + .filter_map(|item| match item { + AssocItemId::TypeAliasId(it) => Some(*it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }) + } +} + +impl ChildFromSource for ModuleId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let crate_def_map = db.crate_def_map(self.krate); + let res = crate_def_map[self.local_id] + .scope + .declarations() + .filter_map(|item| match item { + ModuleDefId::TypeAliasId(it) => Some(it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }); + res + } +} + +impl ChildFromSource for ModuleId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let crate_def_map = db.crate_def_map(self.krate); + let res = crate_def_map[self.local_id] + .scope + .declarations() + .filter_map(|item| match item { + ModuleDefId::StaticId(it) => Some(it), + _ => None, + }) + .find(|func| { + let source = func.lookup(db).source(db); + same_source(&source, &child_source) + }); + res + } +} + +impl ChildFromSource> for VariantId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile>, + ) -> Option { + let arena_map = self.child_source(db); + let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { + child_source.file_id == arena_map.file_id + && match (source, &child_source.value) { + (Either::Left(a), Either::Left(b)) => AstPtr::new(a) == AstPtr::new(b), + (Either::Right(a), Either::Right(b)) => AstPtr::new(a) == AstPtr::new(b), + _ => false, + } + })?; + Some(StructFieldId { parent: *self, local_id }) + } +} + +impl ChildFromSource for EnumId { + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + let arena_map = self.child_source(db); + let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { + child_source.file_id == arena_map.file_id + && AstPtr::new(*source) == AstPtr::new(&child_source.value) + })?; + Some(EnumVariantId { parent: *self, local_id }) + } +} + +/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are +/// equal if they point to exactly the same object. +/// +/// In general, we do not guarantee that we have exactly one instance of a +/// syntax tree for each file. We probably should add such guarantee, but, for +/// the time being, we will use identity-less AstPtr comparison. +fn same_source(s1: &InFile, s2: &InFile) -> bool { + s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) +} diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index cfeacfded9..e02622f62e 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -30,6 +30,7 @@ mod trace; pub mod nameres; pub mod src; +pub mod child_from_source; #[cfg(test)] mod test_db; From 1a567f5ca28b40c1cd744c9123a59695fab351de Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Dec 2019 16:53:17 +0100 Subject: [PATCH 058/312] Reduce copy-paste --- crates/ra_hir/src/from_source.rs | 50 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 58203c721b..6fa9477591 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -2,8 +2,8 @@ use either::Either; use hir_def::{ - child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, - LocationCtx, ModuleId, VariantId, + child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, ImplId, + LocationCtx, ModuleId, TraitId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -53,24 +53,18 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.id.child_from_source(db, src), - Container::ImplBlock(it) => it.id.child_from_source(db, src), - Container::Module(it) => it.id.child_from_source(db, src), - } - .map(Function::from) + Container::find(db, src.as_ref().map(|it| it.syntax()))? + .child_from_source(db, src) + .map(Function::from) } } impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.id.child_from_source(db, src), - Container::ImplBlock(it) => it.id.child_from_source(db, src), - Container::Module(it) => it.id.child_from_source(db, src), - } - .map(Const::from) + Container::find(db, src.as_ref().map(|it| it.syntax()))? + .child_from_source(db, src) + .map(Const::from) } } impl FromSource for Static { @@ -86,12 +80,9 @@ impl FromSource for Static { impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Trait(it) => it.id.child_from_source(db, src), - Container::ImplBlock(it) => it.id.child_from_source(db, src), - Container::Module(it) => it.id.child_from_source(db, src), - } - .map(TypeAlias::from) + Container::find(db, src.as_ref().map(|it| it.syntax()))? + .child_from_source(db, src) + .map(TypeAlias::from) } } @@ -263,3 +254,22 @@ impl Container { Some(Container::Module(c)) } } + +impl ChildFromSource for Container +where + TraitId: ChildFromSource, + ImplId: ChildFromSource, + ModuleId: ChildFromSource, +{ + fn child_from_source( + &self, + db: &impl DefDatabase, + child_source: InFile, + ) -> Option { + match self { + Container::Trait(it) => it.id.child_from_source(db, child_source), + Container::ImplBlock(it) => it.id.child_from_source(db, child_source), + Container::Module(it) => it.id.child_from_source(db, child_source), + } + } +} From 18f6a995d0fc1f45099f3cc810a5d55d5401b41b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 15:10:33 +0100 Subject: [PATCH 059/312] Add expansion infrastructure for derive macros --- crates/ra_hir/src/code_model/src.rs | 5 +- crates/ra_hir/src/from_source.rs | 4 +- crates/ra_hir/src/source_binder.rs | 5 +- crates/ra_hir_def/src/attr.rs | 4 +- crates/ra_hir_def/src/body.rs | 6 +- crates/ra_hir_def/src/docs.rs | 2 +- crates/ra_hir_def/src/nameres/collector.rs | 73 ++++++++++++++++-- crates/ra_hir_def/src/nameres/raw.rs | 15 ++++ crates/ra_hir_def/src/nameres/tests/macros.rs | 24 ++++++ crates/ra_hir_def/src/path.rs | 5 ++ crates/ra_hir_expand/src/ast_id_map.rs | 12 ++- crates/ra_hir_expand/src/builtin_derive.rs | 64 ++++++++++++++++ crates/ra_hir_expand/src/builtin_macro.rs | 37 +++++---- crates/ra_hir_expand/src/db.rs | 19 +++-- crates/ra_hir_expand/src/hygiene.rs | 3 +- crates/ra_hir_expand/src/lib.rs | 76 +++++++++++++------ crates/ra_hir_expand/src/name.rs | 10 +++ crates/ra_mbe/src/syntax_bridge.rs | 34 ++++++--- 18 files changed, 319 insertions(+), 79 deletions(-) create mode 100644 crates/ra_hir_expand/src/builtin_derive.rs diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index d9bccd902f..78a4540827 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -105,7 +105,10 @@ impl HasSource for TypeAlias { impl HasSource for MacroDef { type Ast = ast::MacroCall; fn source(self, db: &impl DefDatabase) -> InFile { - InFile { file_id: self.id.ast_id.file_id, value: self.id.ast_id.to_node(db) } + InFile { + file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, + value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db), + } } } impl HasSource for ImplBlock { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 18d87f6d70..0d3ecbc77d 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -152,9 +152,9 @@ impl FromSource for MacroDef { let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; - let krate = module.krate().crate_id(); + let krate = Some(module.krate().crate_id()); - let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value)); + let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value))); let id: MacroDefId = MacroDefId { krate, ast_id, kind }; Some(MacroDef { id }) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index db0451059e..42c3925135 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -20,7 +20,8 @@ use hir_def::{ AssocItemId, DefWithBodyId, }; use hir_expand::{ - hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroFileKind, + hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, + MacroFileKind, }; use ra_syntax::{ ast::{self, AstNode}, @@ -456,7 +457,7 @@ impl SourceAnalyzer { db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), ); Some(Expansion { - macro_call_id: def.as_call_id(db, ast_id), + macro_call_id: def.as_call_id(db, MacroCallKind::FnLike(ast_id)), macro_file_kind: to_macro_file_kind(macro_call.value), }) } diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 7f9a6e7ca8..2f8f02d821 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -61,7 +61,9 @@ impl Attrs { AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), }, AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), - AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), + AttrDefId::MacroDefId(it) => { + it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)) + } AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db), diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index ef18168363..7b385f3fd8 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -6,7 +6,9 @@ pub mod scope; use std::{ops::Index, sync::Arc}; use either::Either; -use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroDefId, MacroFileKind}; +use hir_expand::{ + hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, MacroFileKind, +}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -46,7 +48,7 @@ impl Expander { if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { if let Some(def) = self.resolve_path_as_macro(db, &path) { - let call_id = def.as_call_id(db, ast_id); + let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); let file_id = call_id.as_file(MacroFileKind::Expr); if let Some(node) = db.parse_or_expand(file_id) { if let Some(expr) = ast::Expr::cast(node) { diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 3fc6d6934c..61727bd260 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -60,7 +60,7 @@ impl Documentation { docs_from_ast(&src.value[it.local_id]) } AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), - AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id.to_node(db)), + AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id?.to_node(db)), AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value), AttrDefId::StaticId(it) => docs_from_ast(&it.lookup(db).source(db).value), AttrDefId::FunctionId(it) => docs_from_ast(&it.lookup(db).source(db).value), diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 9d948d4f43..08693cb13a 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -4,9 +4,10 @@ //! resolves imports and expands macros. use hir_expand::{ + builtin_derive::find_builtin_derive, builtin_macro::find_builtin_macro, name::{self, AsName, Name}, - HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind, + HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, MacroFileKind, }; use ra_cfg::CfgOptions; use ra_db::{CrateId, FileId}; @@ -58,6 +59,7 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), + unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), macro_stack_monitor: MacroStackMonitor::default(), poison_macros: FxHashSet::default(), @@ -102,6 +104,7 @@ struct DefCollector<'a, DB> { glob_imports: FxHashMap>, unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>, unexpanded_macros: Vec<(LocalModuleId, AstId, Path)>, + unexpanded_attribute_macros: Vec<(LocalModuleId, AstId, Path)>, mod_dirs: FxHashMap, /// Some macro use `$tt:tt which mean we have to handle the macro perfectly @@ -470,6 +473,8 @@ where fn resolve_macros(&mut self) -> ReachedFixedPoint { let mut macros = std::mem::replace(&mut self.unexpanded_macros, Vec::new()); + let mut attribute_macros = + std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new()); let mut resolved = Vec::new(); let mut res = ReachedFixedPoint::Yes; macros.retain(|(module_id, ast_id, path)| { @@ -482,7 +487,19 @@ where ); if let Some(def) = resolved_res.resolved_def.take_macros() { - let call_id = def.as_call_id(self.db, *ast_id); + let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(*ast_id)); + resolved.push((*module_id, call_id, def)); + res = ReachedFixedPoint::No; + return false; + } + + true + }); + attribute_macros.retain(|(module_id, ast_id, path)| { + let resolved_res = self.resolve_attribute_macro(path); + + if let Some(def) = resolved_res { + let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); resolved.push((*module_id, call_id, def)); res = ReachedFixedPoint::No; return false; @@ -492,6 +509,7 @@ where }); self.unexpanded_macros = macros; + self.unexpanded_attribute_macros = attribute_macros; for (module_id, macro_call_id, macro_def_id) in resolved { self.collect_macro_expansion(module_id, macro_call_id, macro_def_id); @@ -500,6 +518,20 @@ where res } + fn resolve_attribute_macro(&self, path: &Path) -> Option { + // FIXME this is currently super hacky, just enough to support the + // built-in derives + if let Some(name) = path.as_ident() { + // FIXME this should actually be handled with the normal name + // resolution; the std lib defines built-in stubs for the derives, + // but these are new-style `macro`s, which we don't support yet + if let Some(def_id) = find_builtin_derive(name) { + return Some(def_id); + } + } + None + } + fn collect_macro_expansion( &mut self, module_id: LocalModuleId, @@ -587,7 +619,9 @@ where .def_collector .unresolved_imports .push((self.module_id, import_id, self.raw_items[import_id].clone())), - raw::RawItemKind::Def(def) => self.define_def(&self.raw_items[def]), + raw::RawItemKind::Def(def) => { + self.define_def(&self.raw_items[def], &item.attrs) + } raw::RawItemKind::Macro(mac) => self.collect_macro(&self.raw_items[mac]), raw::RawItemKind::Impl(imp) => { let module = ModuleId { @@ -682,10 +716,16 @@ where res } - fn define_def(&mut self, def: &raw::DefData) { + fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) { let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); + // FIXME: check attrs to see if this is an attribute macro invocation; + // in which case we don't add the invocation, just a single attribute + // macro invocation + + self.collect_derives(attrs, def); + let name = def.name.clone(); let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { @@ -736,6 +776,23 @@ where self.def_collector.update(self.module_id, None, &[(name, resolution)]) } + fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { + for derive_subtree in attrs.by_key("derive").tt_values() { + // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree + for tt in &derive_subtree.token_trees { + let ident = match &tt { + tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident, + tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok + _ => continue, // anything else would be an error (which we currently ignore) + }; + let path = Path::from_tt_ident(ident); + + let ast_id = AstId::new(self.file_id, def.kind.ast_id()); + self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path)); + } + } + } + fn collect_macro(&mut self, mac: &raw::MacroData) { let ast_id = AstId::new(self.file_id, mac.ast_id); @@ -759,8 +816,8 @@ where if is_macro_rules(&mac.path) { if let Some(name) = &mac.name { let macro_id = MacroDefId { - ast_id, - krate: self.def_collector.def_map.krate, + ast_id: Some(ast_id), + krate: Some(self.def_collector.def_map.krate), kind: MacroDefKind::Declarative, }; self.def_collector.define_macro(self.module_id, name.clone(), macro_id, mac.export); @@ -773,7 +830,8 @@ where if let Some(macro_def) = mac.path.as_ident().and_then(|name| { self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) }) { - let macro_call_id = macro_def.as_call_id(self.def_collector.db, ast_id); + let macro_call_id = + macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); return; @@ -829,6 +887,7 @@ mod tests { glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), unexpanded_macros: Vec::new(), + unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), macro_stack_monitor: monitor, poison_macros: FxHashSet::default(), diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index de4e706c29..a2821e1c3c 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -184,6 +184,21 @@ pub(super) enum DefKind { TypeAlias(FileAstId), } +impl DefKind { + pub fn ast_id(&self) -> FileAstId { + match self { + DefKind::Function(it) => it.upcast(), + DefKind::Struct(it) => it.upcast(), + DefKind::Union(it) => it.upcast(), + DefKind::Enum(it) => it.upcast(), + DefKind::Const(it) => it.upcast(), + DefKind::Static(it) => it.upcast(), + DefKind::Trait(it) => it.upcast(), + DefKind::TypeAlias(it) => it.upcast(), + } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(super) struct Macro(RawId); impl_arena_id!(Macro); diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index 704065633a..cfa4ecb1af 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs @@ -600,3 +600,27 @@ fn macro_dollar_crate_is_correct_in_indirect_deps() { â‹®bar: t v "###); } + +#[test] +fn expand_derive() { + let map = compute_crate_def_map( + " + //- /main.rs + #[derive(Clone)] + struct Foo; + ", + ); + assert_eq!(map.modules[map.root].impls.len(), 1); +} + +#[test] +fn expand_multiple_derive() { + let map = compute_crate_def_map( + " + //- /main.rs + #[derive(Copy, Clone)] + struct Foo; + ", + ); + assert_eq!(map.modules[map.root].impls.len(), 2); +} diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3030dcdf6e..e547b2f03c 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -199,6 +199,11 @@ impl Path { name_ref.as_name().into() } + /// Converts an `tt::Ident` into a single-identifier `Path`. + pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path { + ident.as_name().into() + } + /// `true` is this path is a single identifier, like `foo` pub fn is_ident(&self) -> bool { self.kind == PathKind::Plain && self.segments.len() == 1 diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs index cb464c3ff1..a764bdf24e 100644 --- a/crates/ra_hir_expand/src/ast_id_map.rs +++ b/crates/ra_hir_expand/src/ast_id_map.rs @@ -39,6 +39,16 @@ impl Hash for FileAstId { } } +impl FileAstId { + // Can't make this a From implementation because of coherence + pub fn upcast(self) -> FileAstId + where + M: From, + { + FileAstId { raw: self.raw, _ty: PhantomData } + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] struct ErasedFileAstId(RawId); impl_arena_id!(ErasedFileAstId); @@ -53,7 +63,7 @@ impl AstIdMap { pub(crate) fn from_source(node: &SyntaxNode) -> AstIdMap { assert!(node.parent().is_none()); let mut res = AstIdMap { arena: Arena::default() }; - // By walking the tree in bread-first order we make sure that parents + // By walking the tree in breadth-first order we make sure that parents // get lower ids then children. That is, adding a new child does not // change parent's id. This means that, say, adding a new function to a // trait does not change ids of top-level items, which helps caching. diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs new file mode 100644 index 0000000000..0a70c63c00 --- /dev/null +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -0,0 +1,64 @@ +//! Builtin derives. +use crate::db::AstDatabase; +use crate::{name, MacroCallId, MacroDefId, MacroDefKind}; + +use crate::quote; + +macro_rules! register_builtin { + ( $(($name:ident, $kind: ident) => $expand:ident),* ) => { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub enum BuiltinDeriveExpander { + $($kind),* + } + + impl BuiltinDeriveExpander { + pub fn expand( + &self, + db: &dyn AstDatabase, + id: MacroCallId, + tt: &tt::Subtree, + ) -> Result { + let expander = match *self { + $( BuiltinDeriveExpander::$kind => $expand, )* + }; + expander(db, id, tt) + } + } + + pub fn find_builtin_derive(ident: &name::Name) -> Option { + let kind = match ident { + $( id if id == &name::$name => BuiltinDeriveExpander::$kind, )* + _ => return None, + }; + + Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind) }) + } + }; +} + +register_builtin! { + (COPY_TRAIT, Copy) => copy_expand, + (CLONE_TRAIT, Clone) => clone_expand +} + +fn copy_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + let expanded = quote! { + impl Copy for Foo {} + }; + Ok(expanded) +} + +fn clone_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + let expanded = quote! { + impl Clone for Foo {} + }; + Ok(expanded) +} diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index d370dfb34f..35f99b2bc4 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -39,7 +39,7 @@ macro_rules! register_builtin { _ => return None, }; - Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(kind) }) + Some(MacroDefId { krate: Some(krate), ast_id: Some(ast_id), kind: MacroDefKind::BuiltIn(kind) }) } }; } @@ -82,10 +82,9 @@ fn line_expand( _tt: &tt::Subtree, ) -> Result { let loc = db.lookup_intern_macro(id); - let macro_call = loc.ast_id.to_node(db); - let arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; - let arg_start = arg.syntax().text_range().start(); + let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; + let arg_start = arg.text_range().start(); let file = id.as_file(MacroFileKind::Expr); let line_num = to_line_number(db, file, arg_start); @@ -103,11 +102,10 @@ fn stringify_expand( _tt: &tt::Subtree, ) -> Result { let loc = db.lookup_intern_macro(id); - let macro_call = loc.ast_id.to_node(db); let macro_content = { - let arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; - let macro_args = arg.syntax().clone(); + let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; + let macro_args = arg.clone(); let text = macro_args.text(); let without_parens = TextUnit::of_char('(')..text.len() - TextUnit::of_char(')'); text.slice(without_parens).to_string() @@ -148,7 +146,10 @@ fn column_expand( _tt: &tt::Subtree, ) -> Result { let loc = db.lookup_intern_macro(id); - let macro_call = loc.ast_id.to_node(db); + let macro_call = match loc.kind { + crate::MacroCallKind::FnLike(ast_id) => ast_id.to_node(db), + _ => panic!("column macro called as attr"), + }; let _arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; let col_start = macro_call.syntax().text_range().start(); @@ -164,15 +165,10 @@ fn column_expand( } fn file_expand( - db: &dyn AstDatabase, - id: MacroCallId, + _db: &dyn AstDatabase, + _id: MacroCallId, _tt: &tt::Subtree, ) -> Result { - let loc = db.lookup_intern_macro(id); - let macro_call = loc.ast_id.to_node(db); - - let _ = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; - // FIXME: RA purposefully lacks knowledge of absolute file names // so just return "". let file_name = ""; @@ -207,7 +203,7 @@ fn compile_error_expand( #[cfg(test)] mod tests { use super::*; - use crate::{test_db::TestDB, MacroCallLoc}; + use crate::{test_db::TestDB, MacroCallKind, MacroCallLoc}; use ra_db::{fixture::WithFixture, SourceDatabase}; fn expand_builtin_macro(s: &str, expander: BuiltinFnLikeExpander) -> String { @@ -220,14 +216,17 @@ mod tests { // the first one should be a macro_rules let def = MacroDefId { - krate: CrateId(0), - ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0])), + krate: Some(CrateId(0)), + ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[0]))), kind: MacroDefKind::BuiltIn(expander), }; let loc = MacroCallLoc { def, - ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(¯o_calls[1])), + kind: MacroCallKind::FnLike(AstId::new( + file_id.into(), + ast_id_map.ast_id(¯o_calls[1]), + )), }; let id = db.intern_macro(loc); diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 8e46fa177d..99dabf3fbb 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -9,14 +9,15 @@ use ra_prof::profile; use ra_syntax::{AstNode, Parse, SyntaxNode}; use crate::{ - ast_id_map::AstIdMap, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, - MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, MacroFileKind, + ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, + MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, MacroFileKind, }; #[derive(Debug, Clone, Eq, PartialEq)] pub enum TokenExpander { MacroRules(mbe::MacroRules), Builtin(BuiltinFnLikeExpander), + BuiltinDerive(BuiltinDeriveExpander), } impl TokenExpander { @@ -29,6 +30,7 @@ impl TokenExpander { match self { TokenExpander::MacroRules(it) => it.expand(tt), TokenExpander::Builtin(it) => it.expand(db, id, tt), + TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt), } } @@ -36,6 +38,7 @@ impl TokenExpander { match self { TokenExpander::MacroRules(it) => it.map_id_down(id), TokenExpander::Builtin(..) => id, + TokenExpander::BuiltinDerive(..) => id, } } @@ -43,6 +46,7 @@ impl TokenExpander { match self { TokenExpander::MacroRules(it) => it.map_id_up(id), TokenExpander::Builtin(..) => (id, mbe::Origin::Def), + TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Def), } } } @@ -76,7 +80,7 @@ pub(crate) fn macro_def( ) -> Option> { match id.kind { MacroDefKind::Declarative => { - let macro_call = id.ast_id.to_node(db); + let macro_call = id.ast_id?.to_node(db); let arg = macro_call.token_tree()?; let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { log::warn!("fail on macro_def to token tree: {:#?}", arg); @@ -91,6 +95,10 @@ pub(crate) fn macro_def( MacroDefKind::BuiltIn(expander) => { Some(Arc::new((TokenExpander::Builtin(expander.clone()), mbe::TokenMap::default()))) } + MacroDefKind::BuiltInDerive(expander) => Some(Arc::new(( + TokenExpander::BuiltinDerive(expander.clone()), + mbe::TokenMap::default(), + ))), } } @@ -99,9 +107,8 @@ pub(crate) fn macro_arg( id: MacroCallId, ) -> Option> { let loc = db.lookup_intern_macro(id); - let macro_call = loc.ast_id.to_node(db); - let arg = macro_call.token_tree()?; - let (tt, tmap) = mbe::ast_to_token_tree(&arg)?; + let arg = loc.kind.arg(db)?; + let (tt, tmap) = mbe::syntax_node_to_token_tree(&arg)?; Some(Arc::new((tt, tmap))) } diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index 64c8b06c6e..2e8a533f70 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs @@ -25,8 +25,9 @@ impl Hygiene { HirFileIdRepr::MacroFile(macro_file) => { let loc = db.lookup_intern_macro(macro_file.macro_call_id); match loc.def.kind { - MacroDefKind::Declarative => Some(loc.def.krate), + MacroDefKind::Declarative => loc.def.krate, MacroDefKind::BuiltIn(_) => None, + MacroDefKind::BuiltInDerive(_) => None, } } }; diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 3be9bdf869..59c69b91bb 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -9,6 +9,7 @@ pub mod ast_id_map; pub mod name; pub mod hygiene; pub mod diagnostics; +pub mod builtin_derive; pub mod builtin_macro; pub mod quote; @@ -23,6 +24,7 @@ use ra_syntax::{ }; use crate::ast_id_map::FileAstId; +use crate::builtin_derive::BuiltinDeriveExpander; use crate::builtin_macro::BuiltinFnLikeExpander; #[cfg(test)] @@ -69,7 +71,7 @@ impl HirFileId { HirFileIdRepr::FileId(file_id) => file_id, HirFileIdRepr::MacroFile(macro_file) => { let loc = db.lookup_intern_macro(macro_file.macro_call_id); - loc.ast_id.file_id.original_file(db) + loc.kind.file_id().original_file(db) } } } @@ -81,8 +83,8 @@ impl HirFileId { HirFileIdRepr::MacroFile(macro_file) => { let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id); - let arg_tt = loc.ast_id.to_node(db).token_tree()?; - let def_tt = loc.def.ast_id.to_node(db).token_tree()?; + let arg_tt = loc.kind.arg(db)?; + let def_tt = loc.def.ast_id?.to_node(db).token_tree()?; let macro_def = db.macro_def(loc.def)?; let (parse, exp_map) = db.parse_macro(macro_file)?; @@ -90,8 +92,8 @@ impl HirFileId { Some(ExpansionInfo { expanded: InFile::new(self, parse.syntax_node()), - arg: InFile::new(loc.ast_id.file_id, arg_tt), - def: InFile::new(loc.ast_id.file_id, def_tt), + arg: InFile::new(loc.kind.file_id(), arg_tt), + def: InFile::new(loc.def.ast_id?.file_id, def_tt), macro_arg, macro_def, exp_map, @@ -129,18 +131,20 @@ impl salsa::InternKey for MacroCallId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDefId { - pub krate: CrateId, - pub ast_id: AstId, + // FIXME: krate and ast_id are currently optional because we don't have a + // definition location for built-in derives. There is one, though: the + // standard library defines them. The problem is that it uses the new + // `macro` syntax for this, which we don't support yet. As soon as we do + // (which will probably require touching this code), we can instead use + // that (and also remove the hacks for resolving built-in derives). + pub krate: Option, + pub ast_id: Option>, pub kind: MacroDefKind, } impl MacroDefId { - pub fn as_call_id( - self, - db: &dyn db::AstDatabase, - ast_id: AstId, - ) -> MacroCallId { - db.intern_macro(MacroCallLoc { def: self, ast_id }) + pub fn as_call_id(self, db: &dyn db::AstDatabase, kind: MacroCallKind) -> MacroCallId { + db.intern_macro(MacroCallLoc { def: self, kind }) } } @@ -148,12 +152,38 @@ impl MacroDefId { pub enum MacroDefKind { Declarative, BuiltIn(BuiltinFnLikeExpander), + // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander + BuiltInDerive(BuiltinDeriveExpander), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct MacroCallLoc { pub(crate) def: MacroDefId, - pub(crate) ast_id: AstId, + pub(crate) kind: MacroCallKind, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum MacroCallKind { + FnLike(AstId), + Attr(AstId), +} + +impl MacroCallKind { + pub fn file_id(&self) -> HirFileId { + match self { + MacroCallKind::FnLike(ast_id) => ast_id.file_id, + MacroCallKind::Attr(ast_id) => ast_id.file_id, + } + } + + pub fn arg(&self, db: &dyn db::AstDatabase) -> Option { + match self { + MacroCallKind::FnLike(ast_id) => { + Some(ast_id.to_node(db).token_tree()?.syntax().clone()) + } + MacroCallKind::Attr(ast_id) => Some(ast_id.to_node(db).syntax().clone()), + } + } } impl MacroCallId { @@ -167,7 +197,7 @@ impl MacroCallId { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ExpansionInfo { expanded: InFile, - arg: InFile, + arg: InFile, def: InFile, macro_def: Arc<(db::TokenExpander, mbe::TokenMap)>, @@ -178,8 +208,7 @@ pub struct ExpansionInfo { impl ExpansionInfo { pub fn map_token_down(&self, token: InFile<&SyntaxToken>) -> Option> { assert_eq!(token.file_id, self.arg.file_id); - let range = - token.value.text_range().checked_sub(self.arg.value.syntax().text_range().start())?; + let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; let token_id = self.macro_arg.1.token_by_range(range)?; let token_id = self.macro_def.0.map_id_down(token_id); @@ -195,16 +224,15 @@ impl ExpansionInfo { let (token_id, origin) = self.macro_def.0.map_id_up(token_id); let (token_map, tt) = match origin { - mbe::Origin::Call => (&self.macro_arg.1, &self.arg), - mbe::Origin::Def => (&self.macro_def.1, &self.def), + mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), + mbe::Origin::Def => { + (&self.macro_def.1, self.def.as_ref().map(|tt| tt.syntax().clone())) + } }; let range = token_map.range_by_token(token_id)?; - let token = algo::find_covering_element( - tt.value.syntax(), - range + tt.value.syntax().text_range().start(), - ) - .into_token()?; + let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) + .into_token()?; Some(tt.with_value(token)) } } diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 05ba370706..86709b5cf2 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -83,6 +83,12 @@ impl AsName for ast::Name { } } +impl AsName for tt::Ident { + fn as_name(&self) -> Name { + Name::resolve(&self.text) + } +} + impl AsName for ast::FieldKind { fn as_name(&self) -> Name { match self { @@ -153,3 +159,7 @@ pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error"); pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); + +// Builtin derives +pub const COPY_TRAIT: Name = Name::new_inline_ascii(4, b"Copy"); +pub const CLONE_TRAIT: Name = Name::new_inline_ascii(5, b"Clone"); diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 1de399fee4..0fbcb2f664 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -2,7 +2,7 @@ use ra_parser::{FragmentKind, ParseError, TreeSink}; use ra_syntax::{ - ast, AstNode, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, + ast, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxTreeBuilder, TextRange, TextUnit, T, }; use std::iter::successors; @@ -20,7 +20,7 @@ pub struct TokenMap { /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro /// will consume). -pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap)> { +pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> Option<(tt::Subtree, TokenMap)> { syntax_node_to_token_tree(ast.syntax()) } @@ -208,13 +208,8 @@ impl Convertor { } else if token.kind().is_trivia() { continue; } else if token.kind().is_punct() { - assert!( - token.text().len() == 1, - "Input ast::token punct must be single char." - ); - let char = token.text().chars().next().unwrap(); - - let spacing = match child_iter.peek() { + // we need to pull apart joined punctuation tokens + let last_spacing = match child_iter.peek() { Some(NodeOrToken::Token(token)) => { if token.kind().is_punct() { tt::Spacing::Joint @@ -224,8 +219,12 @@ impl Convertor { } _ => tt::Spacing::Alone, }; - - token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); + let spacing_iter = std::iter::repeat(tt::Spacing::Joint) + .take(token.text().len() - 1) + .chain(std::iter::once(last_spacing)); + for (char, spacing) in token.text().chars().zip(spacing_iter) { + token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); + } } else { let child: tt::TokenTree = if token.kind() == T![true] || token.kind() == T![false] { @@ -389,7 +388,10 @@ mod tests { use super::*; use crate::tests::{create_rules, expand}; use ra_parser::TokenSource; - use ra_syntax::algo::{insert_children, InsertPosition}; + use ra_syntax::{ + algo::{insert_children, InsertPosition}, + ast::AstNode, + }; #[test] fn convert_tt_token_source() { @@ -491,4 +493,12 @@ mod tests { assert_eq!(tt.delimiter, tt::Delimiter::Brace); } + + #[test] + fn test_token_tree_multi_char_punct() { + let source_file = ast::SourceFile::parse("struct Foo { a: x::Y }").ok().unwrap(); + let struct_def = source_file.syntax().descendants().find_map(ast::StructDef::cast).unwrap(); + let tt = ast_to_token_tree(&struct_def).unwrap().0; + token_tree_to_syntax_node(&tt, FragmentKind::Item).unwrap(); + } } From 518b5bf92789000416f18de3163c962b31ead0af Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Dec 2019 17:55:38 +0100 Subject: [PATCH 060/312] Remove obsolete comment --- crates/ra_hir_def/src/per_ns.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/ra_hir_def/src/per_ns.rs b/crates/ra_hir_def/src/per_ns.rs index 00e866bf9f..3a5105028f 100644 --- a/crates/ra_hir_def/src/per_ns.rs +++ b/crates/ra_hir_def/src/per_ns.rs @@ -11,8 +11,6 @@ use crate::ModuleDefId; pub struct PerNs { pub types: Option, pub values: Option, - /// Since macros has different type, many methods simply ignore it. - /// We can only use special method like `get_macros` to access it. pub macros: Option, } From ab4ecca210d8d280a4e216c2b6edfff303269144 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 19:27:39 +0100 Subject: [PATCH 061/312] Don't wrap most syntax trees in invisible delimiters when converting to token tree Otherwise parsing them again doesn't work. --- crates/ra_mbe/src/syntax_bridge.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 0fbcb2f664..66c1f0337d 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -245,8 +245,14 @@ impl Convertor { } } NodeOrToken::Node(node) => { - let child = self.go(&node)?.into(); - token_trees.push(child); + let child_subtree = self.go(&node)?; + if child_subtree.delimiter == tt::Delimiter::None + && node.kind() != SyntaxKind::TOKEN_TREE + { + token_trees.extend(child_subtree.token_trees); + } else { + token_trees.push(child_subtree.into()); + } } }; } From db8a00bd99cdc10ae8166fca3827eefebf791471 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 19:29:57 +0100 Subject: [PATCH 062/312] Implement derive(Copy, Clone) properly (well, kind of) --- crates/ra_hir_expand/src/builtin_derive.rs | 187 ++++++++++++++++++++- crates/ra_hir_expand/src/quote.rs | 10 ++ crates/ra_hir_ty/src/tests/macros.rs | 51 ++++++ 3 files changed, 241 insertions(+), 7 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 0a70c63c00..fde50f7e6d 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -1,8 +1,15 @@ //! Builtin derives. -use crate::db::AstDatabase; -use crate::{name, MacroCallId, MacroDefId, MacroDefKind}; -use crate::quote; +use log::debug; + +use ra_parser::FragmentKind; +use ra_syntax::{ + ast::{self, AstNode, ModuleItemOwner, NameOwner, TypeParamsOwner}, + match_ast, +}; + +use crate::db::AstDatabase; +use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; macro_rules! register_builtin { ( $(($name:ident, $kind: ident) => $expand:ident),* ) => { @@ -41,13 +48,79 @@ register_builtin! { (CLONE_TRAIT, Clone) => clone_expand } +struct BasicAdtInfo { + name: tt::Ident, + type_params: usize, +} + +fn parse_adt(tt: &tt::Subtree) -> Result { + let (parsed, token_map) = mbe::token_tree_to_syntax_node(tt, FragmentKind::Items)?; // FragmentKind::Items doesn't parse attrs? + let macro_items = ast::MacroItems::cast(parsed.syntax_node()).ok_or_else(|| { + debug!("derive node didn't parse"); + mbe::ExpandError::UnexpectedToken + })?; + let item = macro_items.items().next().ok_or_else(|| { + debug!("no module item parsed"); + mbe::ExpandError::NoMatchingRule + })?; + let node = item.syntax(); + let (name, params) = match_ast! { + match node { + ast::StructDef(it) => { (it.name(), it.type_param_list()) }, + ast::EnumDef(it) => { (it.name(), it.type_param_list()) }, + ast::UnionDef(it) => { (it.name(), it.type_param_list()) }, + _ => { + debug!("unexpected node is {:?}", node); + return Err(mbe::ExpandError::ConversionError) + }, + } + }; + let name = name.ok_or_else(|| { + debug!("parsed item has no name"); + mbe::ExpandError::NoMatchingRule + })?; + let name_token_id = token_map.token_by_range(name.syntax().text_range()).ok_or_else(|| { + debug!("name token not found"); + mbe::ExpandError::ConversionError + })?; + let name_token = tt::Ident { id: name_token_id, text: name.text().clone() }; + let type_params = params.map_or(0, |type_param_list| type_param_list.type_params().count()); + Ok(BasicAdtInfo { name: name_token, type_params }) +} + +fn make_type_args(n: usize, bound: Vec) -> Vec { + let mut result = Vec::::new(); + result.push(tt::Leaf::Punct(tt::Punct { char: '<', spacing: tt::Spacing::Alone }).into()); + for i in 0..n { + if i > 0 { + result + .push(tt::Leaf::Punct(tt::Punct { char: ',', spacing: tt::Spacing::Alone }).into()); + } + result.push( + tt::Leaf::Ident(tt::Ident { + id: tt::TokenId::unspecified(), + text: format!("T{}", i).into(), + }) + .into(), + ); + result.extend(bound.iter().cloned()); + } + result.push(tt::Leaf::Punct(tt::Punct { char: '>', spacing: tt::Spacing::Alone }).into()); + result +} + fn copy_expand( _db: &dyn AstDatabase, _id: MacroCallId, - _tt: &tt::Subtree, + tt: &tt::Subtree, ) -> Result { + let info = parse_adt(tt)?; + let name = info.name; + let bound = (quote! { : std::marker::Copy }).token_trees; + let type_params = make_type_args(info.type_params, bound); + let type_args = make_type_args(info.type_params, Vec::new()); let expanded = quote! { - impl Copy for Foo {} + impl ##type_params std::marker::Copy for #name ##type_args {} }; Ok(expanded) } @@ -55,10 +128,110 @@ fn copy_expand( fn clone_expand( _db: &dyn AstDatabase, _id: MacroCallId, - _tt: &tt::Subtree, + tt: &tt::Subtree, ) -> Result { + let info = parse_adt(tt)?; + let name = info.name; + let bound = (quote! { : std::clone::Clone }).token_trees; + let type_params = make_type_args(info.type_params, bound); + let type_args = make_type_args(info.type_params, Vec::new()); let expanded = quote! { - impl Clone for Foo {} + impl ##type_params std::clone::Clone for #name ##type_args {} }; Ok(expanded) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{test_db::TestDB, AstId, MacroCallKind, MacroCallLoc, MacroFileKind}; + use ra_db::{fixture::WithFixture, SourceDatabase}; + + fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String { + let (db, file_id) = TestDB::with_single_file(&s); + let parsed = db.parse(file_id); + let items: Vec<_> = + parsed.syntax_node().descendants().filter_map(|it| ast::ModuleItem::cast(it)).collect(); + + let ast_id_map = db.ast_id_map(file_id.into()); + + // the first one should be a macro_rules + let def = + MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(expander) }; + + let loc = MacroCallLoc { + def, + kind: MacroCallKind::Attr(AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]))), + }; + + let id = db.intern_macro(loc); + let parsed = db.parse_or_expand(id.as_file(MacroFileKind::Items)).unwrap(); + + // FIXME text() for syntax nodes parsed from token tree looks weird + // because there's no whitespace, see below + parsed.text().to_string() + } + + #[test] + fn test_copy_expand_simple() { + let expanded = expand_builtin_derive( + r#" + #[derive(Copy)] + struct Foo; +"#, + BuiltinDeriveExpander::Copy, + ); + + assert_eq!(expanded, "impl <>std::marker::CopyforFoo <>{}"); + } + + #[test] + fn test_copy_expand_with_type_params() { + let expanded = expand_builtin_derive( + r#" + #[derive(Copy)] + struct Foo; +"#, + BuiltinDeriveExpander::Copy, + ); + + assert_eq!( + expanded, + "implstd::marker::CopyforFoo{}" + ); + } + + #[test] + fn test_copy_expand_with_lifetimes() { + let expanded = expand_builtin_derive( + r#" + #[derive(Copy)] + struct Foo; +"#, + BuiltinDeriveExpander::Copy, + ); + + // We currently just ignore lifetimes + + assert_eq!( + expanded, + "implstd::marker::CopyforFoo{}" + ); + } + + #[test] + fn test_clone_expand() { + let expanded = expand_builtin_derive( + r#" + #[derive(Clone)] + struct Foo; +"#, + BuiltinDeriveExpander::Clone, + ); + + assert_eq!( + expanded, + "implstd::clone::CloneforFoo{}" + ); + } +} diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 65a35e52fa..4f698ff134 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -60,6 +60,15 @@ macro_rules! __quote { } }; + ( ## $first:ident $($tail:tt)* ) => { + { + let mut tokens = $first.into_iter().map($crate::quote::ToTokenTree::to_token).collect::>(); + let mut tail_tokens = $crate::quote::IntoTt::to_tokens($crate::__quote!($($tail)*)); + tokens.append(&mut tail_tokens); + tokens + } + }; + // Brace ( { $($tt:tt)* } ) => { $crate::__quote!(@SUBTREE Brace $($tt)*) }; // Bracket @@ -85,6 +94,7 @@ macro_rules! __quote { ( & ) => {$crate::__quote!(@PUNCT '&')}; ( , ) => {$crate::__quote!(@PUNCT ',')}; ( : ) => {$crate::__quote!(@PUNCT ':')}; + ( :: ) => {$crate::__quote!(@PUNCT ':', ':')}; ( . ) => {$crate::__quote!(@PUNCT '.')}; ( $first:tt $($tail:tt)+ ) => { diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 0d9a35ce08..9c29a054e2 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -266,3 +266,54 @@ fn main() { "### ); } + +#[test] +fn infer_derive_clone_simple() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std +#[derive(Clone)] +struct S; +fn test() { + S.clone()<|>; +} + +//- /lib.rs crate:std +#[prelude_import] +use clone::*; +mod clone { + trait Clone { + fn clone(&self) -> Self; + } +} +"#, + ); + assert_eq!("S", type_at_pos(&db, pos)); +} + +#[test] +fn infer_derive_clone_with_params() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std +#[derive(Clone)] +struct S; +#[derive(Clone)] +struct Wrapper(T); +struct NonClone; +fn test() { + (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>; +} + +//- /lib.rs crate:std +#[prelude_import] +use clone::*; +mod clone { + trait Clone { + fn clone(&self) -> Self; + } +} +"#, + ); + assert_eq!("(Wrapper, {unknown})", type_at_pos(&db, pos)); +} From 10697041c1c72ddbe27c41912e691656be6ccce4 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 19:52:52 +0100 Subject: [PATCH 063/312] Implement all the other built-in derives Since as long as we're not implementing the bodies, they all work the same way. --- crates/ra_hir_expand/src/builtin_derive.rs | 102 +++++++++++++++++---- crates/ra_hir_expand/src/name.rs | 7 ++ 2 files changed, 90 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index fde50f7e6d..78fa9b09a2 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -45,7 +45,14 @@ macro_rules! register_builtin { register_builtin! { (COPY_TRAIT, Copy) => copy_expand, - (CLONE_TRAIT, Clone) => clone_expand + (CLONE_TRAIT, Clone) => clone_expand, + (DEFAULT_TRAIT, Default) => default_expand, + (DEBUG_TRAIT, Debug) => debug_expand, + (HASH_TRAIT, Hash) => hash_expand, + (ORD_TRAIT, Ord) => ord_expand, + (PARTIAL_ORD_TRAIT, PartialOrd) => partial_ord_expand, + (EQ_TRAIT, Eq) => eq_expand, + (PARTIAL_EQ_TRAIT, PartialEq) => partial_eq_expand } struct BasicAdtInfo { @@ -109,20 +116,29 @@ fn make_type_args(n: usize, bound: Vec) -> Vec { result } +fn expand_simple_derive( + tt: &tt::Subtree, + trait_path: tt::Subtree, +) -> Result { + let info = parse_adt(tt)?; + let name = info.name; + let trait_path_clone = trait_path.token_trees.clone(); + let bound = (quote! { : ##trait_path_clone }).token_trees; + let type_params = make_type_args(info.type_params, bound); + let type_args = make_type_args(info.type_params, Vec::new()); + let trait_path = trait_path.token_trees; + let expanded = quote! { + impl ##type_params ##trait_path for #name ##type_args {} + }; + Ok(expanded) +} + fn copy_expand( _db: &dyn AstDatabase, _id: MacroCallId, tt: &tt::Subtree, ) -> Result { - let info = parse_adt(tt)?; - let name = info.name; - let bound = (quote! { : std::marker::Copy }).token_trees; - let type_params = make_type_args(info.type_params, bound); - let type_args = make_type_args(info.type_params, Vec::new()); - let expanded = quote! { - impl ##type_params std::marker::Copy for #name ##type_args {} - }; - Ok(expanded) + expand_simple_derive(tt, quote! { std::marker::Copy }) } fn clone_expand( @@ -130,15 +146,63 @@ fn clone_expand( _id: MacroCallId, tt: &tt::Subtree, ) -> Result { - let info = parse_adt(tt)?; - let name = info.name; - let bound = (quote! { : std::clone::Clone }).token_trees; - let type_params = make_type_args(info.type_params, bound); - let type_args = make_type_args(info.type_params, Vec::new()); - let expanded = quote! { - impl ##type_params std::clone::Clone for #name ##type_args {} - }; - Ok(expanded) + expand_simple_derive(tt, quote! { std::clone::Clone }) +} + +fn default_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::default::Default }) +} + +fn debug_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::fmt::Debug }) +} + +fn hash_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::hash::Hash }) +} + +fn eq_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::cmp::Eq }) +} + +fn partial_eq_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::cmp::PartialEq }) +} + +fn ord_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::cmp::Ord }) +} + +fn partial_ord_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + tt: &tt::Subtree, +) -> Result { + expand_simple_derive(tt, quote! { std::cmp::PartialOrd }) } #[cfg(test)] diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 86709b5cf2..c5a1911609 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -163,3 +163,10 @@ pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); // Builtin derives pub const COPY_TRAIT: Name = Name::new_inline_ascii(4, b"Copy"); pub const CLONE_TRAIT: Name = Name::new_inline_ascii(5, b"Clone"); +pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(7, b"Default"); +pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(5, b"Debug"); +pub const HASH_TRAIT: Name = Name::new_inline_ascii(4, b"Hash"); +pub const ORD_TRAIT: Name = Name::new_inline_ascii(3, b"Ord"); +pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(10, b"PartialOrd"); +pub const EQ_TRAIT: Name = Name::new_inline_ascii(2, b"Eq"); +pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(9, b"PartialEq"); From b84ce79f911014dfed6bc9d31d6699bc123d3561 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Dec 2019 21:17:17 +0100 Subject: [PATCH 064/312] Simplify test --- crates/ra_hir_ty/src/tests.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index c520bb375e..9f373a8f41 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -11,8 +11,8 @@ use std::fmt::Write; use std::sync::Arc; use hir_def::{ - body::BodySourceMap, db::DefDatabase, nameres::CrateDefMap, AssocItemId, DefWithBodyId, - LocalModuleId, Lookup, ModuleDefId, + body::BodySourceMap, child_from_source::ChildFromSource, db::DefDatabase, nameres::CrateDefMap, + AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, }; use hir_expand::InFile; use insta::assert_snapshot; @@ -31,18 +31,15 @@ use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResu fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { let file = db.parse(pos.file_id).ok().unwrap(); let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); - + let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let module = db.module_for_file(pos.file_id); - let crate_def_map = db.crate_def_map(module.krate); - for decl in crate_def_map[module.local_id].scope.declarations() { - if let ModuleDefId::FunctionId(func) = decl { - let (_body, source_map) = db.body_with_source_map(func.into()); - if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { - let infer = db.infer(func.into()); - let ty = &infer[expr_id]; - return ty.display(db).to_string(); - } - } + let func = module.child_from_source(db, InFile::new(pos.file_id.into(), fn_def)).unwrap(); + + let (_body, source_map) = db.body_with_source_map(func.into()); + if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { + let infer = db.infer(func.into()); + let ty = &infer[expr_id]; + return ty.display(db).to_string(); } panic!("Can't find expression") } From ab7469240cfe73bbac41d10226c3a819fc78b22a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 6 Dec 2019 11:41:51 +0800 Subject: [PATCH 065/312] Fix npm vulnerability warning --- editors/code/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index e6bcbfa602..2ceac60a09 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -598,9 +598,9 @@ } }, "https-proxy-agent": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz", - "integrity": "sha512-c8Ndjc9Bkpfx/vCJueCPy0jlP4ccCCSNDp8xwCZzPjKJUm+B+u9WX2x98Qx4n1PiMNTWo3D7KK5ifNV/yJyRzg==", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", + "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", "dev": true, "requires": { "agent-base": "^4.3.0", From f86fe3d891ab295e9e394a1338da86524a6205d3 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Thu, 5 Dec 2019 23:02:31 +0100 Subject: [PATCH 066/312] Don't unify within a reference If we are expecting a `&Foo` and get a `&something`, when checking the `something`, we are *expecting* a `Foo`, but we shouldn't try to unify whatever we get with that expectation, because it could actually be a `&Foo`, and `&&Foo` coerces to `&Foo`. So this fixes quite a few false type mismatches. --- crates/ra_hir_ty/src/infer/expr.rs | 21 +++++++-------- crates/ra_hir_ty/src/tests.rs | 26 +++++++++++++++++++ crates/ra_hir_ty/src/tests/coercion.rs | 36 ++++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 1e78f6efd4..b8df277063 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -201,7 +201,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Return { expr } => { if let Some(expr) = expr { - self.infer_expr(*expr, &Expectation::has_type(self.return_ty.clone())); + self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); } Ty::simple(TypeCtor::Never) } @@ -245,7 +245,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Field { expr, name } => { - let receiver_ty = self.infer_expr(*expr, &Expectation::none()); + let receiver_ty = self.infer_expr_inner(*expr, &Expectation::none()); let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); let ty = autoderef::autoderef( self.db, @@ -280,7 +280,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.normalize_associated_types_in(ty) } Expr::Await { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let ty = match self.resolve_future_future_output() { Some(future_future_output_alias) => { let ty = self.table.new_type_var(); @@ -299,7 +299,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Try { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let ty = match self.resolve_ops_try_ok() { Some(ops_try_ok_alias) => { let ty = self.table.new_type_var(); @@ -318,7 +318,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { ty } Expr::Cast { expr, type_ref } => { - let _inner_ty = self.infer_expr(*expr, &Expectation::none()); + let _inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); let cast_ty = self.make_ty(type_ref); // FIXME check the cast... cast_ty @@ -334,12 +334,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } else { Expectation::none() }; - // FIXME reference coercions etc. - let inner_ty = self.infer_expr(*expr, &expectation); + let inner_ty = self.infer_expr_inner(*expr, &expectation); Ty::apply_one(TypeCtor::Ref(*mutability), inner_ty) } Expr::Box { expr } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); if let Some(box_) = self.resolve_boxed_box() { Ty::apply_one(TypeCtor::Adt(box_), inner_ty) } else { @@ -347,7 +346,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } Expr::UnaryOp { expr, op } => { - let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); match op { UnaryOp::Deref => match self.resolver.krate() { Some(krate) => { @@ -417,7 +416,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { _ => Ty::Unknown, }, Expr::Range { lhs, rhs, range_type } => { - let lhs_ty = lhs.map(|e| self.infer_expr(e, &Expectation::none())); + let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none())); let rhs_expect = lhs_ty .as_ref() .map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone())); @@ -455,7 +454,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } Expr::Index { base, index } => { - let _base_ty = self.infer_expr(*base, &Expectation::none()); + let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); let _index_ty = self.infer_expr(*index, &Expectation::none()); // FIXME: use `std::ops::Index::Output` to figure out the real return type Ty::Unknown diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 9f373a8f41..f1b67555f2 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -50,6 +50,10 @@ fn type_at(content: &str) -> String { } fn infer(content: &str) -> String { + infer_with_mismatches(content, false) +} + +fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { let (db, file_id) = TestDB::with_single_file(content); let mut acc = String::new(); @@ -57,6 +61,7 @@ fn infer(content: &str) -> String { let mut infer_def = |inference_result: Arc, body_source_map: Arc| { let mut types = Vec::new(); + let mut mismatches = Vec::new(); for (pat, ty) in inference_result.type_of_pat.iter() { let syntax_ptr = match body_source_map.pat_syntax(pat) { @@ -76,6 +81,9 @@ fn infer(content: &str) -> String { None => continue, }; types.push((syntax_ptr, ty)); + if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { + mismatches.push((syntax_ptr, mismatch)); + } } // sort ranges for consistency @@ -101,6 +109,24 @@ fn infer(content: &str) -> String { ) .unwrap(); } + if include_mismatches { + mismatches.sort_by_key(|(src_ptr, _)| { + (src_ptr.value.range().start(), src_ptr.value.range().end()) + }); + for (src_ptr, mismatch) in &mismatches { + let range = src_ptr.value.range(); + let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; + write!( + acc, + "{}{}: expected {}, got {}\n", + macro_prefix, + range, + mismatch.expected.display(&db), + mismatch.actual.display(&db), + ) + .unwrap(); + } + } }; let module = db.module_for_file(file_id); diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 1530fcc637..58b22396fc 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs @@ -1,3 +1,4 @@ +use super::infer_with_mismatches; use insta::assert_snapshot; use test_utils::covers; @@ -367,3 +368,38 @@ fn test() { "### ); } + +#[test] +fn coerce_autoderef() { + assert_snapshot!( + infer_with_mismatches(r#" +struct Foo; +fn takes_ref_foo(x: &Foo) {} +fn test() { + takes_ref_foo(&Foo); + takes_ref_foo(&&Foo); + takes_ref_foo(&&&Foo); +} +"#, true), + @r###" + [30; 31) 'x': &Foo + [39; 41) '{}': () + [52; 133) '{ ...oo); }': () + [58; 71) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () + [58; 77) 'takes_...(&Foo)': () + [72; 76) '&Foo': &Foo + [73; 76) 'Foo': Foo + [83; 96) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () + [83; 103) 'takes_...&&Foo)': () + [97; 102) '&&Foo': &&Foo + [98; 102) '&Foo': &Foo + [99; 102) 'Foo': Foo + [109; 122) 'takes_ref_foo': fn takes_ref_foo(&Foo) -> () + [109; 130) 'takes_...&&Foo)': () + [123; 129) '&&&Foo': &&&Foo + [124; 129) '&&Foo': &&Foo + [125; 129) '&Foo': &Foo + [126; 129) 'Foo': Foo + "### + ); +} From 76ff5b7c15b2c4e85895a49e5859e546d1d6227e Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 3 Dec 2019 19:33:48 +0800 Subject: [PATCH 067/312] Add tests --- crates/ra_hir_def/src/nameres/tests.rs | 32 ++++++++++++++++++++++++++ crates/ra_hir_ty/src/tests/macros.rs | 29 +++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 87fcd617c5..61cdd768e8 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -558,3 +558,35 @@ fn cfg_test() { â‹®Foo: t v "###); } + +#[test] +fn infer_multiple_namespace() { + let map = def_map( + r#" +//- /main.rs +mod a { + pub type T = (); + pub use crate::b::*; +} + +use crate::a::T; + +mod b { + pub const T: () = (); +} +"#, + ); + + assert_snapshot!(map, @r###" + â‹®crate + â‹®T: t v + â‹®a: t + â‹®b: t + â‹® + â‹®crate::b + â‹®T: v + â‹® + â‹®crate::a + â‹®T: t v +"###); +} diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 9c29a054e2..812f171db8 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -210,6 +210,35 @@ pub fn baz() -> usize { 31usize } assert_eq!("(i32, usize)", type_at_pos(&db, pos)); } +#[test] +fn infer_type_value_non_legacy_macro_use_as() { + assert_snapshot!( + infer(r#" +mod m { + macro_rules! _foo { + ($x:ident) => { type $x = u64; } + } + pub(crate) use _foo as foo; +} + +m::foo!(foo); +use foo as bar; +fn f() -> bar { 0 } +fn main() { + let _a = f(); +} +"#), + @r###" + [159; 164) '{ 0 }': u64 + [161; 162) '0': u64 + [175; 199) '{ ...f(); }': () + [187; 189) '_a': u64 + [193; 194) 'f': fn f() -> u64 + [193; 196) 'f()': u64 + "### + ); +} + #[test] fn infer_builtin_macros_line() { assert_snapshot!( From c5ffb0dc815358712a42f9358cc3538f9a7b3014 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 10:57:20 +0100 Subject: [PATCH 068/312] Add stub implementation of format_args{_nl} macros Just enough to fix the huge amount of type mismatches they cause. --- crates/ra_hir_expand/src/builtin_macro.rs | 19 ++++++++++++++++++- crates/ra_hir_expand/src/name.rs | 2 ++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 35f99b2bc4..e0709704a0 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -49,7 +49,11 @@ register_builtin! { (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand, (FILE_MACRO, File) => file_expand, (LINE_MACRO, Line) => line_expand, - (STRINGIFY_MACRO, Stringify) => stringify_expand + (STRINGIFY_MACRO, Stringify) => stringify_expand, + (FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand, + // format_args_nl only differs in that it adds a newline in the end, + // so we use the same stub expansion for now + (FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand } fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { @@ -200,6 +204,19 @@ fn compile_error_expand( Err(mbe::ExpandError::BindingError("Must be a string".into())) } +fn format_args_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + // FIXME this is just a stub to make format macros type-check without mismatches + // We should make this at least insert the arguments, so that go to def etc. work within format macros + let expanded = quote! { + std::fmt::Arguments::new_v1(&[], &[]) + }; + Ok(expanded) +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index c5a1911609..34edf2003a 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -159,6 +159,8 @@ pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error"); pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); +pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(11, b"format_args"); +pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(14, b"format_args_nl"); // Builtin derives pub const COPY_TRAIT: Name = Name::new_inline_ascii(4, b"Copy"); From 3a5aa03e66f1b46218f152f1e3e3db3bb1bd8077 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 10:59:10 +0100 Subject: [PATCH 069/312] Remove unnecessary len parameter for Name::new_inline_ascii I assume it was previously required because `len` was not const, but that doesn't seem to be a problem anymore. --- crates/ra_hir_expand/src/name.rs | 118 +++++++++++++++---------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 34edf2003a..4f2f702c01 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -38,8 +38,8 @@ impl Name { } /// Shortcut to create inline plain text name - const fn new_inline_ascii(len: usize, text: &[u8]) -> Name { - Name::new_text(SmolStr::new_inline_from_ascii(len, text)) + const fn new_inline_ascii(text: &[u8]) -> Name { + Name::new_text(SmolStr::new_inline_from_ascii(text.len(), text)) } /// Resolve a name from the text of token. @@ -105,70 +105,70 @@ impl AsName for ra_db::Dependency { } // Primitives -pub const ISIZE: Name = Name::new_inline_ascii(5, b"isize"); -pub const I8: Name = Name::new_inline_ascii(2, b"i8"); -pub const I16: Name = Name::new_inline_ascii(3, b"i16"); -pub const I32: Name = Name::new_inline_ascii(3, b"i32"); -pub const I64: Name = Name::new_inline_ascii(3, b"i64"); -pub const I128: Name = Name::new_inline_ascii(4, b"i128"); -pub const USIZE: Name = Name::new_inline_ascii(5, b"usize"); -pub const U8: Name = Name::new_inline_ascii(2, b"u8"); -pub const U16: Name = Name::new_inline_ascii(3, b"u16"); -pub const U32: Name = Name::new_inline_ascii(3, b"u32"); -pub const U64: Name = Name::new_inline_ascii(3, b"u64"); -pub const U128: Name = Name::new_inline_ascii(4, b"u128"); -pub const F32: Name = Name::new_inline_ascii(3, b"f32"); -pub const F64: Name = Name::new_inline_ascii(3, b"f64"); -pub const BOOL: Name = Name::new_inline_ascii(4, b"bool"); -pub const CHAR: Name = Name::new_inline_ascii(4, b"char"); -pub const STR: Name = Name::new_inline_ascii(3, b"str"); +pub const ISIZE: Name = Name::new_inline_ascii(b"isize"); +pub const I8: Name = Name::new_inline_ascii(b"i8"); +pub const I16: Name = Name::new_inline_ascii(b"i16"); +pub const I32: Name = Name::new_inline_ascii(b"i32"); +pub const I64: Name = Name::new_inline_ascii(b"i64"); +pub const I128: Name = Name::new_inline_ascii(b"i128"); +pub const USIZE: Name = Name::new_inline_ascii(b"usize"); +pub const U8: Name = Name::new_inline_ascii(b"u8"); +pub const U16: Name = Name::new_inline_ascii(b"u16"); +pub const U32: Name = Name::new_inline_ascii(b"u32"); +pub const U64: Name = Name::new_inline_ascii(b"u64"); +pub const U128: Name = Name::new_inline_ascii(b"u128"); +pub const F32: Name = Name::new_inline_ascii(b"f32"); +pub const F64: Name = Name::new_inline_ascii(b"f64"); +pub const BOOL: Name = Name::new_inline_ascii(b"bool"); +pub const CHAR: Name = Name::new_inline_ascii(b"char"); +pub const STR: Name = Name::new_inline_ascii(b"str"); // Special names -pub const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self"); -pub const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self"); -pub const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules"); +pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self"); +pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self"); +pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules"); // Components of known path (value or mod name) -pub const STD: Name = Name::new_inline_ascii(3, b"std"); -pub const ITER: Name = Name::new_inline_ascii(4, b"iter"); -pub const OPS: Name = Name::new_inline_ascii(3, b"ops"); -pub const FUTURE: Name = Name::new_inline_ascii(6, b"future"); -pub const RESULT: Name = Name::new_inline_ascii(6, b"result"); -pub const BOXED: Name = Name::new_inline_ascii(5, b"boxed"); +pub const STD: Name = Name::new_inline_ascii(b"std"); +pub const ITER: Name = Name::new_inline_ascii(b"iter"); +pub const OPS: Name = Name::new_inline_ascii(b"ops"); +pub const FUTURE: Name = Name::new_inline_ascii(b"future"); +pub const RESULT: Name = Name::new_inline_ascii(b"result"); +pub const BOXED: Name = Name::new_inline_ascii(b"boxed"); // Components of known path (type name) -pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator"); -pub const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item"); -pub const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try"); -pub const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok"); -pub const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future"); -pub const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result"); -pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output"); -pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target"); -pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); -pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(9, b"RangeFrom"); -pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(9, b"RangeFull"); -pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(14, b"RangeInclusive"); -pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(16, b"RangeToInclusive"); -pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(7, b"RangeTo"); -pub const RANGE_TYPE: Name = Name::new_inline_ascii(5, b"Range"); +pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator"); +pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item"); +pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try"); +pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok"); +pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future"); +pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result"); +pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output"); +pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target"); +pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box"); +pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom"); +pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull"); +pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive"); +pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive"); +pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo"); +pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range"); // Builtin Macros -pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); -pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); -pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error"); -pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); -pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); -pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(11, b"format_args"); -pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(14, b"format_args_nl"); +pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file"); +pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column"); +pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error"); +pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line"); +pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify"); +pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args"); +pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl"); // Builtin derives -pub const COPY_TRAIT: Name = Name::new_inline_ascii(4, b"Copy"); -pub const CLONE_TRAIT: Name = Name::new_inline_ascii(5, b"Clone"); -pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(7, b"Default"); -pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(5, b"Debug"); -pub const HASH_TRAIT: Name = Name::new_inline_ascii(4, b"Hash"); -pub const ORD_TRAIT: Name = Name::new_inline_ascii(3, b"Ord"); -pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(10, b"PartialOrd"); -pub const EQ_TRAIT: Name = Name::new_inline_ascii(2, b"Eq"); -pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(9, b"PartialEq"); +pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy"); +pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone"); +pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default"); +pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug"); +pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash"); +pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord"); +pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd"); +pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq"); +pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq"); From eae425b10fd7803ae67d2d39e9aca902daa353ba Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 19:30:01 +0100 Subject: [PATCH 070/312] Implement format_args more properly --- crates/ra_hir_expand/src/builtin_macro.rs | 47 +++++++++++++++++++++-- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index e0709704a0..99303188bf 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -207,12 +207,34 @@ fn compile_error_expand( fn format_args_expand( _db: &dyn AstDatabase, _id: MacroCallId, - _tt: &tt::Subtree, + tt: &tt::Subtree, ) -> Result { - // FIXME this is just a stub to make format macros type-check without mismatches - // We should make this at least insert the arguments, so that go to def etc. work within format macros + // We expand `format_args!("", arg1, arg2)` to + // `std::fmt::Arguments::new_v1(&[], &[&arg1, &arg2])`, + // which is still not really correct, but close enough for now + let mut args = Vec::new(); + let mut current = Vec::new(); + for tt in tt.token_trees.iter().cloned() { + match tt { + tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { + args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + current = Vec::new(); + } + _ => { + current.push(tt); + } + } + } + if !current.is_empty() { + args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + } + if args.is_empty() { + return Err(mbe::ExpandError::NoMatchingRule); + } + let _format_string = args.remove(0); + let arg_tts = args.into_iter().flat_map(|arg| (quote! { & #arg , }).token_trees); let expanded = quote! { - std::fmt::Arguments::new_v1(&[], &[]) + std::fmt::Arguments::new_v1(&[], &[##arg_tts]) }; Ok(expanded) } @@ -324,4 +346,21 @@ mod tests { assert_eq!(expanded, r#"loop{"error!"}"#); } + + #[test] + fn test_format_args_expand() { + let expanded = expand_builtin_macro( + r#" + #[rustc_builtin_macro] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + } + format_args!("{} {:?}", arg1(a, b, c), arg2); +"#, + BuiltinFnLikeExpander::FormatArgs, + ); + + assert_eq!(expanded, r#"std::fmt::Arguments::new_v1(&[] ,&[&arg1(a,b,c),&arg2,])"#); + } } From a565072ddeac519eea3b415a57e9fd208e20e562 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 19:30:15 +0100 Subject: [PATCH 071/312] Try to make go to definition work in format! SourceAnalyzer didn't work properly within expression macro expansions because it didn't find the enclosing function. Fix this by going up the expansion chain to find ancestors. This makes the test work, but apparently in real usage it's still not working. --- crates/ra_hir/src/source_binder.rs | 23 ++++++++++++++++++----- crates/ra_hir_expand/src/lib.rs | 18 ++++++++++++++++++ crates/ra_ide/src/goto_definition.rs | 27 +++++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 42c3925135..cb4345ca14 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -76,18 +76,30 @@ fn def_with_body_from_child_node( db: &impl HirDatabase, child: InFile<&SyntaxNode>, ) -> Option { - child.value.ancestors().find_map(|node| { + ancestors_with_macros(db, child).find_map(|node| { + let n = &node.value; match_ast! { - match node { - ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); }, - ast::StaticDef(def) => { return Static::from_source(db, child.with_value(def)).map(DefWithBody::from); }, + match n { + ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); }, + ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); }, + ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); }, _ => { None }, } } }) } +fn ancestors_with_macros<'a>( + db: &'a (impl HirDatabase), + node: InFile<&SyntaxNode>, +) -> impl Iterator> + 'a { + let file = node.with_value(()); // keep just the file id for borrow checker purposes + let parent_node = node.file_id.call_node(db); + let parent_ancestors: Box>> = + Box::new(parent_node.into_iter().flat_map(move |n| ancestors_with_macros(db, n.as_ref()))); + node.value.ancestors().map(move |n| file.with_value(n)).chain(parent_ancestors) +} + /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] @@ -135,6 +147,7 @@ pub struct ReferenceDescriptor { pub name: String, } +#[derive(Debug)] pub struct Expansion { macro_file_kind: MacroFileKind, macro_call_id: MacroCallId, diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 59c69b91bb..0c1dc87e67 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -76,6 +76,17 @@ impl HirFileId { } } + /// If this is a macro call, returns the syntax node of the call. + pub fn call_node(self, db: &dyn db::AstDatabase) -> Option> { + match self.0 { + HirFileIdRepr::FileId(_) => None, + HirFileIdRepr::MacroFile(macro_file) => { + let loc = db.lookup_intern_macro(macro_file.macro_call_id); + Some(loc.kind.node(db)) + } + } + } + /// Return expansion information if it is a macro-expansion file pub fn expansion_info(self, db: &dyn db::AstDatabase) -> Option { match self.0 { @@ -176,6 +187,13 @@ impl MacroCallKind { } } + pub fn node(&self, db: &dyn db::AstDatabase) -> InFile { + match self { + MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), + MacroCallKind::Attr(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), + } + } + pub fn arg(&self, db: &dyn db::AstDatabase) -> Option { match self { MacroCallKind::FnLike(ast_id) => { diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 76a7412076..b1d567ca77 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -693,4 +693,31 @@ mod tests { "foo FN_DEF FileId(1) [52; 63) [55; 58)", ); } + + #[test] + fn goto_through_format() { + check_goto( + " + //- /lib.rs + #[macro_export] + macro_rules! format { + ($($arg:tt)*) => ($crate::fmt::format($crate::__export::format_args!($($arg)*))) + } + #[rustc_builtin_macro] + #[macro_export] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + } + pub mod __export { + pub use crate::format_args; + } + fn foo() -> i8 {} + fn test() { + format!(\"{}\", fo<|>o()) + } + ", + "foo FN_DEF FileId(1) [359; 376) [362; 365)", + ); + } } From 4a99ef5c39e670162ea3c35d53ccd75b81281865 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 21:21:39 +0100 Subject: [PATCH 072/312] Builtin macros only use caller tokens --- crates/ra_hir_expand/src/db.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 99dabf3fbb..013a6c8ba9 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -45,8 +45,8 @@ impl TokenExpander { pub fn map_id_up(&self, id: tt::TokenId) -> (tt::TokenId, mbe::Origin) { match self { TokenExpander::MacroRules(it) => it.map_id_up(id), - TokenExpander::Builtin(..) => (id, mbe::Origin::Def), - TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Def), + TokenExpander::Builtin(..) => (id, mbe::Origin::Call), + TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call), } } } From c80dc0ad3aee717f9d15c11d300d0eb1c10f1cc8 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 21:24:41 +0100 Subject: [PATCH 073/312] Make the goto_through_format test actually fail :( --- crates/ra_ide/src/goto_definition.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index b1d567ca77..d3c1988132 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -689,11 +689,13 @@ mod tests { fo<|>o(); } } + mod confuse_index { fn foo(); } ", "foo FN_DEF FileId(1) [52; 63) [55; 58)", ); } + #[should_panic] // currently failing because of expr mapping problems #[test] fn goto_through_format() { check_goto( @@ -711,6 +713,7 @@ mod tests { } pub mod __export { pub use crate::format_args; + fn foo() {} // for index confusion } fn foo() -> i8 {} fn test() { From 8c86963d47953045f2f33ee6620d305a6589641e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 5 Dec 2019 23:34:12 +0100 Subject: [PATCH 074/312] DynMap This might, or might not help us to reduce boilerplate associated with plumbing values from analysis to the IDE layer --- Cargo.lock | 7 + crates/ra_hir/src/from_source.rs | 74 +++--- crates/ra_hir_def/Cargo.toml | 1 + crates/ra_hir_def/src/child_by_source.rs | 139 +++++++++++ crates/ra_hir_def/src/child_from_source.rs | 276 --------------------- crates/ra_hir_def/src/dyn_map.rs | 108 ++++++++ crates/ra_hir_def/src/keys.rs | 48 ++++ crates/ra_hir_def/src/lib.rs | 5 +- crates/ra_hir_ty/src/tests.rs | 8 +- crates/ra_syntax/src/ptr.rs | 14 +- 10 files changed, 362 insertions(+), 318 deletions(-) create mode 100644 crates/ra_hir_def/src/child_by_source.rs delete mode 100644 crates/ra_hir_def/src/child_from_source.rs create mode 100644 crates/ra_hir_def/src/dyn_map.rs create mode 100644 crates/ra_hir_def/src/keys.rs diff --git a/Cargo.lock b/Cargo.lock index 0e7594f807..a95f9139f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,11 @@ name = "anyhow" version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "anymap" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "arrayvec" version = "0.5.1" @@ -958,6 +963,7 @@ dependencies = [ name = "ra_hir_def" version = "0.1.0" dependencies = [ + "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1776,6 +1782,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14" +"checksum anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" "checksum arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 5cb222bd38..437f800c1e 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,9 +1,7 @@ //! FIXME: write short doc here -use either::Either; - use hir_def::{ - child_from_source::ChildFromSource, nameres::ModuleSource, AstItemDef, EnumVariantId, ImplId, - LocationCtx, ModuleId, TraitId, VariantId, + child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef, + EnumVariantId, LocationCtx, ModuleId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -53,8 +51,9 @@ impl FromSource for Trait { impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))? - .child_from_source(db, src) + Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::FUNCTION] + .get(&src) + .copied() .map(Function::from) } } @@ -62,26 +61,29 @@ impl FromSource for Function { impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))? - .child_from_source(db, src) + Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::CONST] + .get(&src) + .copied() .map(Const::from) } } impl FromSource for Static { type Ast = ast::StaticDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - match Container::find(db, src.as_ref().map(|it| it.syntax()))? { - Container::Module(it) => it.id.child_from_source(db, src).map(Static::from), - Container::Trait(_) | Container::ImplBlock(_) => None, - } + Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::STATIC] + .get(&src) + .copied() + .map(Static::from) } } impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))? - .child_from_source(db, src) + Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db) + [keys::TYPE_ALIAS] + .get(&src) + .copied() .map(TypeAlias::from) } } @@ -116,32 +118,41 @@ impl FromSource for EnumVariant { let parent_enum = src.value.parent_enum(); let src_enum = InFile { file_id: src.file_id, value: parent_enum }; let parent_enum = Enum::from_source(db, src_enum)?; - parent_enum.id.child_from_source(db, src).map(EnumVariant::from) + parent_enum.id.child_by_source(db)[keys::ENUM_VARIANT] + .get(&src) + .copied() + .map(EnumVariant::from) } } impl FromSource for StructField { type Ast = FieldSource; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + let src = src.as_ref(); + + // FIXME this is buggy let variant_id: VariantId = match src.value { - FieldSource::Named(ref field) => { + FieldSource::Named(field) => { let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?; let src = InFile { file_id: src.file_id, value }; let def = Struct::from_source(db, src)?; def.id.into() } - FieldSource::Pos(ref field) => { + FieldSource::Pos(field) => { let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; let src = InFile { file_id: src.file_id, value }; let def = EnumVariant::from_source(db, src)?; EnumVariantId::from(def).into() } }; - let src = src.map(|field_source| match field_source { - FieldSource::Pos(it) => Either::Left(it), - FieldSource::Named(it) => Either::Right(it), - }); - variant_id.child_from_source(db, src).map(StructField::from) + + let dyn_map = variant_id.child_by_source(db); + match src.value { + FieldSource::Pos(it) => dyn_map[keys::TUPLE_FIELD].get(&src.with_value(it.clone())), + FieldSource::Named(it) => dyn_map[keys::RECORD_FIELD].get(&src.with_value(it.clone())), + } + .copied() + .map(StructField::from) } } @@ -255,21 +266,12 @@ impl Container { } } -impl ChildFromSource for Container -where - TraitId: ChildFromSource, - ImplId: ChildFromSource, - ModuleId: ChildFromSource, -{ - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { +impl ChildBySource for Container { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { match self { - Container::Trait(it) => it.id.child_from_source(db, child_source), - Container::ImplBlock(it) => it.id.child_from_source(db, child_source), - Container::Module(it) => it.id.child_from_source(db, child_source), + Container::Trait(it) => it.id.child_by_source(db), + Container::ImplBlock(it) => it.id.child_by_source(db), + Container::Module(it) => it.id.child_by_source(db), } } } diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index cf3a446fcc..b1923bbf2e 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml @@ -12,6 +12,7 @@ log = "0.4.5" once_cell = "1.0.1" rustc-hash = "1.0" either = "1.5" +anymap = "0.12" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs new file mode 100644 index 0000000000..a3574a9dbb --- /dev/null +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -0,0 +1,139 @@ +//! When *constructing* `hir`, we start at some parent syntax node and recursively +//! lower the children. +//! +//! This modules allows one to go in the opposite direction: start with a syntax +//! node for a *child*, and get its hir. + +use either::Either; + +use crate::{ + db::DefDatabase, + dyn_map::DynMap, + keys, + src::{HasChildSource, HasSource}, + AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, StructFieldId, + TraitId, VariantId, +}; + +pub trait ChildBySource { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap; +} + +impl ChildBySource for TraitId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let data = db.trait_data(*self); + for (_name, item) in data.items.iter() { + match *item { + AssocItemId::FunctionId(func) => { + let src = func.lookup(db).source(db); + res[keys::FUNCTION].insert(src, func) + } + AssocItemId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + res[keys::CONST].insert(src, konst) + } + AssocItemId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + res[keys::TYPE_ALIAS].insert(src, ty) + } + } + } + + res + } +} + +impl ChildBySource for ImplId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let data = db.impl_data(*self); + for &item in data.items.iter() { + match item { + AssocItemId::FunctionId(func) => { + let src = func.lookup(db).source(db); + res[keys::FUNCTION].insert(src, func) + } + AssocItemId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + res[keys::CONST].insert(src, konst) + } + AssocItemId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + res[keys::TYPE_ALIAS].insert(src, ty) + } + } + } + + res + } +} + +impl ChildBySource for ModuleId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let crate_def_map = db.crate_def_map(self.krate); + for item in crate_def_map[self.local_id].scope.declarations() { + match item { + ModuleDefId::FunctionId(func) => { + let src = func.lookup(db).source(db); + res[keys::FUNCTION].insert(src, func) + } + ModuleDefId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + res[keys::CONST].insert(src, konst) + } + ModuleDefId::StaticId(statik) => { + let src = statik.lookup(db).source(db); + res[keys::STATIC].insert(src, statik) + } + ModuleDefId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + res[keys::TYPE_ALIAS].insert(src, ty) + } + _ => (), + } + } + + res + } +} + +impl ChildBySource for VariantId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let arena_map = self.child_source(db); + let arena_map = arena_map.as_ref(); + for (local_id, source) in arena_map.value.iter() { + let id = StructFieldId { parent: *self, local_id }; + match source { + Either::Left(source) => { + res[keys::TUPLE_FIELD].insert(arena_map.with_value(source.clone()), id) + } + Either::Right(source) => { + res[keys::RECORD_FIELD].insert(arena_map.with_value(source.clone()), id) + } + } + } + res + } +} + +impl ChildBySource for EnumId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + + let arena_map = self.child_source(db); + let arena_map = arena_map.as_ref(); + for (local_id, source) in arena_map.value.iter() { + let id = EnumVariantId { parent: *self, local_id }; + res[keys::ENUM_VARIANT].insert(arena_map.with_value(source.clone()), id) + } + + res + } +} diff --git a/crates/ra_hir_def/src/child_from_source.rs b/crates/ra_hir_def/src/child_from_source.rs deleted file mode 100644 index 37d4b78706..0000000000 --- a/crates/ra_hir_def/src/child_from_source.rs +++ /dev/null @@ -1,276 +0,0 @@ -//! When *constructing* `hir`, we start at some parent syntax node and recursively -//! lower the children. -//! -//! This modules allows one to go in the opposite direction: start with a syntax -//! node for a *child*, and get its hir. - -use either::Either; -use hir_expand::InFile; -use ra_syntax::{ast, AstNode, AstPtr}; - -use crate::{ - db::DefDatabase, - src::{HasChildSource, HasSource}, - AssocItemId, ConstId, EnumId, EnumVariantId, FunctionId, ImplId, Lookup, ModuleDefId, ModuleId, - StaticId, StructFieldId, TraitId, TypeAliasId, VariantId, -}; - -pub trait ChildFromSource { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option; -} - -impl ChildFromSource for TraitId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.trait_data(*self); - data.items - .iter() - .filter_map(|(_, item)| match item { - AssocItemId::FunctionId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ImplId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.impl_data(*self); - data.items - .iter() - .filter_map(|item| match item { - AssocItemId::FunctionId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ModuleId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let crate_def_map = db.crate_def_map(self.krate); - let res = crate_def_map[self.local_id] - .scope - .declarations() - .filter_map(|item| match item { - ModuleDefId::FunctionId(it) => Some(it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }); - res - } -} - -impl ChildFromSource for TraitId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.trait_data(*self); - data.items - .iter() - .filter_map(|(_, item)| match item { - AssocItemId::ConstId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ImplId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.impl_data(*self); - data.items - .iter() - .filter_map(|item| match item { - AssocItemId::ConstId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ModuleId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let crate_def_map = db.crate_def_map(self.krate); - let res = crate_def_map[self.local_id] - .scope - .declarations() - .filter_map(|item| match item { - ModuleDefId::ConstId(it) => Some(it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }); - res - } -} - -impl ChildFromSource for TraitId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.trait_data(*self); - data.items - .iter() - .filter_map(|(_, item)| match item { - AssocItemId::TypeAliasId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ImplId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let data = db.impl_data(*self); - data.items - .iter() - .filter_map(|item| match item { - AssocItemId::TypeAliasId(it) => Some(*it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }) - } -} - -impl ChildFromSource for ModuleId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let crate_def_map = db.crate_def_map(self.krate); - let res = crate_def_map[self.local_id] - .scope - .declarations() - .filter_map(|item| match item { - ModuleDefId::TypeAliasId(it) => Some(it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }); - res - } -} - -impl ChildFromSource for ModuleId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let crate_def_map = db.crate_def_map(self.krate); - let res = crate_def_map[self.local_id] - .scope - .declarations() - .filter_map(|item| match item { - ModuleDefId::StaticId(it) => Some(it), - _ => None, - }) - .find(|func| { - let source = func.lookup(db).source(db); - same_source(&source, &child_source) - }); - res - } -} - -impl ChildFromSource> for VariantId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile>, - ) -> Option { - let arena_map = self.child_source(db); - let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { - child_source.file_id == arena_map.file_id - && match (source, &child_source.value) { - (Either::Left(a), Either::Left(b)) => AstPtr::new(a) == AstPtr::new(b), - (Either::Right(a), Either::Right(b)) => AstPtr::new(a) == AstPtr::new(b), - _ => false, - } - })?; - Some(StructFieldId { parent: *self, local_id }) - } -} - -impl ChildFromSource for EnumId { - fn child_from_source( - &self, - db: &impl DefDatabase, - child_source: InFile, - ) -> Option { - let arena_map = self.child_source(db); - let (local_id, _) = arena_map.as_ref().value.iter().find(|(_local_id, source)| { - child_source.file_id == arena_map.file_id - && AstPtr::new(*source) == AstPtr::new(&child_source.value) - })?; - Some(EnumVariantId { parent: *self, local_id }) - } -} - -/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are -/// equal if they point to exactly the same object. -/// -/// In general, we do not guarantee that we have exactly one instance of a -/// syntax tree for each file. We probably should add such guarantee, but, for -/// the time being, we will use identity-less AstPtr comparison. -fn same_source(s1: &InFile, s2: &InFile) -> bool { - s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new) -} diff --git a/crates/ra_hir_def/src/dyn_map.rs b/crates/ra_hir_def/src/dyn_map.rs new file mode 100644 index 0000000000..6f269d7b01 --- /dev/null +++ b/crates/ra_hir_def/src/dyn_map.rs @@ -0,0 +1,108 @@ +//! This module defines a `DynMap` -- a container for heterogeneous maps. +//! +//! This means that `DynMap` stores a bunch of hash maps inside, and those maps +//! can be of different types. +//! +//! It is used like this: +//! +//! ``` +//! // keys define submaps of a `DynMap` +//! const STRING_TO_U32: Key = Key::new(); +//! const U32_TO_VEC: Key> = Key::new(); +//! +//! // Note: concrete type, no type params! +//! let mut map = DynMap::new(); +//! +//! // To access a specific map, index the `DynMap` by `Key`: +//! map[STRING_TO_U32].insert("hello".to_string(), 92); +//! let value = map[U32_TO_VEC].get(92); +//! assert!(value.is_none()); +//! ``` +//! +//! This is a work of fiction. Any similarities to Kotlin's `BindingContext` are +//! a coincidence. +use std::{ + hash::Hash, + marker::PhantomData, + ops::{Index, IndexMut}, +}; + +use anymap::Map; +use rustc_hash::FxHashMap; + +pub struct Key { + _phantom: PhantomData<(K, V, P)>, +} + +impl Key { + pub(crate) const fn new() -> Key { + Key { _phantom: PhantomData } + } +} + +impl Copy for Key {} + +impl Clone for Key { + fn clone(&self) -> Key { + *self + } +} + +pub trait Policy { + type K; + type V; + + fn insert(map: &mut DynMap, key: Self::K, value: Self::V); + fn get<'a>(map: &'a DynMap, key: &Self::K) -> Option<&'a Self::V>; +} + +impl Policy for (K, V) { + type K = K; + type V = V; + fn insert(map: &mut DynMap, key: K, value: V) { + map.map.entry::>().or_insert_with(Default::default).insert(key, value); + } + fn get<'a>(map: &'a DynMap, key: &K) -> Option<&'a V> { + map.map.get::>()?.get(key) + } +} + +pub struct DynMap { + pub(crate) map: Map, +} + +impl Default for DynMap { + fn default() -> Self { + DynMap { map: Map::new() } + } +} + +#[repr(transparent)] +pub struct KeyMap { + map: DynMap, + _phantom: PhantomData, +} + +impl KeyMap> { + pub fn insert(&mut self, key: P::K, value: P::V) { + P::insert(&mut self.map, key, value) + } + pub fn get(&self, key: &P::K) -> Option<&P::V> { + P::get(&self.map, key) + } +} + +impl Index> for DynMap { + type Output = KeyMap>; + fn index(&self, _key: Key) -> &Self::Output { + // Safe due to `#[repr(transparent)]`. + unsafe { std::mem::transmute::<&DynMap, &KeyMap>>(self) } + } +} + +impl IndexMut> for DynMap { + fn index_mut(&mut self, _key: Key) -> &mut Self::Output { + // Safe due to `#[repr(transparent)]`. + unsafe { std::mem::transmute::<&mut DynMap, &mut KeyMap>>(self) } + } +} diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs new file mode 100644 index 0000000000..447b7e3baa --- /dev/null +++ b/crates/ra_hir_def/src/keys.rs @@ -0,0 +1,48 @@ +//! keys to be used with `DynMap` + +use std::marker::PhantomData; + +use hir_expand::InFile; +use ra_syntax::{ast, AstNode, AstPtr}; +use rustc_hash::FxHashMap; + +use crate::{ + dyn_map::{DynMap, Policy}, + ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, +}; + +type Key = crate::dyn_map::Key, V, AstPtrPolicy>; + +pub const FUNCTION: Key = Key::new(); +pub const CONST: Key = Key::new(); +pub const STATIC: Key = Key::new(); +pub const ENUM_VARIANT: Key = Key::new(); +pub const TYPE_ALIAS: Key = Key::new(); +pub const TUPLE_FIELD: Key = Key::new(); +pub const RECORD_FIELD: Key = Key::new(); + +/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are +/// equal if they point to exactly the same object. +/// +/// In general, we do not guarantee that we have exactly one instance of a +/// syntax tree for each file. We probably should add such guarantee, but, for +/// the time being, we will use identity-less AstPtr comparison. +pub struct AstPtrPolicy { + _phantom: PhantomData<(AST, ID)>, +} + +impl Policy for AstPtrPolicy { + type K = InFile; + type V = ID; + fn insert(map: &mut DynMap, key: InFile, value: ID) { + let key = key.as_ref().map(AstPtr::new); + map.map + .entry::>, ID>>() + .or_insert_with(Default::default) + .insert(key, value); + } + fn get<'a>(map: &'a DynMap, key: &InFile) -> Option<&'a ID> { + let key = key.as_ref().map(AstPtr::new); + map.map.get::>, ID>>()?.get(&key) + } +} diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index e02622f62e..68e66d2765 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -16,6 +16,9 @@ pub mod builtin_type; pub mod diagnostics; pub mod per_ns; +pub mod dyn_map; +pub mod keys; + pub mod adt; pub mod data; pub mod generics; @@ -30,7 +33,7 @@ mod trace; pub mod nameres; pub mod src; -pub mod child_from_source; +pub mod child_by_source; #[cfg(test)] mod test_db; diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 9f373a8f41..6920ac747e 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -11,8 +11,8 @@ use std::fmt::Write; use std::sync::Arc; use hir_def::{ - body::BodySourceMap, child_from_source::ChildFromSource, db::DefDatabase, nameres::CrateDefMap, - AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, + body::BodySourceMap, child_by_source::ChildBySource, db::DefDatabase, keys, + nameres::CrateDefMap, AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, }; use hir_expand::InFile; use insta::assert_snapshot; @@ -33,7 +33,9 @@ fn type_at_pos(db: &TestDB, pos: FilePosition) -> String { let expr = algo::find_node_at_offset::(file.syntax(), pos.offset).unwrap(); let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap(); let module = db.module_for_file(pos.file_id); - let func = module.child_from_source(db, InFile::new(pos.file_id.into(), fn_def)).unwrap(); + let func = *module.child_by_source(db)[keys::FUNCTION] + .get(&InFile::new(pos.file_id.into(), fn_def)) + .unwrap(); let (_body, source_map) = db.body_with_source_map(func.into()); if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) { diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs index e049fce611..db6230aab9 100644 --- a/crates/ra_syntax/src/ptr.rs +++ b/crates/ra_syntax/src/ptr.rs @@ -1,6 +1,10 @@ //! FIXME: write short doc here -use std::{iter::successors, marker::PhantomData}; +use std::{ + hash::{Hash, Hasher}, + iter::successors, + marker::PhantomData, +}; use crate::{AstNode, SyntaxKind, SyntaxNode, TextRange}; @@ -43,7 +47,7 @@ impl SyntaxNodePtr { } /// Like `SyntaxNodePtr`, but remembers the type of node -#[derive(Debug, Hash)] +#[derive(Debug)] pub struct AstPtr { raw: SyntaxNodePtr, _ty: PhantomData N>, @@ -64,6 +68,12 @@ impl PartialEq for AstPtr { } } +impl Hash for AstPtr { + fn hash(&self, state: &mut H) { + self.raw.hash(state) + } +} + impl AstPtr { pub fn new(node: &N) -> AstPtr { AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData } From b2c01f446edcbc12b5dd870064cbfc6c1a47eb8b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 21:46:18 +0100 Subject: [PATCH 075/312] Implement ancestors_with_macros in a better way --- crates/ra_hir/src/source_binder.rs | 13 +------------ crates/ra_hir_expand/src/lib.rs | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index cb4345ca14..0e136b9049 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -76,7 +76,7 @@ fn def_with_body_from_child_node( db: &impl HirDatabase, child: InFile<&SyntaxNode>, ) -> Option { - ancestors_with_macros(db, child).find_map(|node| { + child.cloned().ancestors_with_macros(db).find_map(|node| { let n = &node.value; match_ast! { match n { @@ -89,17 +89,6 @@ fn def_with_body_from_child_node( }) } -fn ancestors_with_macros<'a>( - db: &'a (impl HirDatabase), - node: InFile<&SyntaxNode>, -) -> impl Iterator> + 'a { - let file = node.with_value(()); // keep just the file id for borrow checker purposes - let parent_node = node.file_id.call_node(db); - let parent_ancestors: Box>> = - Box::new(parent_node.into_iter().flat_map(move |n| ancestors_with_macros(db, n.as_ref()))); - node.value.ancestors().map(move |n| file.with_value(n)).chain(parent_ancestors) -} - /// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of /// original source files. It should not be used inside the HIR itself. #[derive(Debug)] diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 0c1dc87e67..0a5da7e547 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -301,3 +301,24 @@ impl InFile { db.parse_or_expand(self.file_id).expect("source created from invalid file") } } + +impl InFile<&T> { + pub fn cloned(&self) -> InFile { + self.with_value(self.value.clone()) + } +} + +impl InFile { + pub fn ancestors_with_macros<'a>( + self, + db: &'a impl crate::db::AstDatabase, + ) -> impl Iterator> + 'a { + std::iter::successors(Some(self), move |node| match node.value.parent() { + Some(parent) => Some(node.with_value(parent)), + None => { + let parent_node = node.file_id.call_node(db)?; + Some(parent_node) + } + }) + } +} From e5997e174666435acd5abb4531f833bd41bbdb00 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 7 Dec 2019 09:50:21 +0800 Subject: [PATCH 076/312] Push glob_imports only if non-exists --- crates/ra_hir_def/src/nameres/collector.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 08693cb13a..252178b6bd 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -352,10 +352,10 @@ where self.update(module_id, Some(import_id), &items); // record the glob import in case we add further items - self.glob_imports - .entry(m.local_id) - .or_default() - .push((module_id, import_id)); + let glob = self.glob_imports.entry(m.local_id).or_default(); + if !glob.iter().any(|it| *it == (module_id, import_id)) { + glob.push((module_id, import_id)); + } } } Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => { From de08d30b80f80ee0eaecf4dddb72e6fb829a46b6 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 7 Dec 2019 11:52:20 +0100 Subject: [PATCH 077/312] Get rid of unwraps in add_new Probably fixes #2464. --- crates/ra_assists/src/assists/add_new.rs | 41 +++++++++++------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index f977547fb9..d340cac8fd 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -56,42 +56,39 @@ pub(crate) fn add_new(ctx: AssistCtx) -> Option { let vis = vis.as_ref().map(String::as_str).unwrap_or(""); write!(&mut buf, " {}fn new(", vis).unwrap(); - join(field_list.fields().map(|f| { - format!( - "{}: {}", - f.name().unwrap().syntax().text(), - f.ascribed_type().unwrap().syntax().text() - ) + join(field_list.fields().filter_map(|f| { + Some(format!("{}: {}", f.name()?.syntax().text(), f.ascribed_type()?.syntax().text())) })) .separator(", ") .to_buf(&mut buf); buf.push_str(") -> Self { Self {"); - join(field_list.fields().map(|f| f.name().unwrap().syntax().text())) + join(field_list.fields().filter_map(|f| Some(f.name()?.syntax().text()))) .separator(", ") .surround_with(" ", " ") .to_buf(&mut buf); buf.push_str("} }"); - let (start_offset, end_offset) = if let Some(impl_block) = impl_block { - buf.push('\n'); - let start = impl_block - .syntax() - .descendants_with_tokens() - .find(|t| t.kind() == T!['{']) - .unwrap() - .text_range() - .end(); + let (start_offset, end_offset) = impl_block + .and_then(|impl_block| { + buf.push('\n'); + let start = impl_block + .syntax() + .descendants_with_tokens() + .find(|t| t.kind() == T!['{'])? + .text_range() + .end(); - (start, TextUnit::from_usize(1)) - } else { - buf = generate_impl_text(&strukt, &buf); - let start = strukt.syntax().text_range().end(); + Some((start, TextUnit::from_usize(1))) + }) + .unwrap_or_else(|| { + buf = generate_impl_text(&strukt, &buf); + let start = strukt.syntax().text_range().end(); - (start, TextUnit::from_usize(3)) - }; + (start, TextUnit::from_usize(3)) + }); edit.set_cursor(start_offset + TextUnit::of_str(&buf) - end_offset); edit.insert(start_offset, buf); From 51f4fb448f1993a20c9527a8e6d301a9202ce35a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 7 Dec 2019 19:20:41 +0800 Subject: [PATCH 078/312] Refactor resolve_imports logic --- crates/ra_hir_def/src/nameres/collector.rs | 156 ++++++++++++++---- .../ra_hir_def/src/nameres/path_resolution.rs | 13 +- 2 files changed, 129 insertions(+), 40 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 252178b6bd..3b3f30eecf 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -58,6 +58,8 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C def_map, glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), + resolved_imports: Vec::new(), + unexpanded_macros: Vec::new(), unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), @@ -97,12 +99,41 @@ impl MacroStackMonitor { } } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +enum PartialResolvedImport { + /// None of any namespaces is resolved + Unresolved, + /// One of namespaces is resolved + Indeterminate(PerNs), + /// All namespaces are resolved, OR it is came from other crate + Resolved(PerNs), +} + +impl PartialResolvedImport { + fn namespaces(&self) -> PerNs { + match self { + PartialResolvedImport::Unresolved => PerNs::none(), + PartialResolvedImport::Indeterminate(ns) => *ns, + PartialResolvedImport::Resolved(ns) => *ns, + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq)] +struct ImportDirective { + module_id: LocalModuleId, + import_id: LocalImportId, + import: raw::ImportData, + status: PartialResolvedImport, +} + /// Walks the tree of module recursively struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, glob_imports: FxHashMap>, - unresolved_imports: Vec<(LocalModuleId, LocalImportId, raw::ImportData)>, + unresolved_imports: Vec, + resolved_imports: Vec, unexpanded_macros: Vec<(LocalModuleId, AstId, Path)>, unexpanded_attribute_macros: Vec<(LocalModuleId, AstId, Path)>, mod_dirs: FxHashMap, @@ -148,9 +179,11 @@ where let mut i = 0; loop { self.db.check_canceled(); - match (self.resolve_imports(), self.resolve_macros()) { - (ReachedFixedPoint::Yes, ReachedFixedPoint::Yes) => break, - _ => i += 1, + self.resolve_imports(); + + match self.resolve_macros() { + ReachedFixedPoint::Yes => break, + ReachedFixedPoint::No => i += 1, } if i == 1000 { log::error!("name resolution is stuck"); @@ -158,10 +191,26 @@ where } } + // Resolve all indeterminate resolved imports again + // As some of the macros will expand newly import shadowing partial resolved imports + // FIXME: We maybe could skip this, if we handle the Indetermine imports in `resolve_imports` + // correctly + let partial_resolved = self.resolved_imports.iter().filter_map(|directive| { + if let PartialResolvedImport::Indeterminate(_) = directive.status { + let mut directive = directive.clone(); + directive.status = PartialResolvedImport::Unresolved; + Some(directive) + } else { + None + } + }); + self.unresolved_imports.extend(partial_resolved); + self.resolve_imports(); + let unresolved_imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); // show unresolved imports in completion, etc - for (module_id, import, import_data) in unresolved_imports { - self.record_resolved_import(module_id, PerNs::none(), import, &import_data) + for directive in unresolved_imports { + self.record_resolved_import(&directive) } } @@ -262,31 +311,43 @@ where } } - fn resolve_imports(&mut self) -> ReachedFixedPoint { - let mut imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); - let mut resolved = Vec::new(); - imports.retain(|(module_id, import, import_data)| { - let (def, fp) = self.resolve_import(*module_id, import_data); - if fp == ReachedFixedPoint::Yes { - resolved.push((*module_id, def, *import, import_data.clone())) + /// Import resolution + /// + /// This is a fix point algorithm. We resolve imports until no forward + /// progress in resolving imports is made + fn resolve_imports(&mut self) { + let mut n_previous_unresolved = self.unresolved_imports.len() + 1; + + while self.unresolved_imports.len() < n_previous_unresolved { + n_previous_unresolved = self.unresolved_imports.len(); + let imports = std::mem::replace(&mut self.unresolved_imports, Vec::new()); + for mut directive in imports { + directive.status = self.resolve_import(directive.module_id, &directive.import); + + match directive.status { + PartialResolvedImport::Indeterminate(_) => { + self.record_resolved_import(&directive); + // FIXME: For avoid performance regression, + // we consider an imported resolved if it is indeterminate (i.e not all namespace resolved) + self.resolved_imports.push(directive) + } + PartialResolvedImport::Resolved(_) => { + self.record_resolved_import(&directive); + self.resolved_imports.push(directive) + } + PartialResolvedImport::Unresolved => { + self.unresolved_imports.push(directive); + } + } } - fp == ReachedFixedPoint::No - }); - self.unresolved_imports = imports; - // Resolves imports, filling-in module scopes - let result = - if resolved.is_empty() { ReachedFixedPoint::Yes } else { ReachedFixedPoint::No }; - for (module_id, def, import, import_data) in resolved { - self.record_resolved_import(module_id, def, import, &import_data) } - result } fn resolve_import( &self, module_id: LocalModuleId, import: &raw::ImportData, - ) -> (PerNs, ReachedFixedPoint) { + ) -> PartialResolvedImport { log::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition); if import.is_extern_crate { let res = self.def_map.resolve_name_in_extern_prelude( @@ -295,7 +356,7 @@ where .as_ident() .expect("extern crate should have been desugared to one-element path"), ); - (res, ReachedFixedPoint::Yes) + PartialResolvedImport::Resolved(res) } else { let res = self.def_map.resolve_path_fp_with_macro( self.db, @@ -305,17 +366,35 @@ where BuiltinShadowMode::Module, ); - (res.resolved_def, res.reached_fixedpoint) + let def = res.resolved_def; + if res.reached_fixedpoint == ReachedFixedPoint::No { + return PartialResolvedImport::Unresolved; + } + + if let Some(krate) = res.krate { + if krate != self.def_map.krate { + return PartialResolvedImport::Resolved(def); + } + } + + // Check whether all namespace is resolved + if def.take_types().is_some() + && def.take_values().is_some() + && def.take_macros().is_some() + { + PartialResolvedImport::Resolved(def) + } else { + PartialResolvedImport::Indeterminate(def) + } } } - fn record_resolved_import( - &mut self, - module_id: LocalModuleId, - def: PerNs, - import_id: LocalImportId, - import: &raw::ImportData, - ) { + fn record_resolved_import(&mut self, directive: &ImportDirective) { + let module_id = directive.module_id; + let import_id = directive.import_id; + let import = &directive.import; + let def = directive.status.namespaces(); + if import.is_glob { log::debug!("glob import: {:?}", import); match def.take_types() { @@ -615,10 +694,14 @@ where raw::RawItemKind::Module(m) => { self.collect_module(&self.raw_items[m], &item.attrs) } - raw::RawItemKind::Import(import_id) => self - .def_collector - .unresolved_imports - .push((self.module_id, import_id, self.raw_items[import_id].clone())), + raw::RawItemKind::Import(import_id) => { + self.def_collector.unresolved_imports.push(ImportDirective { + module_id: self.module_id, + import_id, + import: self.raw_items[import_id].clone(), + status: PartialResolvedImport::Unresolved, + }) + } raw::RawItemKind::Def(def) => { self.define_def(&self.raw_items[def], &item.attrs) } @@ -886,6 +969,7 @@ mod tests { def_map, glob_imports: FxHashMap::default(), unresolved_imports: Vec::new(), + resolved_imports: Vec::new(), unexpanded_macros: Vec::new(), unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 42a75226ba..aab4b1dd97 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -19,7 +19,7 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{Path, PathKind}, per_ns::PerNs, - AdtId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, + AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -39,19 +39,21 @@ pub(super) struct ResolvePathResult { pub(super) resolved_def: PerNs, pub(super) segment_index: Option, pub(super) reached_fixedpoint: ReachedFixedPoint, + pub(super) krate: Option, } impl ResolvePathResult { fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult { - ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None) + ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None) } fn with( resolved_def: PerNs, reached_fixedpoint: ReachedFixedPoint, segment_index: Option, + krate: Option, ) -> ResolvePathResult { - ResolvePathResult { resolved_def, reached_fixedpoint, segment_index } + ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate } } } @@ -175,6 +177,7 @@ impl CrateDefMap { def, ReachedFixedPoint::Yes, s.map(|s| s + i), + Some(module.krate), ); } @@ -201,6 +204,7 @@ impl CrateDefMap { PerNs::types(e.into()), ReachedFixedPoint::Yes, Some(i), + Some(self.krate), ); } } @@ -218,12 +222,13 @@ impl CrateDefMap { PerNs::types(s), ReachedFixedPoint::Yes, Some(i), + Some(self.krate), ); } }; } - ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None) + ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate)) } fn resolve_name_in_module( From 30fefcc08cc0c670ce541476491238d258ca55c1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 6 Dec 2019 17:35:05 +0100 Subject: [PATCH 079/312] Store GenericParams in arena --- crates/ra_hir_def/src/generics.rs | 25 +++++++++++++------------ crates/ra_hir_def/src/lib.rs | 10 ++++++++++ crates/ra_hir_def/src/resolver.rs | 2 +- crates/ra_hir_ty/src/infer/expr.rs | 2 +- 4 files changed, 25 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 5f648ffc35..abe749a404 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -5,18 +5,19 @@ use std::sync::Arc; use hir_expand::name::{self, AsName, Name}; +use ra_arena::Arena; use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::DefDatabase, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ContainerId, GenericDefId, Lookup, + AdtId, AstItemDef, ContainerId, GenericDefId, LocalGenericParamId, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] -pub struct GenericParam { +pub struct GenericParamData { // FIXME: give generic params proper IDs pub idx: u32, pub name: Name, @@ -27,7 +28,7 @@ pub struct GenericParam { #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParams { pub parent_params: Option>, - pub params: Vec, + pub params: Arena, pub where_predicates: Vec, } @@ -56,7 +57,7 @@ impl GenericParams { parent_params: Option>, ) -> GenericParams { let mut generics = - GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() }; + GenericParams { params: Arena::default(), parent_params, where_predicates: Vec::new() }; let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { @@ -66,7 +67,7 @@ impl GenericParams { GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), GenericDefId::TraitId(it) => { // traits get the Self type as an implicit first type parameter - generics.params.push(GenericParam { + generics.params.alloc(GenericParamData { idx: start, name: name::SELF_TYPE, default: None, @@ -110,8 +111,8 @@ impl GenericParams { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` let default = type_param.default_type().map(TypeRef::from_ast); - let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default }; - self.params.push(param); + let param = GenericParamData { idx: idx as u32 + start, name: name.clone(), default }; + self.params.alloc(param); let type_ref = TypeRef::Path(name.into()); self.fill_bounds(&type_param, type_ref); @@ -140,8 +141,8 @@ impl GenericParams { self.where_predicates.push(WherePredicate { type_ref, bound }); } - pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { - self.params.iter().find(|p| &p.name == name) + pub fn find_by_name(&self, name: &Name) -> Option<&GenericParamData> { + self.params.iter().map(|(_id, data)| data).find(|p| &p.name == name) } pub fn count_parent_params(&self) -> usize { @@ -153,14 +154,14 @@ impl GenericParams { parent_count + self.params.len() } - fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) { + fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParamData)) { if let Some(parent) = &self.parent_params { parent.for_each_param(f); } - self.params.iter().for_each(f); + self.params.iter().map(|(_id, data)| data).for_each(f); } - pub fn params_including_parent(&self) -> Vec<&GenericParam> { + pub fn params_including_parent(&self) -> Vec<&GenericParamData> { let mut vec = Vec::with_capacity(self.count_params_including_parent()); self.for_each_param(&mut |p| vec.push(p)); vec diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 68e66d2765..b8dfc0ab1a 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -317,6 +317,16 @@ macro_rules! impl_froms { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct GenericParamId { + pub parent: GenericDefId, + pub local_id: LocalGenericParamId, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocalGenericParamId(RawId); +impl_arena_id!(LocalGenericParamId); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ContainerId { ModuleId(ModuleId), diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 7d4df222e3..ee19d79a76 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -426,7 +426,7 @@ impl Scope { } } Scope::GenericParams { params, .. } => { - for param in params.params.iter() { + for (_id, param) in params.params.iter() { f(param.name.clone(), ScopeDef::GenericParam(param.idx)) } } diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index b8df277063..0c34289993 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -662,7 +662,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let mut substs = Vec::with_capacity(parent_param_count + param_count); // Parent arguments are unknown, except for the receiver type if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { - for param in &parent_generics.params { + for (_id, param) in parent_generics.params.iter() { if param.name == name::SELF_TYPE { substs.push(receiver_ty.clone()); } else { From 8e9837df21942ca12a5aece0a868ea46eb405742 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 11:50:36 +0100 Subject: [PATCH 080/312] Remove idx and parent generics from generics This makes `hir_def::GenericParams` flatter. The logic for re-numbering the params is moved to hir instead. --- crates/ra_hir/src/code_model.rs | 5 +- crates/ra_hir/src/source_binder.rs | 10 +--- crates/ra_hir_def/src/generics.rs | 90 ++++++---------------------- crates/ra_hir_def/src/resolver.rs | 38 +++++++----- crates/ra_hir_ty/src/autoderef.rs | 8 +-- crates/ra_hir_ty/src/infer/expr.rs | 24 ++++---- crates/ra_hir_ty/src/lib.rs | 32 ++++------ crates/ra_hir_ty/src/lower.rs | 35 ++++++----- crates/ra_hir_ty/src/traits/chalk.rs | 14 ++--- crates/ra_hir_ty/src/utils.rs | 82 ++++++++++++++++++++++++- 10 files changed, 181 insertions(+), 157 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 7706399ae5..29ace8479d 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -15,7 +15,7 @@ use hir_def::{ per_ns::PerNs, resolver::HasResolver, type_ref::{Mutability, TypeRef}, - AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericDefId, + AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericParamId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, }; @@ -857,8 +857,7 @@ impl Local { #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct GenericParam { - pub(crate) parent: GenericDefId, - pub(crate) idx: u32, + pub(crate) id: GenericParamId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0e136b9049..8c4b635d22 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -262,10 +262,7 @@ impl SourceAnalyzer { ) -> Option { let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(idx) => PathResolution::GenericParam(GenericParam { - parent: self.resolver.generic_def().unwrap(), - idx, - }), + TypeNs::GenericParam(id) => PathResolution::GenericParam(GenericParam { id }), TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { PathResolution::Def(Adt::from(it).into()) } @@ -337,10 +334,7 @@ impl SourceAnalyzer { resolver::ScopeDef::PerNs(it) => it.into(), resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), - resolver::ScopeDef::GenericParam(idx) => { - let parent = self.resolver.generic_def().unwrap(); - ScopeDef::GenericParam(GenericParam { parent, idx }) - } + resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(GenericParam { id }), resolver::ScopeDef::Local(pat_id) => { let parent = self.resolver.body_owner().unwrap().into(); ScopeDef::Local(Local { parent, pat_id }) diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index abe749a404..94ce835646 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -12,14 +12,12 @@ use crate::{ db::DefDatabase, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ContainerId, GenericDefId, LocalGenericParamId, Lookup, + AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParamData { - // FIXME: give generic params proper IDs - pub idx: u32, pub name: Name, pub default: Option, } @@ -27,7 +25,6 @@ pub struct GenericParamData { /// Data about the generic parameters of a function, struct, impl, etc. #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParams { - pub parent_params: Option>, pub params: Arena, pub where_predicates: Vec, } @@ -47,51 +44,40 @@ impl GenericParams { db: &impl DefDatabase, def: GenericDefId, ) -> Arc { - let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it)); - Arc::new(GenericParams::new(db, def.into(), parent_generics)) + Arc::new(GenericParams::new(db, def.into())) } - fn new( - db: &impl DefDatabase, - def: GenericDefId, - parent_params: Option>, - ) -> GenericParams { - let mut generics = - GenericParams { params: Arena::default(), parent_params, where_predicates: Vec::new() }; - let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; + fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { + let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; // FIXME: add `: Sized` bound for everything except for `Self` in traits match def { - GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start), - GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value, start), - GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value, start), - GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start), + GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), + GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), + GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), + GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), GenericDefId::TraitId(it) => { // traits get the Self type as an implicit first type parameter - generics.params.alloc(GenericParamData { - idx: start, - name: name::SELF_TYPE, - default: None, - }); - generics.fill(&it.source(db).value, start + 1); + generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); + generics.fill(&it.source(db).value); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name::SELF_TYPE.into()); generics.fill_bounds(&it.source(db).value, self_param); } - GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start), + GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), // Note that we don't add `Self` here: in `impl`s, `Self` is not a // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. - GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start), + GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} } generics } - fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) { + fn fill(&mut self, node: &impl TypeParamsOwner) { if let Some(params) = node.type_param_list() { - self.fill_params(params, start) + self.fill_params(params) } if let Some(where_clause) = node.where_clause() { self.fill_where_predicates(where_clause); @@ -106,12 +92,12 @@ impl GenericParams { } } - fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { - for (idx, type_param) in params.type_params().enumerate() { + fn fill_params(&mut self, params: ast::TypeParamList) { + for type_param in params.type_params() { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` let default = type_param.default_type().map(TypeRef::from_ast); - let param = GenericParamData { idx: idx as u32 + start, name: name.clone(), default }; + let param = GenericParamData { name: name.clone(), default }; self.params.alloc(param); let type_ref = TypeRef::Path(name.into()); @@ -141,45 +127,7 @@ impl GenericParams { self.where_predicates.push(WherePredicate { type_ref, bound }); } - pub fn find_by_name(&self, name: &Name) -> Option<&GenericParamData> { - self.params.iter().map(|(_id, data)| data).find(|p| &p.name == name) - } - - pub fn count_parent_params(&self) -> usize { - self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0) - } - - pub fn count_params_including_parent(&self) -> usize { - let parent_count = self.count_parent_params(); - parent_count + self.params.len() - } - - fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParamData)) { - if let Some(parent) = &self.parent_params { - parent.for_each_param(f); - } - self.params.iter().map(|(_id, data)| data).for_each(f); - } - - pub fn params_including_parent(&self) -> Vec<&GenericParamData> { - let mut vec = Vec::with_capacity(self.count_params_including_parent()); - self.for_each_param(&mut |p| vec.push(p)); - vec - } -} - -fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option { - let container = match def { - GenericDefId::FunctionId(it) => it.lookup(db).container, - GenericDefId::TypeAliasId(it) => it.lookup(db).container, - GenericDefId::ConstId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), - GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, - }; - - match container { - ContainerId::ImplId(it) => Some(it.into()), - ContainerId::TraitId(it) => Some(it.into()), - ContainerId::ModuleId(_) => None, + pub fn find_by_name(&self, name: &Name) -> Option { + self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index ee19d79a76..e00bd03d54 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -18,12 +18,13 @@ use crate::{ path::{Path, PathKind}, per_ns::PerNs, AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, + GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, }; #[derive(Debug, Clone, Default)] pub struct Resolver { + // FIXME: all usages generally call `.rev`, so maybe reverse once in consturciton? scopes: Vec, } @@ -58,7 +59,7 @@ enum Scope { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeNs { SelfType(ImplId), - GenericParam(u32), + GenericParam(GenericParamId), AdtId(AdtId), AdtSelfType(AdtId), // Yup, enum variants are added to the types ns, but any usage of variant as @@ -152,10 +153,13 @@ impl Resolver { Scope::ExprScope(_) => continue, Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, - Scope::GenericParams { params, .. } => { - if let Some(param) = params.find_by_name(first_name) { + Scope::GenericParams { params, def } => { + if let Some(local_id) = params.find_by_name(first_name) { let idx = if path.segments.len() == 1 { None } else { Some(1) }; - return Some((TypeNs::GenericParam(param.idx), idx)); + return Some(( + TypeNs::GenericParam(GenericParamId { local_id, parent: *def }), + idx, + )); } } Scope::ImplBlockScope(impl_) => { @@ -246,9 +250,9 @@ impl Resolver { } Scope::ExprScope(_) => continue, - Scope::GenericParams { params, .. } if n_segments > 1 => { - if let Some(param) = params.find_by_name(first_name) { - let ty = TypeNs::GenericParam(param.idx); + Scope::GenericParams { params, def } if n_segments > 1 => { + if let Some(local_id) = params.find_by_name(first_name) { + let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def }); return Some(ResolveValueResult::Partial(ty, 1)); } } @@ -368,6 +372,7 @@ impl Resolver { ) -> impl Iterator + 'a { self.scopes .iter() + .rev() .filter_map(|scope| match scope { Scope::GenericParams { params, .. } => Some(params), _ => None, @@ -376,14 +381,14 @@ impl Resolver { } pub fn generic_def(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { + self.scopes.iter().rev().find_map(|scope| match scope { Scope::GenericParams { def, .. } => Some(*def), _ => None, }) } pub fn body_owner(&self) -> Option { - self.scopes.iter().find_map(|scope| match scope { + self.scopes.iter().rev().find_map(|scope| match scope { Scope::ExprScope(it) => Some(it.owner), _ => None, }) @@ -394,7 +399,7 @@ pub enum ScopeDef { PerNs(PerNs), ImplSelfType(ImplId), AdtSelfType(AdtId), - GenericParam(u32), + GenericParam(GenericParamId), Local(PatId), } @@ -425,9 +430,12 @@ impl Scope { }); } } - Scope::GenericParams { params, .. } => { - for (_id, param) in params.params.iter() { - f(param.name.clone(), ScopeDef::GenericParam(param.idx)) + Scope::GenericParams { params, def } => { + for (local_id, param) in params.params.iter() { + f( + param.name.clone(), + ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }), + ) } } Scope::ImplBlockScope(i) => { diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index 9d1d4e48c6..a6db7f623b 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs @@ -10,10 +10,10 @@ use hir_expand::name; use log::{info, warn}; use ra_db::CrateId; -use crate::db::HirDatabase; - -use super::{ +use crate::{ + db::HirDatabase, traits::{InEnvironment, Solution}, + utils::generics, Canonical, Substs, Ty, TypeWalk, }; @@ -54,7 +54,7 @@ fn deref_by_trait( }; let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; - let generic_params = db.generic_params(target.into()); + let generic_params = generics(db, target.into()); if generic_params.count_params_including_parent() != 1 { // the Target type + Deref trait should only have one generic parameter, // namely Deref's Self type diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 0c34289993..e52040eb5b 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -6,7 +6,6 @@ use std::sync::Arc; use hir_def::{ builtin_type::Signedness, expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, - generics::GenericParams, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, AdtId, ContainerId, Lookup, StructFieldId, @@ -15,7 +14,11 @@ use hir_expand::name::{self, Name}; use ra_syntax::ast::RangeOp; use crate::{ - autoderef, db::HirDatabase, method_resolution, op, traits::InEnvironment, utils::variant_data, + autoderef, + db::HirDatabase, + method_resolution, op, + traits::InEnvironment, + utils::{generics, variant_data, Generics}, CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, }; @@ -596,7 +599,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Some((ty, func)) => { let ty = canonicalized_receiver.decanonicalize_ty(ty); self.write_method_resolution(tgt_expr, func); - (ty, self.db.value_ty(func.into()), Some(self.db.generic_params(func.into()))) + (ty, self.db.value_ty(func.into()), Some(generics(self.db, func.into()))) } None => (receiver_ty, Ty::Unknown, None), }; @@ -653,16 +656,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn substs_for_method_call( &mut self, - def_generics: Option>, + def_generics: Option, generic_args: Option<&GenericArgs>, receiver_ty: &Ty, ) -> Substs { - let (parent_param_count, param_count) = - def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); + let (parent_param_count, param_count) = def_generics + .as_ref() + .map_or((0, 0), |g| (g.count_parent_params(), g.params.params.len())); let mut substs = Vec::with_capacity(parent_param_count + param_count); // Parent arguments are unknown, except for the receiver type - if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { - for (_id, param) in parent_generics.params.iter() { + if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { + for (_id, param) in parent_generics { if param.name == name::SELF_TYPE { substs.push(receiver_ty.clone()); } else { @@ -706,9 +710,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { // construct a TraitDef let substs = a_ty.parameters.prefix( - self.db - .generic_params(trait_.into()) - .count_params_including_parent(), + generics(self.db, trait_.into()).count_params_including_parent(), ); self.obligations.push(Obligation::Trait(TraitRef { trait_: trait_.into(), diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 3c1f738dfc..99fd7158ee 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -44,7 +44,7 @@ use std::sync::Arc; use std::{fmt, iter, mem}; use hir_def::{ - expr::ExprId, generics::GenericParams, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, + expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, }; use hir_expand::name::Name; @@ -53,7 +53,7 @@ use ra_db::{impl_intern_key, salsa, CrateId}; use crate::{ db::HirDatabase, primitive::{FloatTy, IntTy, Uncertain}, - utils::make_mut_slice, + utils::{generics, make_mut_slice, Generics}, }; use display::{HirDisplay, HirFormatter}; @@ -166,15 +166,15 @@ impl TypeCtor { | TypeCtor::Closure { .. } // 1 param representing the signature of the closure => 1, TypeCtor::Adt(adt) => { - let generic_params = db.generic_params(AdtId::from(adt).into()); + let generic_params = generics(db, AdtId::from(adt).into()); generic_params.count_params_including_parent() } TypeCtor::FnDef(callable) => { - let generic_params = db.generic_params(callable.into()); + let generic_params = generics(db, callable.into()); generic_params.count_params_including_parent() } TypeCtor::AssociatedType(type_alias) => { - let generic_params = db.generic_params(type_alias.into()); + let generic_params = generics(db, type_alias.into()); generic_params.count_params_including_parent() } TypeCtor::FnPtr { num_args } => num_args as usize + 1, @@ -364,35 +364,25 @@ impl Substs { } /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). - pub fn identity(generic_params: &GenericParams) -> Substs { + pub(crate) fn identity(generic_params: &Generics) -> Substs { Substs( - generic_params - .params_including_parent() - .into_iter() - .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() }) - .collect(), + generic_params.iter().map(|(idx, p)| Ty::Param { idx, name: p.name.clone() }).collect(), ) } /// Return Substs that replace each parameter by a bound variable. - pub fn bound_vars(generic_params: &GenericParams) -> Substs { - Substs( - generic_params - .params_including_parent() - .into_iter() - .map(|p| Ty::Bound(p.idx)) - .collect(), - ) + pub(crate) fn bound_vars(generic_params: &Generics) -> Substs { + Substs(generic_params.iter().map(|(idx, _p)| Ty::Bound(idx)).collect()) } pub fn build_for_def(db: &impl HirDatabase, def: impl Into) -> SubstsBuilder { let def = def.into(); - let params = db.generic_params(def); + let params = generics(db, def); let param_count = params.count_params_including_parent(); Substs::builder(param_count) } - pub fn build_for_generics(generic_params: &GenericParams) -> SubstsBuilder { + pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { Substs::builder(generic_params.count_params_including_parent()) } diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 32569ac66f..d31f6a2d29 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -24,7 +24,7 @@ use crate::{ db::HirDatabase, primitive::{FloatTy, IntTy}, utils::{ - all_super_traits, associated_type_by_name_including_super_traits, make_mut_slice, + all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, variant_data, }, FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, @@ -111,7 +111,9 @@ impl Ty { Some((it, None)) => it, _ => return None, }; - if let TypeNs::GenericParam(idx) = resolution { + if let TypeNs::GenericParam(param_id) = resolution { + let generics = generics(db, resolver.generic_def().expect("generics in scope")); + let idx = generics.param_idx(param_id); Some(idx) } else { None @@ -174,9 +176,11 @@ impl Ty { Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) }; } - TypeNs::GenericParam(idx) => { + TypeNs::GenericParam(param_id) => { + let generics = generics(db, resolver.generic_def().expect("generics in scope")); + let idx = generics.param_idx(param_id); // FIXME: maybe return name in resolution? - let name = resolved_segment.name.clone(); + let name = generics.param_name(param_id); Ty::Param { idx, name } } TypeNs::SelfType(impl_id) => db.impl_self_ty(impl_id).clone(), @@ -315,10 +319,10 @@ pub(super) fn substs_from_path_segment( add_self_param: bool, ) -> Substs { let mut substs = Vec::new(); - let def_generics = def_generic.map(|def| db.generic_params(def.into())); + let def_generics = def_generic.map(|def| generics(db, def.into())); let (parent_param_count, param_count) = - def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); + def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.params.len())); substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); if add_self_param { // FIXME this add_self_param argument is kind of a hack: Traits have the @@ -567,12 +571,11 @@ pub(crate) fn generic_predicates_query( /// Resolve the default type params from generics pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDefId) -> Substs { let resolver = def.resolver(db); - let generic_params = db.generic_params(def.into()); + let generic_params = generics(db, def.into()); let defaults = generic_params - .params_including_parent() - .into_iter() - .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) + .iter() + .map(|(_idx, p)| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t))) .collect(); Substs(defaults) @@ -589,7 +592,7 @@ fn fn_sig_for_fn(db: &impl HirDatabase, def: FunctionId) -> FnSig { /// Build the declared type of a function. This should not need to look at the /// function body. fn type_for_fn(db: &impl HirDatabase, def: FunctionId) -> Ty { - let generics = db.generic_params(def.into()); + let generics = generics(db, def.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(def.into()), substs) } @@ -639,7 +642,7 @@ fn type_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> Ty { if struct_data.variant_data.is_unit() { return type_for_adt(db, def.into()); // Unit struct } - let generics = db.generic_params(def.into()); + let generics = generics(db, def.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(def.into()), substs) } @@ -653,7 +656,7 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId .iter() .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) .collect::>(); - let generics = db.generic_params(def.parent.into()); + let generics = generics(db, def.parent.into()); let substs = Substs::identity(&generics); let ret = type_for_adt(db, def.parent.into()).subst(&substs); FnSig::from_params_and_return(params, ret) @@ -666,18 +669,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId) if var_data.is_unit() { return type_for_adt(db, def.parent.into()); // Unit variant } - let generics = db.generic_params(def.parent.into()); + let generics = generics(db, def.parent.into()); let substs = Substs::identity(&generics); Ty::apply(TypeCtor::FnDef(EnumVariantId::from(def).into()), substs) } fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Ty { - let generics = db.generic_params(adt.into()); + let generics = generics(db, adt.into()); Ty::apply(TypeCtor::Adt(adt), Substs::identity(&generics)) } fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Ty { - let generics = db.generic_params(t.into()); + let generics = generics(db, t.into()); let resolver = t.resolver(db); let type_ref = &db.type_alias_data(t).type_ref; let substs = Substs::identity(&generics); diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index e3f02fa156..1d44320b94 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -19,8 +19,8 @@ use ra_db::{ use super::{builtin, AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; use crate::{ - db::HirDatabase, display::HirDisplay, ApplicationTy, GenericPredicate, ProjectionTy, Substs, - TraitRef, Ty, TypeCtor, TypeWalk, + db::HirDatabase, display::HirDisplay, utils::generics, ApplicationTy, GenericPredicate, + ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; /// This represents a trait whose name we could not resolve. @@ -547,7 +547,7 @@ pub(crate) fn associated_ty_data_query( ContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), }; - let generic_params = db.generic_params(type_alias.into()); + let generic_params = generics(db, type_alias.into()); let bound_data = chalk_rust_ir::AssociatedTyDatumBound { // FIXME add bounds and where clauses bounds: vec![], @@ -589,7 +589,7 @@ pub(crate) fn trait_datum_query( let trait_: TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); - let generic_params = db.generic_params(trait_.into()); + let generic_params = generics(db, trait_.into()); let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, @@ -626,7 +626,7 @@ pub(crate) fn struct_datum_query( let where_clauses = type_ctor .as_generic_def() .map(|generic_def| { - let generic_params = db.generic_params(generic_def.into()); + let generic_params = generics(db, generic_def.into()); let bound_vars = Substs::bound_vars(&generic_params); convert_where_clauses(db, generic_def, &bound_vars) }) @@ -669,7 +669,7 @@ fn impl_block_datum( let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); - let generic_params = db.generic_params(impl_id.into()); + let generic_params = generics(db, impl_id.into()); let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; @@ -767,7 +767,7 @@ fn type_alias_associated_ty_value( .trait_data(trait_ref.trait_) .associated_type_by_name(&type_alias_data.name) .expect("assoc ty value should not exist"); // validated when building the impl data as well - let generic_params = db.generic_params(impl_id.into()); + let generic_params = generics(db, impl_id.into()); let bound_vars = Substs::bound_vars(&generic_params); let ty = db.ty(type_alias.into()).subst(&bound_vars); let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index e4ba890efa..2c458867ff 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -5,9 +5,10 @@ use std::sync::Arc; use hir_def::{ adt::VariantData, db::DefDatabase, + generics::{GenericParamData, GenericParams}, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, - TraitId, TypeAliasId, VariantId, + ContainerId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, VariantId, }; use hir_expand::name::{self, Name}; @@ -82,3 +83,82 @@ pub(crate) fn make_mut_slice(a: &mut Arc<[T]>) -> &mut [T] { } Arc::get_mut(a).unwrap() } + +pub(crate) fn generics(db: &impl DefDatabase, def: GenericDefId) -> Generics { + let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); + Generics { def, params: db.generic_params(def), parent_generics } +} + +pub(crate) struct Generics { + def: GenericDefId, + pub(crate) params: Arc, + parent_generics: Option>, +} + +impl Generics { + pub(crate) fn iter<'a>(&'a self) -> impl Iterator + 'a { + self.parent_generics + .as_ref() + .into_iter() + .flat_map(|it| it.params.params.iter()) + .chain(self.params.params.iter()) + .enumerate() + .map(|(i, (_local_id, p))| (i as u32, p)) + } + + pub(crate) fn iter_parent<'a>( + &'a self, + ) -> impl Iterator + 'a { + self.parent_generics + .as_ref() + .into_iter() + .flat_map(|it| it.params.params.iter()) + .enumerate() + .map(|(i, (_local_id, p))| (i as u32, p)) + } + + pub(crate) fn count_parent_params(&self) -> usize { + self.parent_generics.as_ref().map_or(0, |p| p.count_params_including_parent()) + } + + pub(crate) fn count_params_including_parent(&self) -> usize { + let parent_count = self.count_parent_params(); + parent_count + self.params.params.len() + } + pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 { + self.find_param(param).0 + } + pub(crate) fn param_name(&self, param: GenericParamId) -> Name { + self.find_param(param).1.name.clone() + } + fn find_param(&self, param: GenericParamId) -> (u32, &GenericParamData) { + if param.parent == self.def { + let (idx, (_local_id, data)) = self + .params + .params + .iter() + .enumerate() + .find(|(_, (idx, _))| *idx == param.local_id) + .unwrap(); + + return ((self.count_parent_params() + idx) as u32, data); + } + self.parent_generics.as_ref().unwrap().find_param(param) + } +} + +fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option { + let container = match def { + GenericDefId::FunctionId(it) => it.lookup(db).container, + GenericDefId::TypeAliasId(it) => it.lookup(db).container, + GenericDefId::ConstId(it) => it.lookup(db).container, + GenericDefId::EnumVariantId(it) => return Some(it.parent.into()), + GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None, + }; + + match container { + ContainerId::ImplId(it) => Some(it.into()), + ContainerId::TraitId(it) => Some(it.into()), + ContainerId::ModuleId(_) => None, + } +} From d6c2b92409902d9ceca8cd064026cfcc1f357cf6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 13:05:05 +0100 Subject: [PATCH 081/312] Refactor parameter count tracking --- crates/ra_hir_ty/src/autoderef.rs | 2 +- crates/ra_hir_ty/src/infer/expr.rs | 18 ++++++++---------- crates/ra_hir_ty/src/lib.rs | 10 +++++----- crates/ra_hir_ty/src/lower.rs | 13 ++++++------- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- crates/ra_hir_ty/src/utils.rs | 17 +++++++++-------- 6 files changed, 30 insertions(+), 32 deletions(-) diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index a6db7f623b..d557962b4f 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs @@ -55,7 +55,7 @@ fn deref_by_trait( let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; let generic_params = generics(db, target.into()); - if generic_params.count_params_including_parent() != 1 { + if generic_params.len() != 1 { // the Target type + Deref trait should only have one generic parameter, // namely Deref's Self type return None; diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index e52040eb5b..2c296987c8 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -660,10 +660,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { generic_args: Option<&GenericArgs>, receiver_ty: &Ty, ) -> Substs { - let (parent_param_count, param_count) = def_generics - .as_ref() - .map_or((0, 0), |g| (g.count_parent_params(), g.params.params.len())); - let mut substs = Vec::with_capacity(parent_param_count + param_count); + let (total_len, _parent_len, child_len) = + def_generics.as_ref().map_or((0, 0, 0), |g| g.len_split()); + let mut substs = Vec::with_capacity(total_len); // Parent arguments are unknown, except for the receiver type if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { for (_id, param) in parent_generics { @@ -677,7 +676,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // handle provided type arguments if let Some(generic_args) = generic_args { // if args are provided, it should be all of them, but we can't rely on that - for arg in generic_args.args.iter().take(param_count) { + for arg in generic_args.args.iter().take(child_len) { match arg { GenericArg::Type(type_ref) => { let ty = self.make_ty(type_ref); @@ -687,10 +686,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } }; let supplied_params = substs.len(); - for _ in supplied_params..parent_param_count + param_count { + for _ in supplied_params..total_len { substs.push(Ty::Unknown); } - assert_eq!(substs.len(), parent_param_count + param_count); + assert_eq!(substs.len(), total_len); Substs(substs.into()) } @@ -709,9 +708,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { CallableDef::FunctionId(f) => { if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { // construct a TraitDef - let substs = a_ty.parameters.prefix( - generics(self.db, trait_.into()).count_params_including_parent(), - ); + let substs = + a_ty.parameters.prefix(generics(self.db, trait_.into()).len()); self.obligations.push(Obligation::Trait(TraitRef { trait_: trait_.into(), substs, diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 99fd7158ee..036d3a589a 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -167,15 +167,15 @@ impl TypeCtor { => 1, TypeCtor::Adt(adt) => { let generic_params = generics(db, AdtId::from(adt).into()); - generic_params.count_params_including_parent() + generic_params.len() } TypeCtor::FnDef(callable) => { let generic_params = generics(db, callable.into()); - generic_params.count_params_including_parent() + generic_params.len() } TypeCtor::AssociatedType(type_alias) => { let generic_params = generics(db, type_alias.into()); - generic_params.count_params_including_parent() + generic_params.len() } TypeCtor::FnPtr { num_args } => num_args as usize + 1, TypeCtor::Tuple { cardinality } => cardinality as usize, @@ -378,12 +378,12 @@ impl Substs { pub fn build_for_def(db: &impl HirDatabase, def: impl Into) -> SubstsBuilder { let def = def.into(); let params = generics(db, def); - let param_count = params.count_params_including_parent(); + let param_count = params.len(); Substs::builder(param_count) } pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { - Substs::builder(generic_params.count_params_including_parent()) + Substs::builder(generic_params.len()) } pub fn build_for_type_ctor(db: &impl HirDatabase, type_ctor: TypeCtor) -> SubstsBuilder { diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index d31f6a2d29..eab91229e3 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -321,9 +321,8 @@ pub(super) fn substs_from_path_segment( let mut substs = Vec::new(); let def_generics = def_generic.map(|def| generics(db, def.into())); - let (parent_param_count, param_count) = - def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.params.len())); - substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); + let (total_len, parent_len, child_len) = def_generics.map_or((0, 0, 0), |g| g.len_split()); + substs.extend(iter::repeat(Ty::Unknown).take(parent_len)); if add_self_param { // FIXME this add_self_param argument is kind of a hack: Traits have the // Self type as an implicit first type parameter, but it can't be @@ -334,8 +333,8 @@ pub(super) fn substs_from_path_segment( if let Some(generic_args) = &segment.args_and_bindings { // if args are provided, it should be all of them, but we can't rely on that let self_param_correction = if add_self_param { 1 } else { 0 }; - let param_count = param_count - self_param_correction; - for arg in generic_args.args.iter().take(param_count) { + let child_len = child_len + self_param_correction; + for arg in generic_args.args.iter().take(child_len) { match arg { GenericArg::Type(type_ref) => { let ty = Ty::from_hir(db, resolver, type_ref); @@ -346,10 +345,10 @@ pub(super) fn substs_from_path_segment( } // add placeholders for args that were not provided let supplied_params = substs.len(); - for _ in supplied_params..parent_param_count + param_count { + for _ in supplied_params..total_len { substs.push(Ty::Unknown); } - assert_eq!(substs.len(), parent_param_count + param_count); + assert_eq!(substs.len(), total_len); // handle defaults if let Some(def_generic) = def_generic { diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1d44320b94..1e7ff93d59 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -557,7 +557,7 @@ pub(crate) fn associated_ty_data_query( trait_id: trait_.to_chalk(db), id, name: lalrpop_intern::intern(&db.type_alias_data(type_alias).name.to_string()), - binders: make_binders(bound_data, generic_params.count_params_including_parent()), + binders: make_binders(bound_data, generic_params.len()), }; Arc::new(datum) } diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 2c458867ff..936cfe25e0 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -117,13 +117,14 @@ impl Generics { .map(|(i, (_local_id, p))| (i as u32, p)) } - pub(crate) fn count_parent_params(&self) -> usize { - self.parent_generics.as_ref().map_or(0, |p| p.count_params_including_parent()) + pub(crate) fn len(&self) -> usize { + self.len_split().0 } - - pub(crate) fn count_params_including_parent(&self) -> usize { - let parent_count = self.count_parent_params(); - parent_count + self.params.params.len() + /// (total, parents, child) + pub(crate) fn len_split(&self) -> (usize, usize, usize) { + let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); + let child = self.params.params.len(); + (parent + child, parent, child) } pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 { self.find_param(param).0 @@ -140,8 +141,8 @@ impl Generics { .enumerate() .find(|(_, (idx, _))| *idx == param.local_id) .unwrap(); - - return ((self.count_parent_params() + idx) as u32, data); + let (_total, parent_len, _child) = self.len_split(); + return ((parent_len + idx) as u32, data); } self.parent_generics.as_ref().unwrap().find_param(param) } From 29b5e1ec2a4bc25daddfe5137503b156b3cd283f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 13:19:21 +0100 Subject: [PATCH 082/312] Reformat --- crates/ra_hir_ty/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 036d3a589a..3ad913e55e 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -44,8 +44,8 @@ use std::sync::Arc; use std::{fmt, iter, mem}; use hir_def::{ - expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, - GenericDefId, HasModule, Lookup, TraitId, TypeAliasId, + expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, + Lookup, TraitId, TypeAliasId, }; use hir_expand::name::Name; use ra_db::{impl_intern_key, salsa, CrateId}; From 8ec5f2fcdcdd2e2a9297093189ad8c05e1dd7a8f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 12:46:36 +0100 Subject: [PATCH 083/312] Skip slow tests by default --- .github/workflows/ci.yaml | 8 ++-- .../ra_lsp_server/tests/heavy_tests/main.rs | 38 +++++++++++++++++++ crates/test_utils/src/lib.rs | 11 ++++++ 3 files changed, 54 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5bc41533c4..cb397ae14a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,6 +14,7 @@ jobs: env: RUSTFLAGS: -D warnings CARGO_INCREMENTAL: 0 + RUN_SLOW_TESTS: 1 steps: - name: Checkout repository @@ -46,9 +47,10 @@ jobs: - name: Prepare build directory for cache run: | - find ./target/debug -maxdepth 1 -type f -delete && \ - rm -fr ./target/debug/{deps,.fingerprint}/{*ra_*,*heavy_test*,*gen_lsp*,*thread_worker*} && \ - rm -f ./target/.rustc_info.json + find ./target/debug -maxdepth 1 -type f -delete \ + && rm -fr ./target/debug/{deps,.fingerprint}/{*ra_*,*heavy_test*,*gen_lsp*,*thread_worker*} \ + && rm -f ./target/.rustc_info.json \ + && rm ./target/.slow_tests_cookie type-script: name: TypeScript diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index fec50bd25c..cfbf16ea5f 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -12,6 +12,7 @@ use ra_lsp_server::req::{ }; use serde_json::json; use tempfile::TempDir; +use test_utils::skip_slow_tests; use crate::support::{project, Project}; @@ -20,6 +21,10 @@ const PROFILE: &'static str = ""; #[test] fn completes_items_from_standard_library() { + if skip_slow_tests() { + return; + } + let project_start = Instant::now(); let server = Project::with_fixture( r#" @@ -50,6 +55,10 @@ use std::collections::Spam; #[test] fn test_runnables_no_project() { + if skip_slow_tests() { + return; + } + let server = project( r" //- lib.rs @@ -99,6 +108,10 @@ fn foo() { #[test] fn test_runnables_project() { + if skip_slow_tests() { + return; + } + let code = r#" //- foo/Cargo.toml [package] @@ -170,6 +183,10 @@ fn main() {} #[test] fn test_format_document() { + if skip_slow_tests() { + return; + } + let server = project( r#" //- Cargo.toml @@ -222,6 +239,10 @@ pub use std::collections::HashMap; #[test] fn test_format_document_2018() { + if skip_slow_tests() { + return; + } + let server = project( r#" //- Cargo.toml @@ -277,8 +298,13 @@ pub use std::collections::HashMap; ]), ); } + #[test] fn test_missing_module_code_action() { + if skip_slow_tests() { + return; + } + let server = project( r#" //- Cargo.toml @@ -337,6 +363,10 @@ fn main() {} #[test] fn test_missing_module_code_action_in_json_project() { + if skip_slow_tests() { + return; + } + let tmp_dir = TempDir::new().unwrap(); let path = tmp_dir.path(); @@ -412,6 +442,10 @@ fn main() {{}} #[test] fn diagnostics_dont_block_typing() { + if skip_slow_tests() { + return; + } + let librs: String = (0..10).map(|i| format!("mod m{};", i)).collect(); let libs: String = (0..10).map(|i| format!("//- src/m{}.rs\nfn foo() {{}}\n\n", i)).collect(); let server = Project::with_fixture(&format!( @@ -480,6 +514,10 @@ fn main() {{}} #[test] fn preserves_dos_line_endings() { + if skip_slow_tests() { + return; + } + let server = Project::with_fixture( &" //- Cargo.toml diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 1244ea8cf1..657ddf2a69 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -356,6 +356,17 @@ pub fn read_text(path: &Path) -> String { .replace("\r\n", "\n") } +pub fn skip_slow_tests() -> bool { + let should_skip = std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err(); + if should_skip { + eprintln!("ignoring slow test") + } else { + let path = project_dir().join("./target/.slow_tests_cookie"); + fs::write(&path, ".").unwrap(); + } + should_skip +} + const REWRITE: bool = false; fn assert_equal_text(expected: &str, actual: &str, path: &Path) { From decc4cb084e7cfb9be845bf4b5ad06ff2c4c42c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 19:14:01 +0100 Subject: [PATCH 084/312] Show type hints for & patterns --- crates/ra_ide/src/inlay_hints.rs | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 59eced9d73..3730121afe 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -122,18 +122,11 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec { while let Some(maybe_leaf_pat) = pats_to_process.pop_front() { match &maybe_leaf_pat { - ast::Pat::BindPat(bind_pat) => { - if let Some(pat) = bind_pat.pat() { - pats_to_process.push_back(pat); - } else { - leaf_pats.push(maybe_leaf_pat); - } - } - ast::Pat::TuplePat(tuple_pat) => { - for arg_pat in tuple_pat.args() { - pats_to_process.push_back(arg_pat); - } - } + ast::Pat::BindPat(bind_pat) => match bind_pat.pat() { + Some(pat) => pats_to_process.push_back(pat), + _ => leaf_pats.push(maybe_leaf_pat), + }, + ast::Pat::TuplePat(tuple_pat) => pats_to_process.extend(tuple_pat.args()), ast::Pat::RecordPat(record_pat) => { if let Some(pat_list) = record_pat.record_field_pat_list() { pats_to_process.extend( @@ -151,10 +144,9 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec { } } ast::Pat::TupleStructPat(tuple_struct_pat) => { - for arg_pat in tuple_struct_pat.args() { - pats_to_process.push_back(arg_pat); - } + pats_to_process.extend(tuple_struct_pat.args()) } + ast::Pat::RefPat(ref_pat) => pats_to_process.extend(ref_pat.pat()), _ => (), } } @@ -163,9 +155,10 @@ fn get_leaf_pats(root_pat: ast::Pat) -> Vec { #[cfg(test)] mod tests { - use crate::mock_analysis::single_file; use insta::assert_debug_snapshot; + use crate::mock_analysis::single_file; + #[test] fn let_statement() { let (analysis, file_id) = single_file( @@ -202,6 +195,7 @@ fn main() { let test = (42, 'a'); let (a, (b, c, (d, e), f)) = (2, (3, 4, (6.6, 7.7), 5)); + let &x = &92; }"#, ); @@ -257,6 +251,11 @@ fn main() { kind: TypeHint, label: "f64", }, + InlayHint { + range: [627; 628), + kind: TypeHint, + label: "i32", + }, ] "### ); From d75f768c13752dfa5ea9189a0b4dfb9b460993e6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 17:34:28 +0100 Subject: [PATCH 085/312] Minor --- crates/ra_hir_def/src/generics.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 94ce835646..b3e345082b 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -58,11 +58,12 @@ impl GenericParams { GenericDefId::TraitId(it) => { // traits get the Self type as an implicit first type parameter generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); - generics.fill(&it.source(db).value); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name::SELF_TYPE.into()); generics.fill_bounds(&it.source(db).value, self_param); + + generics.fill(&it.source(db).value); } GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), // Note that we don't add `Self` here: in `impl`s, `Self` is not a @@ -75,7 +76,7 @@ impl GenericParams { generics } - fn fill(&mut self, node: &impl TypeParamsOwner) { + fn fill(&mut self, node: &dyn TypeParamsOwner) { if let Some(params) = node.type_param_list() { self.fill_params(params) } @@ -84,7 +85,7 @@ impl GenericParams { } } - fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { + fn fill_bounds(&mut self, node: &dyn ast::TypeBoundsOwner, type_ref: TypeRef) { for bound in node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) { From dda9587e75f4fd1740d16531038023ff582ef43f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 18:24:52 +0100 Subject: [PATCH 086/312] Track source of type parameters --- crates/ra_hir/src/code_model/src.rs | 12 +++- crates/ra_hir_def/src/generics.rs | 93 ++++++++++++++++++++++------- 2 files changed, 82 insertions(+), 23 deletions(-) diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 78a4540827..8f04ebd23a 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -9,8 +9,8 @@ use hir_def::{ use ra_syntax::ast; use crate::{ - db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, - Module, Static, Struct, StructField, Trait, TypeAlias, Union, + db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock, + Import, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, }; pub use hir_expand::InFile; @@ -129,3 +129,11 @@ impl HasSource for Import { src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) } } + +impl HasSource for GenericParam { + type Ast = Either; + fn source(self, db: &impl DefDatabase) -> InFile { + let child_source = self.id.parent.child_source(db); + child_source.map(|it| it[self.id.local_id].clone()) + } +} diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index b3e345082b..0df5a20f56 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -4,12 +4,18 @@ //! in rustc. use std::sync::Arc; -use hir_expand::name::{self, AsName, Name}; -use ra_arena::Arena; +use either::Either; +use hir_expand::{ + name::{self, AsName, Name}, + InFile, +}; +use ra_arena::{map::ArenaMap, Arena}; +use ra_db::FileId; use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ db::DefDatabase, + src::HasChildSource, src::HasSource, type_ref::{TypeBound, TypeRef}, AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, @@ -39,46 +45,81 @@ pub struct WherePredicate { pub bound: TypeBound, } +type SourceMap = ArenaMap>; + impl GenericParams { pub(crate) fn generic_params_query( db: &impl DefDatabase, def: GenericDefId, ) -> Arc { - Arc::new(GenericParams::new(db, def.into())) + let (params, _source_map) = GenericParams::new(db, def.into()); + Arc::new(params) } - fn new(db: &impl DefDatabase, def: GenericDefId) -> GenericParams { + fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile) { let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; + let mut sm = ArenaMap::default(); // FIXME: add `: Sized` bound for everything except for `Self` in traits - match def { - GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value), - GenericDefId::AdtId(AdtId::StructId(it)) => generics.fill(&it.source(db).value), - GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.source(db).value), - GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value), + let file_id = match def { + GenericDefId::FunctionId(it) => { + let src = it.lookup(db).source(db); + generics.fill(&mut sm, &src.value); + src.file_id + } + GenericDefId::AdtId(AdtId::StructId(it)) => { + let src = it.source(db); + generics.fill(&mut sm, &src.value); + src.file_id + } + GenericDefId::AdtId(AdtId::UnionId(it)) => { + let src = it.source(db); + generics.fill(&mut sm, &src.value); + src.file_id + } + GenericDefId::AdtId(AdtId::EnumId(it)) => { + let src = it.source(db); + generics.fill(&mut sm, &src.value); + src.file_id + } GenericDefId::TraitId(it) => { + let src = it.source(db); + // traits get the Self type as an implicit first type parameter - generics.params.alloc(GenericParamData { name: name::SELF_TYPE, default: None }); + let self_param_id = generics + .params + .alloc(GenericParamData { name: name::SELF_TYPE, default: None }); + sm.insert(self_param_id, Either::Left(src.value.clone())); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar let self_param = TypeRef::Path(name::SELF_TYPE.into()); - generics.fill_bounds(&it.source(db).value, self_param); + generics.fill_bounds(&src.value, self_param); - generics.fill(&it.source(db).value); + generics.fill(&mut sm, &src.value); + src.file_id + } + GenericDefId::TypeAliasId(it) => { + let src = it.lookup(db).source(db); + generics.fill(&mut sm, &src.value); + src.file_id } - GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value), // Note that we don't add `Self` here: in `impl`s, `Self` is not a // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. - GenericDefId::ImplId(it) => generics.fill(&it.source(db).value), - GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {} - } + GenericDefId::ImplId(it) => { + let src = it.source(db); + generics.fill(&mut sm, &src.value); + src.file_id + } + // We won't be using this ID anyway + GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), + }; - generics + (generics, InFile::new(file_id, sm)) } - fn fill(&mut self, node: &dyn TypeParamsOwner) { + fn fill(&mut self, sm: &mut SourceMap, node: &dyn TypeParamsOwner) { if let Some(params) = node.type_param_list() { - self.fill_params(params) + self.fill_params(sm, params) } if let Some(where_clause) = node.where_clause() { self.fill_where_predicates(where_clause); @@ -93,13 +134,14 @@ impl GenericParams { } } - fn fill_params(&mut self, params: ast::TypeParamList) { + fn fill_params(&mut self, sm: &mut SourceMap, params: ast::TypeParamList) { for type_param in params.type_params() { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` let default = type_param.default_type().map(TypeRef::from_ast); let param = GenericParamData { name: name.clone(), default }; - self.params.alloc(param); + let param_id = self.params.alloc(param); + sm.insert(param_id, Either::Right(type_param.clone())); let type_ref = TypeRef::Path(name.into()); self.fill_bounds(&type_param, type_ref); @@ -132,3 +174,12 @@ impl GenericParams { self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) } } + +impl HasChildSource for GenericDefId { + type ChildId = LocalGenericParamId; + type Value = Either; + fn child_source(&self, db: &impl DefDatabase) -> InFile { + let (_, sm) = GenericParams::new(db, *self); + sm + } +} From 1692f07393dba4f5c122df1a609d5b18751bf406 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 18:48:35 +0100 Subject: [PATCH 087/312] ToNav for GenericParam --- crates/ra_hir/src/code_model.rs | 7 ++++++ .../ra_ide/src/display/navigation_target.rs | 22 ++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 29ace8479d..8833750c84 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -860,6 +860,13 @@ pub struct GenericParam { pub(crate) id: GenericParamId, } +impl GenericParam { + pub fn name(self, db: &impl HirDatabase) -> Name { + let params = db.generic_params(self.id.parent); + params.params[self.id.local_id].name.clone() + } +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplBlock { pub(crate) id: ImplId, diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index add11fbc36..e8c3d980fb 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -6,7 +6,7 @@ use ra_db::{FileId, SourceDatabase}; use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, match_ast, AstNode, SmolStr, - SyntaxKind::{self, BIND_PAT}, + SyntaxKind::{self, BIND_PAT, TYPE_PARAM}, TextRange, }; @@ -351,6 +351,26 @@ impl ToNav for hir::Local { } } +impl ToNav for hir::GenericParam { + fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { + let src = self.source(db); + let range = match src.value { + Either::Left(it) => it.syntax().text_range(), + Either::Right(it) => it.syntax().text_range(), + }; + NavigationTarget { + file_id: src.file_id.original_file(db), + name: self.name(db).to_string().into(), + kind: TYPE_PARAM, + full_range: range, + focus_range: None, + container_name: None, + description: None, + docs: None, + } + } +} + pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option { let parse = db.parse(symbol.file_id); let node = symbol.ptr.to_node(parse.tree().syntax()); From d1a01aa2f8ca9eff9ba2321f2f113623742e212c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 18:54:18 +0100 Subject: [PATCH 088/312] Gotodef for TypeParameters --- crates/ra_ide/src/goto_definition.rs | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index d3c1988132..64c0cbad48 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -64,9 +64,11 @@ pub(crate) fn reference_definition( let name_kind = classify_name_ref(db, name_ref).map(|d| d.kind); match name_kind { - Some(Macro(mac)) => return Exact(mac.to_nav(db)), - Some(Field(field)) => return Exact(field.to_nav(db)), - Some(AssocItem(assoc)) => return Exact(assoc.to_nav(db)), + Some(Macro(it)) => return Exact(it.to_nav(db)), + Some(Field(it)) => return Exact(it.to_nav(db)), + Some(GenericParam(it)) => return Exact(it.to_nav(db)), + Some(AssocItem(it)) => return Exact(it.to_nav(db)), + Some(Local(it)) => return Exact(it.to_nav(db)), Some(Def(def)) => match NavigationTarget::from_def(db, def) { Some(nav) => return Exact(nav), None => return Approximate(vec![]), @@ -77,10 +79,6 @@ pub(crate) fn reference_definition( // us to the actual type return Exact(imp.to_nav(db)); } - Some(Local(local)) => return Exact(local.to_nav(db)), - Some(GenericParam(_)) => { - // FIXME: go to the generic param def - } None => {} }; @@ -723,4 +721,17 @@ mod tests { "foo FN_DEF FileId(1) [359; 376) [362; 365)", ); } + + #[test] + fn goto_for_type_param() { + check_goto( + " + //- /lib.rs + struct Foo { + t: <|>T, + } + ", + "T TYPE_PARAM FileId(1) [11; 12)", + ); + } } From 7d2080a0311cab62388f416beeb360695dbc5ded Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 19:52:09 +0100 Subject: [PATCH 089/312] Classify name works for TypeParams --- crates/ra_hir/src/code_model.rs | 4 ++++ crates/ra_hir/src/from_source.rs | 23 ++++++++++++++++++++--- crates/ra_hir_def/src/generics.rs | 20 +++++++++++++++++++- crates/ra_hir_def/src/keys.rs | 3 ++- crates/ra_hir_def/src/lib.rs | 14 ++++++++++++++ crates/ra_ide/src/references/classify.rs | 9 +++++++++ 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 8833750c84..0295eb9486 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -865,6 +865,10 @@ impl GenericParam { let params = db.generic_params(self.id.parent); params.params[self.id.local_id].name.clone() } + + pub fn module(self, db: &impl HirDatabase) -> Module { + self.id.parent.module(db).into() + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 437f800c1e..686ab1d79f 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir_def::{ child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef, - EnumVariantId, LocationCtx, ModuleId, VariantId, + EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -11,8 +11,8 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, - MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock, InFile, + Local, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, }; pub trait FromSource: Sized { @@ -177,6 +177,23 @@ impl Local { } } +impl GenericParam { + pub fn from_source(db: &impl HirDatabase, src: InFile) -> Option { + let file_id = src.file_id; + let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { + let res = match_ast! { + match it { + ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() }, + _ => return None, + } + }; + Some(res) + })?; + let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?; + Some(GenericParam { id }) + } +} + impl Module { pub fn from_declaration(db: &impl DefDatabase, src: InFile) -> Option { let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast); diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 0df5a20f56..159f9034bc 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -14,11 +14,14 @@ use ra_db::FileId; use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner}; use crate::{ + child_by_source::ChildBySource, db::DefDatabase, + dyn_map::DynMap, + keys, src::HasChildSource, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, GenericDefId, LocalGenericParamId, Lookup, + AdtId, AstItemDef, GenericDefId, GenericParamId, LocalGenericParamId, Lookup, }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -183,3 +186,18 @@ impl HasChildSource for GenericDefId { sm } } + +impl ChildBySource for GenericDefId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + let arena_map = self.child_source(db); + let arena_map = arena_map.as_ref(); + for (local_id, src) in arena_map.value.iter() { + let id = GenericParamId { parent: *self, local_id }; + if let Either::Right(type_param) = src { + res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) + } + } + res + } +} diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index 447b7e3baa..ca5630c801 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, + ConstId, EnumVariantId, FunctionId, GenericParamId, StaticId, StructFieldId, TypeAliasId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -20,6 +20,7 @@ pub const ENUM_VARIANT: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); +pub const TYPE_PARAM: Key = Key::new(); /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// equal if they point to exactly the same object. diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index b8dfc0ab1a..6dfb3c03d0 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -525,6 +525,20 @@ impl HasModule for DefWithBodyId { } } +impl HasModule for GenericDefId { + fn module(&self, db: &impl db::DefDatabase) -> ModuleId { + match self { + GenericDefId::FunctionId(it) => it.lookup(db).module(db), + GenericDefId::AdtId(it) => it.module(db), + GenericDefId::TraitId(it) => it.module(db), + GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), + GenericDefId::ImplId(it) => it.module(db), + GenericDefId::EnumVariantId(it) => it.parent.module(db), + GenericDefId::ConstId(it) => it.lookup(db).module(db), + } + } +} + impl HasModule for StaticLoc { fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { self.container diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index b716d32e59..65df2e3352 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -110,6 +110,15 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti kind: NameKind::Macro(def), }) }, + ast::TypeParam(it) => { + let src = name.with_value(it); + let def = hir::GenericParam::from_source(db, src)?; + Some(NameDefinition { + visibility: None, + container: def.module(db), + kind: NameKind::GenericParam(def), + }) + }, _ => None, } } From f4f8b8147426b0096d4b5126e487caaa13d13c27 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 20:05:08 +0100 Subject: [PATCH 090/312] Get the right analyzer for impls --- crates/ra_hir/src/source_binder.rs | 6 +++++- crates/ra_ide/src/references/classify.rs | 1 - crates/ra_ide/src/snapshots/highlighting.html | 9 +++++++++ crates/ra_ide/src/syntax_highlighting.rs | 9 +++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 8c4b635d22..2957e496c1 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -37,7 +37,7 @@ use crate::{ InEnvironment, TraitEnvironment, Ty, }, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, GenericParam, - Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, + ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option { @@ -59,6 +59,10 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) - let src = node.with_value(it); Some(Enum::from_source(db, src)?.id.resolver(db)) }, + ast::ImplBlock(it) => { + let src = node.with_value(it); + Some(ImplBlock::from_source(db, src)?.id.resolver(db)) + }, _ => match node.value.kind() { FN_DEF | CONST_DEF | STATIC_DEF => { let def = def_with_body_from_child_node(db, node)?; diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 65df2e3352..ed98dbc13a 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -178,7 +178,6 @@ pub(crate) fn classify_name_ref( Some(NameDefinition { kind, container, visibility: None }) } PathResolution::GenericParam(par) => { - // FIXME: get generic param def let kind = NameKind::GenericParam(par); Some(NameDefinition { kind, container, visibility }) } diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index b39c4d3717..4166a8f90d 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -9,6 +9,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .parameter { color: #94BFF3; } .builtin { color: #DD6718; } .text { color: #DCDCCC; } +.type { color: #7CB8BB; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } .macro { color: #94BFF3; } @@ -45,4 +46,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd let z = &y; y; +} + +enum E<X> { + V(X) +} + +impl<X> E<X> { + fn new<T>() -> E<T> {} } \ No newline at end of file diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index e6a79541fe..20eefeb57a 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -255,6 +255,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .parameter { color: #94BFF3; } .builtin { color: #DD6718; } .text { color: #DCDCCC; } +.type { color: #7CB8BB; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } .macro { color: #94BFF3; } @@ -303,6 +304,14 @@ fn main() { y; } + +enum E { + V(X) +} + +impl E { + fn new() -> E {} +} "# .trim(), ); From 88c5b1282a5770097c6c768b24bedfc3a6944e08 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 20:09:53 +0100 Subject: [PATCH 091/312] Rename GenericParam -> TypeParam We don't have LifetimeParam yet, but they are planned! --- crates/ra_hir/src/code_model.rs | 16 +++++------ crates/ra_hir/src/code_model/src.rs | 6 ++-- crates/ra_hir/src/from_source.rs | 8 +++--- crates/ra_hir/src/lib.rs | 6 ++-- crates/ra_hir/src/source_binder.rs | 10 +++---- crates/ra_hir_def/src/generics.rs | 28 +++++++++---------- crates/ra_hir_def/src/keys.rs | 4 +-- crates/ra_hir_def/src/lib.rs | 8 +++--- crates/ra_hir_def/src/resolver.rs | 18 ++++++------ crates/ra_hir_ty/src/utils.rs | 26 ++++++++--------- .../ra_ide/src/display/navigation_target.rs | 2 +- crates/ra_ide/src/goto_definition.rs | 2 +- crates/ra_ide/src/hover.rs | 2 +- crates/ra_ide/src/references.rs | 2 +- crates/ra_ide/src/references/classify.rs | 8 +++--- .../ra_ide/src/references/name_definition.rs | 6 ++-- .../src/snapshots/rainbow_highlighting.html | 1 + crates/ra_ide/src/syntax_highlighting.rs | 3 +- 18 files changed, 77 insertions(+), 79 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0295eb9486..4578a0ba8e 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -15,9 +15,9 @@ use hir_def::{ per_ns::PerNs, resolver::HasResolver, type_ref::{Mutability, TypeRef}, - AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, GenericParamId, - HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, - Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, + AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, + LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -856,14 +856,14 @@ impl Local { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct GenericParam { - pub(crate) id: GenericParamId, +pub struct TypeParam { + pub(crate) id: TypeParamId, } -impl GenericParam { +impl TypeParam { pub fn name(self, db: &impl HirDatabase) -> Name { let params = db.generic_params(self.id.parent); - params.params[self.id.local_id].name.clone() + params.types[self.id.local_id].name.clone() } pub fn module(self, db: &impl HirDatabase) -> Module { @@ -1111,7 +1111,7 @@ impl HirDisplay for Type { pub enum ScopeDef { ModuleDef(ModuleDef), MacroDef(MacroDef), - GenericParam(GenericParam), + GenericParam(TypeParam), ImplSelfType(ImplBlock), AdtSelfType(Adt), Local(Local), diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 8f04ebd23a..b09582f93c 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -9,8 +9,8 @@ use hir_def::{ use ra_syntax::ast; use crate::{ - db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock, - Import, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, + db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, + Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub use hir_expand::InFile; @@ -130,7 +130,7 @@ impl HasSource for Import { } } -impl HasSource for GenericParam { +impl HasSource for TypeParam { type Ast = Either; fn source(self, db: &impl DefDatabase) -> InFile { let child_source = self.id.parent.child_source(db); diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 686ab1d79f..68e59fc1ec 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -11,8 +11,8 @@ use ra_syntax::{ use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, - Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, GenericParam, ImplBlock, InFile, - Local, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, Union, + Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, + MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub trait FromSource: Sized { @@ -177,7 +177,7 @@ impl Local { } } -impl GenericParam { +impl TypeParam { pub fn from_source(db: &impl HirDatabase, src: InFile) -> Option { let file_id = src.file_id; let parent: GenericDefId = src.value.syntax().ancestors().find_map(|it| { @@ -190,7 +190,7 @@ impl GenericParam { Some(res) })?; let &id = parent.child_by_source(db)[keys::TYPE_PARAM].get(&src)?; - Some(GenericParam { id }) + Some(TypeParam { id }) } } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index f12e4ca3f2..9eb34b5dcd 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -42,9 +42,9 @@ pub mod from_source; pub use crate::{ code_model::{ src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, - DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, GenericParam, - HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, - StructField, Trait, Type, TypeAlias, Union, VariantDef, + DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs, + ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, + StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, }, from_source::FromSource, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 2957e496c1..b80aaeb901 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -36,8 +36,8 @@ use crate::{ method_resolution::{self, implements_trait}, InEnvironment, TraitEnvironment, Ty, }, - Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, GenericParam, - ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, + Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock, Local, + MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option { @@ -112,7 +112,7 @@ pub enum PathResolution { /// A local binding (only value namespace) Local(Local), /// A generic parameter - GenericParam(GenericParam), + TypeParam(TypeParam), SelfType(crate::ImplBlock), Macro(MacroDef), AssocItem(crate::AssocItem), @@ -266,7 +266,7 @@ impl SourceAnalyzer { ) -> Option { let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::GenericParam(GenericParam { id }), + TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { PathResolution::Def(Adt::from(it).into()) } @@ -338,7 +338,7 @@ impl SourceAnalyzer { resolver::ScopeDef::PerNs(it) => it.into(), resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()), resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()), - resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(GenericParam { id }), + resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(TypeParam { id }), resolver::ScopeDef::Local(pat_id) => { let parent = self.resolver.body_owner().unwrap().into(); ScopeDef::Local(Local { parent, pat_id }) diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 159f9034bc..976cf72d09 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -21,12 +21,12 @@ use crate::{ src::HasChildSource, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, GenericDefId, GenericParamId, LocalGenericParamId, Lookup, + AdtId, AstItemDef, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, }; /// Data about a generic parameter (to a function, struct, impl, ...). #[derive(Clone, PartialEq, Eq, Debug)] -pub struct GenericParamData { +pub struct TypeParamData { pub name: Name, pub default: Option, } @@ -34,7 +34,8 @@ pub struct GenericParamData { /// Data about the generic parameters of a function, struct, impl, etc. #[derive(Clone, PartialEq, Eq, Debug)] pub struct GenericParams { - pub params: Arena, + pub types: Arena, + // lifetimes: Arena, pub where_predicates: Vec, } @@ -48,7 +49,7 @@ pub struct WherePredicate { pub bound: TypeBound, } -type SourceMap = ArenaMap>; +type SourceMap = ArenaMap>; impl GenericParams { pub(crate) fn generic_params_query( @@ -60,7 +61,7 @@ impl GenericParams { } fn new(db: &impl DefDatabase, def: GenericDefId) -> (GenericParams, InFile) { - let mut generics = GenericParams { params: Arena::default(), where_predicates: Vec::new() }; + let mut generics = GenericParams { types: Arena::default(), where_predicates: Vec::new() }; let mut sm = ArenaMap::default(); // FIXME: add `: Sized` bound for everything except for `Self` in traits let file_id = match def { @@ -88,9 +89,8 @@ impl GenericParams { let src = it.source(db); // traits get the Self type as an implicit first type parameter - let self_param_id = generics - .params - .alloc(GenericParamData { name: name::SELF_TYPE, default: None }); + let self_param_id = + generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None }); sm.insert(self_param_id, Either::Left(src.value.clone())); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar @@ -142,8 +142,8 @@ impl GenericParams { let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); // FIXME: Use `Path::from_src` let default = type_param.default_type().map(TypeRef::from_ast); - let param = GenericParamData { name: name.clone(), default }; - let param_id = self.params.alloc(param); + let param = TypeParamData { name: name.clone(), default }; + let param_id = self.types.alloc(param); sm.insert(param_id, Either::Right(type_param.clone())); let type_ref = TypeRef::Path(name.into()); @@ -173,13 +173,13 @@ impl GenericParams { self.where_predicates.push(WherePredicate { type_ref, bound }); } - pub fn find_by_name(&self, name: &Name) -> Option { - self.params.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) + pub fn find_by_name(&self, name: &Name) -> Option { + self.types.iter().find_map(|(id, p)| if &p.name == name { Some(id) } else { None }) } } impl HasChildSource for GenericDefId { - type ChildId = LocalGenericParamId; + type ChildId = LocalTypeParamId; type Value = Either; fn child_source(&self, db: &impl DefDatabase) -> InFile { let (_, sm) = GenericParams::new(db, *self); @@ -193,7 +193,7 @@ impl ChildBySource for GenericDefId { let arena_map = self.child_source(db); let arena_map = arena_map.as_ref(); for (local_id, src) in arena_map.value.iter() { - let id = GenericParamId { parent: *self, local_id }; + let id = TypeParamId { parent: *self, local_id }; if let Either::Right(type_param) = src { res[keys::TYPE_PARAM].insert(arena_map.with_value(type_param.clone()), id) } diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index ca5630c801..be702a4f80 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, GenericParamId, StaticId, StructFieldId, TypeAliasId, + ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, TypeParamId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -20,7 +20,7 @@ pub const ENUM_VARIANT: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); -pub const TYPE_PARAM: Key = Key::new(); +pub const TYPE_PARAM: Key = Key::new(); /// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are /// equal if they point to exactly the same object. diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 6dfb3c03d0..569da4f284 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -318,14 +318,14 @@ macro_rules! impl_froms { } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct GenericParamId { +pub struct TypeParamId { pub parent: GenericDefId, - pub local_id: LocalGenericParamId, + pub local_id: LocalTypeParamId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalGenericParamId(RawId); -impl_arena_id!(LocalGenericParamId); +pub struct LocalTypeParamId(RawId); +impl_arena_id!(LocalTypeParamId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ContainerId { diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index e00bd03d54..4c859e497f 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -18,8 +18,8 @@ use crate::{ path::{Path, PathKind}, per_ns::PerNs, AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, GenericParamId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, - StaticId, StructId, TraitId, TypeAliasId, + GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, + StructId, TraitId, TypeAliasId, TypeParamId, }; #[derive(Debug, Clone, Default)] @@ -59,7 +59,7 @@ enum Scope { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum TypeNs { SelfType(ImplId), - GenericParam(GenericParamId), + GenericParam(TypeParamId), AdtId(AdtId), AdtSelfType(AdtId), // Yup, enum variants are added to the types ns, but any usage of variant as @@ -157,7 +157,7 @@ impl Resolver { if let Some(local_id) = params.find_by_name(first_name) { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some(( - TypeNs::GenericParam(GenericParamId { local_id, parent: *def }), + TypeNs::GenericParam(TypeParamId { local_id, parent: *def }), idx, )); } @@ -252,7 +252,7 @@ impl Resolver { Scope::GenericParams { params, def } if n_segments > 1 => { if let Some(local_id) = params.find_by_name(first_name) { - let ty = TypeNs::GenericParam(GenericParamId { local_id, parent: *def }); + let ty = TypeNs::GenericParam(TypeParamId { local_id, parent: *def }); return Some(ResolveValueResult::Partial(ty, 1)); } } @@ -399,7 +399,7 @@ pub enum ScopeDef { PerNs(PerNs), ImplSelfType(ImplId), AdtSelfType(AdtId), - GenericParam(GenericParamId), + GenericParam(TypeParamId), Local(PatId), } @@ -431,10 +431,10 @@ impl Scope { } } Scope::GenericParams { params, def } => { - for (local_id, param) in params.params.iter() { + for (local_id, param) in params.types.iter() { f( param.name.clone(), - ScopeDef::GenericParam(GenericParamId { local_id, parent: *def }), + ScopeDef::GenericParam(TypeParamId { local_id, parent: *def }), ) } } @@ -481,7 +481,7 @@ impl Resolver { fn push_generic_params_scope(self, db: &impl DefDatabase, def: GenericDefId) -> Resolver { let params = db.generic_params(def); - if params.params.is_empty() { + if params.types.is_empty() { self } else { self.push_scope(Scope::GenericParams { def, params }) diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 936cfe25e0..aeb211a91c 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -5,10 +5,10 @@ use std::sync::Arc; use hir_def::{ adt::VariantData, db::DefDatabase, - generics::{GenericParamData, GenericParams}, + generics::{GenericParams, TypeParamData}, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, - ContainerId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId, VariantId, + ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, }; use hir_expand::name::{self, Name}; @@ -96,23 +96,21 @@ pub(crate) struct Generics { } impl Generics { - pub(crate) fn iter<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn iter<'a>(&'a self) -> impl Iterator + 'a { self.parent_generics .as_ref() .into_iter() - .flat_map(|it| it.params.params.iter()) - .chain(self.params.params.iter()) + .flat_map(|it| it.params.types.iter()) + .chain(self.params.types.iter()) .enumerate() .map(|(i, (_local_id, p))| (i as u32, p)) } - pub(crate) fn iter_parent<'a>( - &'a self, - ) -> impl Iterator + 'a { + pub(crate) fn iter_parent<'a>(&'a self) -> impl Iterator + 'a { self.parent_generics .as_ref() .into_iter() - .flat_map(|it| it.params.params.iter()) + .flat_map(|it| it.params.types.iter()) .enumerate() .map(|(i, (_local_id, p))| (i as u32, p)) } @@ -123,20 +121,20 @@ impl Generics { /// (total, parents, child) pub(crate) fn len_split(&self) -> (usize, usize, usize) { let parent = self.parent_generics.as_ref().map_or(0, |p| p.len()); - let child = self.params.params.len(); + let child = self.params.types.len(); (parent + child, parent, child) } - pub(crate) fn param_idx(&self, param: GenericParamId) -> u32 { + pub(crate) fn param_idx(&self, param: TypeParamId) -> u32 { self.find_param(param).0 } - pub(crate) fn param_name(&self, param: GenericParamId) -> Name { + pub(crate) fn param_name(&self, param: TypeParamId) -> Name { self.find_param(param).1.name.clone() } - fn find_param(&self, param: GenericParamId) -> (u32, &GenericParamData) { + fn find_param(&self, param: TypeParamId) -> (u32, &TypeParamData) { if param.parent == self.def { let (idx, (_local_id, data)) = self .params - .params + .types .iter() .enumerate() .find(|(_, (idx, _))| *idx == param.local_id) diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index e8c3d980fb..6a6b49afdf 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -351,7 +351,7 @@ impl ToNav for hir::Local { } } -impl ToNav for hir::GenericParam { +impl ToNav for hir::TypeParam { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); let range = match src.value { diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 64c0cbad48..1b968134d6 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -66,7 +66,7 @@ pub(crate) fn reference_definition( match name_kind { Some(Macro(it)) => return Exact(it.to_nav(db)), Some(Field(it)) => return Exact(it.to_nav(db)), - Some(GenericParam(it)) => return Exact(it.to_nav(db)), + Some(TypeParam(it)) => return Exact(it.to_nav(db)), Some(AssocItem(it)) => return Exact(it.to_nav(db)), Some(Local(it)) => return Exact(it.to_nav(db)), Some(Def(def)) => match NavigationTarget::from_def(db, def) { diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index d8185c6889..d372ca758e 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -138,7 +138,7 @@ fn hover_text_from_name_kind( *no_fallback = true; None } - GenericParam(_) | SelfType(_) => { + TypeParam(_) | SelfType(_) => { // FIXME: Hover for generic param None } diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index 3e7bfd872e..e3ecde50dd 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs @@ -85,7 +85,7 @@ pub(crate) fn find_all_refs( NameKind::Def(def) => NavigationTarget::from_def(db, def)?, NameKind::SelfType(imp) => imp.to_nav(db), NameKind::Local(local) => local.to_nav(db), - NameKind::GenericParam(_) => return None, + NameKind::TypeParam(_) => return None, }; let search_scope = { diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index ed98dbc13a..c1f091ec08 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -112,11 +112,11 @@ pub(crate) fn classify_name(db: &RootDatabase, name: InFile<&ast::Name>) -> Opti }, ast::TypeParam(it) => { let src = name.with_value(it); - let def = hir::GenericParam::from_source(db, src)?; + let def = hir::TypeParam::from_source(db, src)?; Some(NameDefinition { visibility: None, container: def.module(db), - kind: NameKind::GenericParam(def), + kind: NameKind::TypeParam(def), }) }, _ => None, @@ -177,8 +177,8 @@ pub(crate) fn classify_name_ref( let kind = NameKind::Local(local); Some(NameDefinition { kind, container, visibility: None }) } - PathResolution::GenericParam(par) => { - let kind = NameKind::GenericParam(par); + PathResolution::TypeParam(par) => { + let kind = NameKind::TypeParam(par); Some(NameDefinition { kind, container, visibility }) } PathResolution::Macro(def) => { diff --git a/crates/ra_ide/src/references/name_definition.rs b/crates/ra_ide/src/references/name_definition.rs index 10d3a2364c..8c67c88639 100644 --- a/crates/ra_ide/src/references/name_definition.rs +++ b/crates/ra_ide/src/references/name_definition.rs @@ -4,8 +4,8 @@ //! Note that the reference search is possible for not all of the classified items. use hir::{ - Adt, AssocItem, GenericParam, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, - StructField, VariantDef, + Adt, AssocItem, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, StructField, + TypeParam, VariantDef, }; use ra_syntax::{ast, ast::VisibilityOwner}; @@ -19,7 +19,7 @@ pub enum NameKind { Def(ModuleDef), SelfType(ImplBlock), Local(Local), - GenericParam(GenericParam), + TypeParam(TypeParam), } #[derive(PartialEq, Eq)] diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 79f11ea80c..9dfbc80475 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -9,6 +9,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .parameter { color: #94BFF3; } .builtin { color: #DD6718; } .text { color: #DCDCCC; } +.type { color: #7CB8BB; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } .macro { color: #94BFF3; } diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 20eefeb57a..7ecb1a0272 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -225,8 +225,7 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { Def(hir::ModuleDef::Trait(_)) => "type", Def(hir::ModuleDef::TypeAlias(_)) => "type", Def(hir::ModuleDef::BuiltinType(_)) => "type", - SelfType(_) => "type", - GenericParam(_) => "type", + SelfType(_) | TypeParam(_) => "type", Local(local) => { if local.is_mut(db) { "variable.mut" From 6e2e60cbc9226dd3f43cf2b83ff6f5a0cf39e639 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 7 Dec 2019 21:55:02 +0100 Subject: [PATCH 092/312] Discover type parameters in more cases --- crates/ra_hir/src/from_source.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 68e59fc1ec..4acc038e45 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -184,6 +184,11 @@ impl TypeParam { let res = match_ast! { match it { ast::FnDef(value) => { Function::from_source(db, InFile { value, file_id})?.id.into() }, + ast::StructDef(value) => { Struct::from_source(db, InFile { value, file_id})?.id.into() }, + ast::EnumDef(value) => { Enum::from_source(db, InFile { value, file_id})?.id.into() }, + ast::TraitDef(value) => { Trait::from_source(db, InFile { value, file_id})?.id.into() }, + ast::TypeAliasDef(value) => { TypeAlias::from_source(db, InFile { value, file_id})?.id.into() }, + ast::ImplBlock(value) => { ImplBlock::from_source(db, InFile { value, file_id})?.id.into() }, _ => return None, } }; From 509fedd9d2f228c6dca762cbf06c31af34ac0c75 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 8 Dec 2019 16:16:52 +0800 Subject: [PATCH 093/312] Remove MacroFileKind --- crates/ra_hir/src/source_binder.rs | 41 +------------------- crates/ra_hir_def/src/body.rs | 6 +-- crates/ra_hir_def/src/nameres/collector.rs | 4 +- crates/ra_hir_expand/src/builtin_derive.rs | 4 +- crates/ra_hir_expand/src/builtin_macro.rs | 9 ++--- crates/ra_hir_expand/src/db.rs | 45 ++++++++++++++++++---- crates/ra_hir_expand/src/lib.rs | 13 +------ 7 files changed, 52 insertions(+), 70 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index b80aaeb901..c5a920688f 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -21,7 +21,6 @@ use hir_def::{ }; use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, - MacroFileKind, }; use ra_syntax::{ ast::{self, AstNode}, @@ -142,7 +141,6 @@ pub struct ReferenceDescriptor { #[derive(Debug)] pub struct Expansion { - macro_file_kind: MacroFileKind, macro_call_id: MacroCallId, } @@ -157,7 +155,7 @@ impl Expansion { } pub fn file_id(&self) -> HirFileId { - self.macro_call_id.as_file(self.macro_file_kind) + self.macro_call_id.as_file() } } @@ -456,10 +454,7 @@ impl SourceAnalyzer { macro_call.file_id, db.ast_id_map(macro_call.file_id).ast_id(macro_call.value), ); - Some(Expansion { - macro_call_id: def.as_call_id(db, MacroCallKind::FnLike(ast_id)), - macro_file_kind: to_macro_file_kind(macro_call.value), - }) + Some(Expansion { macro_call_id: def.as_call_id(db, MacroCallKind::FnLike(ast_id)) }) } } @@ -543,35 +538,3 @@ fn adjust( }) .map(|(_ptr, scope)| *scope) } - -/// Given a `ast::MacroCall`, return what `MacroKindFile` it belongs to. -/// FIXME: Not completed -fn to_macro_file_kind(macro_call: &ast::MacroCall) -> MacroFileKind { - let syn = macro_call.syntax(); - let parent = match syn.parent() { - Some(it) => it, - None => { - // FIXME: - // If it is root, which means the parent HirFile - // MacroKindFile must be non-items - // return expr now. - return MacroFileKind::Expr; - } - }; - - match parent.kind() { - MACRO_ITEMS | SOURCE_FILE => MacroFileKind::Items, - LET_STMT => { - // FIXME: Handle Pattern - MacroFileKind::Expr - } - EXPR_STMT => MacroFileKind::Statements, - BLOCK => MacroFileKind::Statements, - ARG_LIST => MacroFileKind::Expr, - TRY_EXPR => MacroFileKind::Expr, - _ => { - // Unknown , Just guess it is `Items` - MacroFileKind::Items - } - } -} diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7b385f3fd8..b3bc336cf9 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -6,9 +6,7 @@ pub mod scope; use std::{ops::Index, sync::Arc}; use either::Either; -use hir_expand::{ - hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, MacroFileKind, -}; +use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -49,7 +47,7 @@ impl Expander { if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { if let Some(def) = self.resolve_path_as_macro(db, &path) { let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); - let file_id = call_id.as_file(MacroFileKind::Expr); + let file_id = call_id.as_file(); if let Some(node) = db.parse_or_expand(file_id) { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 08693cb13a..6a01e3ab7b 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -7,7 +7,7 @@ use hir_expand::{ builtin_derive::find_builtin_derive, builtin_macro::find_builtin_macro, name::{self, AsName, Name}, - HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, MacroFileKind, + HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, }; use ra_cfg::CfgOptions; use ra_db::{CrateId, FileId}; @@ -545,7 +545,7 @@ where self.macro_stack_monitor.increase(macro_def_id); if !self.macro_stack_monitor.is_poison(macro_def_id) { - let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items); + let file_id: HirFileId = macro_call_id.as_file(); let raw_items = self.db.raw_items(file_id); let mod_dir = self.mod_dirs[&module_id].clone(); ModCollector { diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 78fa9b09a2..5746376022 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -208,7 +208,7 @@ fn partial_ord_expand( #[cfg(test)] mod tests { use super::*; - use crate::{test_db::TestDB, AstId, MacroCallKind, MacroCallLoc, MacroFileKind}; + use crate::{test_db::TestDB, AstId, MacroCallKind, MacroCallLoc}; use ra_db::{fixture::WithFixture, SourceDatabase}; fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String { @@ -229,7 +229,7 @@ mod tests { }; let id = db.intern_macro(loc); - let parsed = db.parse_or_expand(id.as_file(MacroFileKind::Items)).unwrap(); + let parsed = db.parse_or_expand(id.as_file()).unwrap(); // FIXME text() for syntax nodes parsed from token tree looks weird // because there's no whitespace, see below diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 99303188bf..c7071fe85a 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -2,8 +2,7 @@ use crate::db::AstDatabase; use crate::{ ast::{self, AstNode}, - name, AstId, CrateId, HirFileId, MacroCallId, MacroDefId, MacroDefKind, MacroFileKind, - TextUnit, + name, AstId, CrateId, HirFileId, MacroCallId, MacroDefId, MacroDefKind, TextUnit, }; use crate::quote; @@ -90,7 +89,7 @@ fn line_expand( let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; let arg_start = arg.text_range().start(); - let file = id.as_file(MacroFileKind::Expr); + let file = id.as_file(); let line_num = to_line_number(db, file, arg_start); let expanded = quote! { @@ -158,7 +157,7 @@ fn column_expand( let _arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; let col_start = macro_call.syntax().text_range().start(); - let file = id.as_file(MacroFileKind::Expr); + let file = id.as_file(); let col_num = to_col_number(db, file, col_start); let expanded = quote! { @@ -269,7 +268,7 @@ mod tests { }; let id = db.intern_macro(loc); - let parsed = db.parse_or_expand(id.as_file(MacroFileKind::Expr)).unwrap(); + let parsed = db.parse_or_expand(id.as_file()).unwrap(); parsed.text().to_string() } diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 013a6c8ba9..4bdb41619c 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -6,11 +6,11 @@ use mbe::MacroRules; use ra_db::{salsa, SourceDatabase}; use ra_parser::FragmentKind; use ra_prof::profile; -use ra_syntax::{AstNode, Parse, SyntaxNode}; +use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode}; use crate::{ ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, - MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, MacroFileKind, + MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, }; #[derive(Debug, Clone, Eq, PartialEq)] @@ -155,11 +155,42 @@ pub(crate) fn parse_macro( }) .ok()?; - let fragment_kind = match macro_file.macro_file_kind { - MacroFileKind::Items => FragmentKind::Items, - MacroFileKind::Expr => FragmentKind::Expr, - MacroFileKind::Statements => FragmentKind::Statements, - }; + let fragment_kind = to_fragment_kind(db, macro_call_id); + let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; Some((parse, Arc::new(rev_token_map))) } + +/// Given a `MacroCallId`, return what `FragmentKind` it belongs to. +/// FIXME: Not completed +fn to_fragment_kind(db: &dyn AstDatabase, macro_call_id: MacroCallId) -> FragmentKind { + let syn = db.lookup_intern_macro(macro_call_id).kind.node(db).value; + + let parent = match syn.parent() { + Some(it) => it, + None => { + // FIXME: + // If it is root, which means the parent HirFile + // MacroKindFile must be non-items + // return expr now. + return FragmentKind::Expr; + } + }; + + match parent.kind() { + MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items, + LET_STMT => { + // FIXME: Handle Pattern + FragmentKind::Expr + } + EXPR_STMT => FragmentKind::Statements, + BLOCK => FragmentKind::Statements, + ARG_LIST => FragmentKind::Expr, + TRY_EXPR => FragmentKind::Expr, + TUPLE_EXPR => FragmentKind::Expr, + _ => { + // Unknown , Just guess it is `Items` + FragmentKind::Items + } + } +} diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 0a5da7e547..94e1e466a5 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -117,14 +117,6 @@ impl HirFileId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroFile { macro_call_id: MacroCallId, - macro_file_kind: MacroFileKind, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum MacroFileKind { - Items, - Expr, - Statements, } /// `MacroCallId` identifies a particular macro invocation, like @@ -205,9 +197,8 @@ impl MacroCallKind { } impl MacroCallId { - pub fn as_file(self, kind: MacroFileKind) -> HirFileId { - let macro_file = MacroFile { macro_call_id: self, macro_file_kind: kind }; - macro_file.into() + pub fn as_file(self) -> HirFileId { + MacroFile { macro_call_id: self }.into() } } From 08d3166c8b23b5a342f32e088f7e0d6e032ec17b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:01:45 +0100 Subject: [PATCH 094/312] Cleanup Crate API --- crates/ra_hir/src/code_model.rs | 48 +++++++++++++------- crates/ra_hir/src/debug.rs | 4 +- crates/ra_hir/src/from_id.rs | 4 +- crates/ra_hir/src/from_source.rs | 2 +- crates/ra_ide/src/references/search_scope.rs | 16 +++---- 5 files changed, 42 insertions(+), 32 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 4578a0ba8e..3695115e42 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -25,7 +25,7 @@ use hir_expand::{ MacroDefId, }; use hir_ty::expr::ExprValidator; -use ra_db::{CrateId, Edition}; +use ra_db::{CrateId, Edition, FileId}; use ra_syntax::ast; use crate::{ @@ -40,7 +40,7 @@ use crate::{ /// root module. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Crate { - pub(crate) crate_id: CrateId, + pub(crate) id: CrateId, } #[derive(Debug)] @@ -50,33 +50,47 @@ pub struct CrateDependency { } impl Crate { - pub fn crate_id(self) -> CrateId { - self.crate_id - } - pub fn dependencies(self, db: &impl DefDatabase) -> Vec { db.crate_graph() - .dependencies(self.crate_id) + .dependencies(self.id) .map(|dep| { - let krate = Crate { crate_id: dep.crate_id() }; + let krate = Crate { id: dep.crate_id() }; let name = dep.as_name(); CrateDependency { krate, name } }) .collect() } + // FIXME: add `transitive_reverse_dependencies`. + pub fn reverse_dependencies(self, db: &impl DefDatabase) -> Vec { + let crate_graph = db.crate_graph(); + crate_graph + .iter() + .filter(|&krate| crate_graph.dependencies(krate).any(|it| it.crate_id == self.id)) + .map(|id| Crate { id }) + .collect() + } + pub fn root_module(self, db: &impl DefDatabase) -> Option { - let module_id = db.crate_def_map(self.crate_id).root; + let module_id = db.crate_def_map(self.id).root; Some(Module::new(self, module_id)) } + pub fn root_file(self, db: &impl DefDatabase) -> FileId { + db.crate_graph().crate_root(self.id) + } + pub fn edition(self, db: &impl DefDatabase) -> Edition { let crate_graph = db.crate_graph(); - crate_graph.edition(self.crate_id) + crate_graph.edition(self.id) } pub fn all(db: &impl DefDatabase) -> Vec { - db.crate_graph().iter().map(|crate_id| Crate { crate_id }).collect() + db.crate_graph().iter().map(|id| Crate { id }).collect() + } + + pub fn crate_id(self) -> CrateId { + self.id } } @@ -115,7 +129,7 @@ pub use hir_def::attr::Attrs; impl Module { pub(crate) fn new(krate: Crate, crate_module_id: LocalModuleId) -> Module { - Module { id: ModuleId { krate: krate.crate_id, local_id: crate_module_id } } + Module { id: ModuleId { krate: krate.id, local_id: crate_module_id } } } /// Name of this module. @@ -133,7 +147,7 @@ impl Module { /// Returns the crate this module is part of. pub fn krate(self) -> Crate { - Crate { crate_id: self.id.krate } + Crate { id: self.id.krate } } /// Topmost parent of this module. Every module has a `crate_root`, but some @@ -878,11 +892,11 @@ pub struct ImplBlock { impl ImplBlock { pub fn all_in_crate(db: &impl HirDatabase, krate: Crate) -> Vec { - let impls = db.impls_in_crate(krate.crate_id); + let impls = db.impls_in_crate(krate.id); impls.all_impls().map(Self::from).collect() } pub fn for_trait(db: &impl HirDatabase, krate: Crate, trait_: Trait) -> Vec { - let impls = db.impls_in_crate(krate.crate_id); + let impls = db.impls_in_crate(krate.id); impls.lookup_impl_blocks_for_trait(trait_.id).map(Self::from).collect() } @@ -915,7 +929,7 @@ impl ImplBlock { } pub fn krate(&self, db: &impl DefDatabase) -> Crate { - Crate { crate_id: self.module(db).id.krate } + Crate { id: self.module(db).id.krate } } } @@ -1053,7 +1067,7 @@ impl Type { krate: Crate, mut callback: impl FnMut(AssocItem) -> Option, ) -> Option { - for krate in self.ty.value.def_crates(db, krate.crate_id)? { + for krate in self.ty.value.def_crates(db, krate.id)? { let impls = db.impls_in_crate(krate); for impl_block in impls.lookup_impl_blocks(&self.ty.value) { diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs index 7a2810f71a..6cd5c8cb97 100644 --- a/crates/ra_hir/src/debug.rs +++ b/crates/ra_hir/src/debug.rs @@ -57,9 +57,9 @@ pub trait HirDebugDatabase { impl HirDebugDatabase for DB { fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut builder = fmt.debug_tuple("Crate"); - match self.crate_name(krate.crate_id) { + match self.crate_name(krate.id) { Some(name) => builder.field(&name), - None => builder.field(&krate.crate_id), + None => builder.field(&krate.id), } .finish() } diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index e96a18d12a..0398d0ee6b 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -14,8 +14,8 @@ use crate::{ }; impl From for Crate { - fn from(crate_id: ra_db::CrateId) -> Self { - Crate { crate_id } + fn from(id: ra_db::CrateId) -> Self { + Crate { id } } } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 4acc038e45..071ca2e5a9 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -95,7 +95,7 @@ impl FromSource for MacroDef { let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; - let krate = Some(module.krate().crate_id()); + let krate = Some(module.krate().id); let ast_id = Some(AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value))); diff --git a/crates/ra_ide/src/references/search_scope.rs b/crates/ra_ide/src/references/search_scope.rs index f5c9589f4d..241dd358f9 100644 --- a/crates/ra_ide/src/references/search_scope.rs +++ b/crates/ra_ide/src/references/search_scope.rs @@ -5,7 +5,7 @@ use std::mem; use hir::{DefWithBody, HasSource, ModuleSource}; -use ra_db::{FileId, SourceDatabase, SourceDatabaseExt}; +use ra_db::{FileId, SourceDatabaseExt}; use ra_prof::profile; use ra_syntax::{AstNode, TextRange}; use rustc_hash::FxHashMap; @@ -120,15 +120,11 @@ impl NameDefinition { } if vis.as_str() == "pub" { let krate = self.container.krate(); - let crate_graph = db.crate_graph(); - for crate_id in crate_graph.iter() { - let mut crate_deps = crate_graph.dependencies(crate_id); - if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) { - let root_file = crate_graph.crate_root(crate_id); - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); - res.extend(source_root.walk().map(|id| (id, None))); - } + for rev_dep in krate.reverse_dependencies(db) { + let root_file = rev_dep.root_file(db); + let source_root_id = db.file_source_root(root_file); + let source_root = db.source_root(source_root_id); + res.extend(source_root.walk().map(|id| (id, None))); } return SearchScope::new(res); } From 200bda3daf66f338e9bb1d833146f06fb81f829e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:16:57 +0100 Subject: [PATCH 095/312] Cleanup Field ty --- crates/ra_hir/src/code_model.rs | 31 +++++++++++++++-------- crates/ra_hir_def/src/resolver.rs | 42 +++++++++++++++++++------------ 2 files changed, 47 insertions(+), 26 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3695115e42..e854b22bf7 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -265,8 +265,10 @@ impl StructField { self.parent.variant_data(db).fields()[self.id].name.clone() } - pub fn ty(&self, db: &impl HirDatabase) -> Ty { - db.field_types(self.parent.into())[self.id].clone() + pub fn ty(&self, db: &impl HirDatabase) -> Type { + let var_id = self.parent.into(); + let ty = db.field_types(var_id)[self.id].clone(); + Type::new(db, self.parent.module(db).id.krate.into(), var_id, ty) } pub fn parent_def(&self, _db: &impl HirDatabase) -> VariantDef { @@ -940,15 +942,19 @@ pub struct Type { } impl Type { + fn new(db: &impl HirDatabase, krate: CrateId, lexical_env: impl HasResolver, ty: Ty) -> Type { + let resolver = lexical_env.resolver(db); + let environment = TraitEnvironment::lower(db, &resolver); + Type { krate, ty: InEnvironment { value: ty, environment } } + } + fn from_def( db: &impl HirDatabase, krate: CrateId, def: impl HasResolver + Into, ) -> Type { - let resolver = def.resolver(db); - let environment = TraitEnvironment::lower(db, &resolver); let ty = db.ty(def.into()); - Type { krate, ty: InEnvironment { value: ty, environment } } + Type::new(db, krate, def, ty) } pub fn is_bool(&self) -> bool { @@ -1039,11 +1045,16 @@ impl Type { ) -> Vec<(StructField, Type)> { // FIXME: check that ty and def match match &self.ty.value { - Ty::Apply(a_ty) => def - .fields(db) - .into_iter() - .map(|it| (it, self.derived(it.ty(db).subst(&a_ty.parameters)))) - .collect(), + Ty::Apply(a_ty) => { + let field_types = db.field_types(def.into()); + def.fields(db) + .into_iter() + .map(|it| { + let ty = field_types[it.id].clone().subst(&a_ty.parameters); + (it, self.derived(ty)) + }) + .collect() + } _ => Vec::new(), } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 4c859e497f..9484a61d53 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -19,7 +19,7 @@ use crate::{ per_ns::PerNs, AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, TypeParamId, + StructId, TraitId, TypeAliasId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -544,16 +544,6 @@ impl HasResolver for FunctionId { } } -impl HasResolver for DefWithBodyId { - fn resolver(self, db: &impl DefDatabase) -> Resolver { - match self { - DefWithBodyId::ConstId(c) => c.resolver(db), - DefWithBodyId::FunctionId(f) => f.resolver(db), - DefWithBodyId::StaticId(s) => s.resolver(db), - } - } -} - impl HasResolver for ConstId { fn resolver(self, db: &impl DefDatabase) -> Resolver { self.lookup(db).container.resolver(db) @@ -572,6 +562,25 @@ impl HasResolver for TypeAliasId { } } +impl HasResolver for ImplId { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + self.module(db) + .resolver(db) + .push_generic_params_scope(db, self.into()) + .push_impl_block_scope(self) + } +} + +impl HasResolver for DefWithBodyId { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + match self { + DefWithBodyId::ConstId(c) => c.resolver(db), + DefWithBodyId::FunctionId(f) => f.resolver(db), + DefWithBodyId::StaticId(s) => s.resolver(db), + } + } +} + impl HasResolver for ContainerId { fn resolver(self, db: &impl DefDatabase) -> Resolver { match self { @@ -596,11 +605,12 @@ impl HasResolver for GenericDefId { } } -impl HasResolver for ImplId { +impl HasResolver for VariantId { fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db) - .resolver(db) - .push_generic_params_scope(db, self.into()) - .push_impl_block_scope(self) + match self { + VariantId::EnumVariantId(it) => it.parent.resolver(db), + VariantId::StructId(it) => it.resolver(db), + VariantId::UnionId(it) => it.resolver(db), + } } } From 7aacf9a19739f53a45840df2d08b5f3cca761192 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:20:59 +0100 Subject: [PATCH 096/312] Drop some unused methods --- crates/ra_hir/src/code_model.rs | 48 +------------------------------- crates/ra_hir/src/from_source.rs | 6 ++-- 2 files changed, 5 insertions(+), 49 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e854b22bf7..9cbea024a7 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -158,13 +158,6 @@ impl Module { self.with_module_id(def_map.root) } - /// Finds a child module with the specified name. - pub fn child(self, db: &impl DefDatabase, name: &Name) -> Option { - let def_map = db.crate_def_map(self.id.krate); - let child_id = def_map[self.id.local_id].children.get(name)?; - Some(self.with_module_id(*child_id)) - } - /// Iterates over all child modules. pub fn children(self, db: &impl DefDatabase) -> impl Iterator { let def_map = db.crate_def_map(self.id.krate); @@ -238,7 +231,7 @@ impl Module { def_map[self.id.local_id].impls.iter().copied().map(ImplBlock::from).collect() } - fn with_module_id(self, module_id: LocalModuleId) -> Module { + pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { Module::new(self.krate(), module_id) } } @@ -303,23 +296,10 @@ impl Struct { .collect() } - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { - db.struct_data(self.id.into()) - .variant_data - .fields() - .iter() - .find(|(_id, data)| data.name == *name) - .map(|(id, _)| StructField { parent: self.into(), id }) - } - pub fn ty(self, db: &impl HirDatabase) -> Type { Type::from_def(db, self.id.module(db).krate, self.id) } - pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { - db.value_ty(self.id.into()) - } - fn variant_data(self, db: &impl DefDatabase) -> Arc { db.struct_data(self.id.into()).variant_data.clone() } @@ -352,15 +332,6 @@ impl Union { .collect() } - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { - db.union_data(self.id) - .variant_data - .fields() - .iter() - .find(|(_id, data)| data.name == *name) - .map(|(id, _)| StructField { parent: self.into(), id }) - } - fn variant_data(self, db: &impl DefDatabase) -> Arc { db.union_data(self.id).variant_data.clone() } @@ -392,11 +363,6 @@ impl Enum { .collect() } - pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option { - let id = db.enum_data(self.id).variant(name)?; - Some(EnumVariant { parent: self, id }) - } - pub fn ty(self, db: &impl HirDatabase) -> Type { Type::from_def(db, self.id.module(db).krate, self.id) } @@ -428,14 +394,6 @@ impl EnumVariant { .collect() } - pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option { - self.variant_data(db) - .fields() - .iter() - .find(|(_id, data)| data.name == *name) - .map(|(id, _)| StructField { parent: self.into(), id }) - } - pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc { db.enum_data(self.parent.id).variants[self.id].variant_data.clone() } @@ -561,10 +519,6 @@ impl Function { db.body(self.id.into()) } - pub fn ty(self, db: &impl HirDatabase) -> Ty { - db.value_ty(self.id.into()) - } - pub fn infer(self, db: &impl HirDatabase) -> Arc { db.infer(self.id.into()) } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 071ca2e5a9..307f3d5bff 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -216,8 +216,10 @@ impl Module { } }?; - let child_name = src.value.name()?; - parent_module.child(db, &child_name.as_name()) + let child_name = src.value.name()?.as_name(); + let def_map = db.crate_def_map(parent_module.id.krate); + let child_id = def_map[parent_module.id.local_id].children.get(&child_name)?; + Some(parent_module.with_module_id(*child_id)) } pub fn from_definition(db: &impl DefDatabase, src: InFile) -> Option { From b017bae8370e166034ac569c357b662358d45f19 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:26:53 +0100 Subject: [PATCH 097/312] remove `infer` method from CodeModel --- crates/ra_hir/src/code_model.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9cbea024a7..0100ac91c0 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -31,7 +31,7 @@ use ra_syntax::ast; use crate::{ db::{DefDatabase, HirDatabase}, ty::display::HirFormatter, - ty::{self, InEnvironment, InferenceResult, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk}, + ty::{self, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk}, CallableDef, HirDisplay, InFile, Name, }; @@ -519,10 +519,6 @@ impl Function { db.body(self.id.into()) } - pub fn infer(self, db: &impl HirDatabase) -> Arc { - db.infer(self.id.into()) - } - /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { match self.container(db) { @@ -548,7 +544,7 @@ impl Function { } pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { - let infer = self.infer(db); + let infer = db.infer(self.id.into()); infer.add_diagnostics(db, self.id, sink); let mut validator = ExprValidator::new(self.id, infer, sink); validator.validate_body(db); @@ -573,10 +569,6 @@ impl Const { db.const_data(self.id).name.clone() } - pub fn infer(self, db: &impl HirDatabase) -> Arc { - db.infer(self.id.into()) - } - /// The containing impl block, if this is a type alias. pub fn impl_block(self, db: &impl DefDatabase) -> Option { match self.container(db) { @@ -615,10 +607,6 @@ impl Static { pub fn krate(self, db: &impl DefDatabase) -> Option { Some(self.module(db).krate()) } - - pub fn infer(self, db: &impl HirDatabase) -> Arc { - db.infer(self.id.into()) - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From b77d7c24aa929e53a2bc2a0ffa319de9bf1ab1fa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:27:21 +0100 Subject: [PATCH 098/312] Remove bodies from code_model --- crates/ra_hir/src/code_model.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 0100ac91c0..906716dfce 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -7,7 +7,6 @@ use std::sync::Arc; use either::Either; use hir_def::{ adt::VariantData, - body::{Body, BodySourceMap}, builtin_type::BuiltinType, docs::Documentation, expr::{BindingAnnotation, Pat, PatId}, @@ -511,14 +510,6 @@ impl Function { db.function_data(self.id).params.clone() } - pub fn body_source_map(self, db: &impl HirDatabase) -> Arc { - db.body_with_source_map(self.id.into()).1 - } - - pub fn body(self, db: &impl HirDatabase) -> Arc { - db.body(self.id.into()) - } - /// The containing impl block, if this is a method. pub fn impl_block(self, db: &impl DefDatabase) -> Option { match self.container(db) { From b37c6a746b6c7cf85dc1ec6e40ac41455b8f2ec0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:44:14 +0100 Subject: [PATCH 099/312] Remove ty from code_model --- Cargo.lock | 2 ++ crates/ra_cli/Cargo.toml | 4 +++- crates/ra_cli/src/analysis_stats.rs | 15 ++++++++---- crates/ra_hir/src/code_model.rs | 36 +++++++++++++---------------- crates/ra_hir/src/from_id.rs | 14 +++++------ crates/ra_hir/src/lib.rs | 7 +----- crates/ra_hir/src/source_binder.rs | 24 +++++++++---------- crates/ra_hir/src/ty.rs | 4 ---- crates/ra_ide/src/parent_module.rs | 2 +- 9 files changed, 53 insertions(+), 55 deletions(-) delete mode 100644 crates/ra_hir/src/ty.rs diff --git a/Cargo.lock b/Cargo.lock index a95f9139f1..d80e585482 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -919,6 +919,8 @@ dependencies = [ "ra_batch 0.1.0", "ra_db 0.1.0", "ra_hir 0.1.0", + "ra_hir_def 0.1.0", + "ra_hir_ty 0.1.0", "ra_ide 0.1.0", "ra_prof 0.1.0", "ra_syntax 0.1.0", diff --git a/crates/ra_cli/Cargo.toml b/crates/ra_cli/Cargo.toml index 21a37c7bf4..12af075f7d 100644 --- a/crates/ra_cli/Cargo.toml +++ b/crates/ra_cli/Cargo.toml @@ -12,7 +12,9 @@ env_logger = { version = "0.7.1", default-features = false, features = ["humanti ra_syntax = { path = "../ra_syntax" } ra_ide = { path = "../ra_ide" } ra_batch = { path = "../ra_batch" } -ra_hir = { path = "../ra_hir" } +hir = { path = "../ra_hir", package = "ra_hir" } +hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } +hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } ra_db = { path = "../ra_db" } [dependencies.ra_prof] diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs index 9b1802a5fc..ac65415a5e 100644 --- a/crates/ra_cli/src/analysis_stats.rs +++ b/crates/ra_cli/src/analysis_stats.rs @@ -2,8 +2,13 @@ use std::{collections::HashSet, fmt::Write, path::Path, time::Instant}; +use hir::{ + db::{DefDatabase, HirDatabase}, + AssocItem, Crate, HasSource, HirDisplay, ModuleDef, +}; +use hir_def::FunctionId; +use hir_ty::{Ty, TypeWalk}; use ra_db::SourceDatabaseExt; -use ra_hir::{AssocItem, Crate, HasSource, HirDisplay, ModuleDef, Ty, TypeWalk}; use ra_syntax::AstNode; use crate::{progress_report::ProgressReport, Result, Verbosity}; @@ -101,8 +106,9 @@ pub fn run( continue; } } - let body = f.body(db); - let inference_result = f.infer(db); + let f_id = FunctionId::from(f); + let body = db.body(f_id.into()); + let inference_result = db.infer(f_id.into()); for (expr_id, _) in body.exprs.iter() { let ty = &inference_result[expr_id]; num_exprs += 1; @@ -122,7 +128,8 @@ pub fn run( if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr_id) { num_type_mismatches += 1; if verbosity.is_verbose() { - let src = f.body_source_map(db).expr_syntax(expr_id); + let (_, sm) = db.body_with_source_map(f_id.into()); + let src = sm.expr_syntax(expr_id); if let Some(src) = src { // FIXME: it might be nice to have a function (on Analysis?) that goes from Source -> (LineCol, LineCol) directly let original_file = src.file_id.original_file(db); diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 906716dfce..3d956afa74 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -23,14 +23,15 @@ use hir_expand::{ name::{self, AsName}, MacroDefId, }; -use hir_ty::expr::ExprValidator; +use hir_ty::{ + autoderef, display::HirFormatter, expr::ExprValidator, ApplicationTy, Canonical, InEnvironment, + TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, +}; use ra_db::{CrateId, Edition, FileId}; use ra_syntax::ast; use crate::{ db::{DefDatabase, HirDatabase}, - ty::display::HirFormatter, - ty::{self, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk}, CallableDef, HirDisplay, InFile, Name, }; @@ -87,10 +88,6 @@ impl Crate { pub fn all(db: &impl DefDatabase) -> Vec { db.crate_graph().iter().map(|id| Crate { id }).collect() } - - pub fn crate_id(self) -> CrateId { - self.id - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -937,7 +934,7 @@ impl Type { pub fn fields(&self, db: &impl HirDatabase) -> Vec<(StructField, Type)> { if let Ty::Apply(a_ty) = &self.ty.value { match a_ty.ctor { - ty::TypeCtor::Adt(AdtId::StructId(s)) => { + TypeCtor::Adt(AdtId::StructId(s)) => { let var_def = s.into(); return db .field_types(var_def) @@ -959,7 +956,7 @@ impl Type { let mut res = Vec::new(); if let Ty::Apply(a_ty) = &self.ty.value { match a_ty.ctor { - ty::TypeCtor::Tuple { .. } => { + TypeCtor::Tuple { .. } => { for ty in a_ty.parameters.iter() { let ty = ty.clone().subst(&a_ty.parameters); res.push(self.derived(ty)); @@ -995,10 +992,10 @@ impl Type { pub fn autoderef<'a>(&'a self, db: &'a impl HirDatabase) -> impl Iterator + 'a { // There should be no inference vars in types passed here // FIXME check that? - let canonical = crate::ty::Canonical { value: self.ty.value.clone(), num_vars: 0 }; + let canonical = Canonical { value: self.ty.value.clone(), num_vars: 0 }; let environment = self.ty.environment.clone(); let ty = InEnvironment { value: canonical, environment: environment.clone() }; - ty::autoderef(db, Some(self.krate), ty) + autoderef(db, Some(self.krate), ty) .map(|canonical| canonical.value) .map(move |ty| self.derived(ty)) } @@ -1038,15 +1035,14 @@ impl Type { // FIXME: provide required accessors such that it becomes implementable from outside. pub fn is_equal_for_find_impls(&self, other: &Type) -> bool { match (&self.ty.value, &other.ty.value) { - (Ty::Apply(a_original_ty), Ty::Apply(ty::ApplicationTy { ctor, parameters })) => { - match ctor { - TypeCtor::Ref(..) => match parameters.as_single() { - Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor, - _ => false, - }, - _ => a_original_ty.ctor == *ctor, - } - } + (Ty::Apply(a_original_ty), Ty::Apply(ApplicationTy { ctor, parameters })) => match ctor + { + TypeCtor::Ref(..) => match parameters.as_single() { + Ty::Apply(a_ty) => a_original_ty.ctor == a_ty.ctor, + _ => false, + }, + _ => a_original_ty.ctor == *ctor, + }, _ => false, } } diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 0398d0ee6b..75a1a77722 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -9,16 +9,10 @@ use hir_def::{ }; use crate::{ - Adt, AssocItem, AttrDef, Crate, DefWithBody, EnumVariant, GenericDef, ModuleDef, StructField, + Adt, AssocItem, AttrDef, DefWithBody, EnumVariant, GenericDef, ModuleDef, StructField, VariantDef, }; -impl From for Crate { - fn from(id: ra_db::CrateId) -> Self { - Crate { id } - } -} - macro_rules! from_id { ($(($id:path, $ty:path)),*) => {$( impl From<$id> for $ty { @@ -26,10 +20,16 @@ macro_rules! from_id { $ty { id } } } + impl From<$ty> for $id { + fn from(ty: $ty) -> $id { + ty.id + } + } )*} } from_id![ + (ra_db::CrateId, crate::Crate), (hir_def::ModuleId, crate::Module), (hir_def::StructId, crate::Struct), (hir_def::UnionId, crate::Union), diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 9eb34b5dcd..bb22882b13 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -31,7 +31,6 @@ pub mod debug; pub mod db; pub mod source_binder; -mod ty; pub mod diagnostics; mod from_id; @@ -48,11 +47,6 @@ pub use crate::{ }, from_source::FromSource, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, - ty::{ - display::HirDisplay, - primitive::{FloatBitness, FloatTy, IntBitness, IntTy, Signedness, Uncertain}, - ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, - }, }; pub use hir_def::{ @@ -66,3 +60,4 @@ pub use hir_def::{ pub use hir_expand::{ name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, }; +pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c5a920688f..9efd0477c1 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -22,6 +22,10 @@ use hir_def::{ use hir_expand::{ hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, }; +use hir_ty::{ + method_resolution::{self, implements_trait}, + Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty, +}; use ra_syntax::{ ast::{self, AstNode}, match_ast, AstPtr, @@ -30,13 +34,9 @@ use ra_syntax::{ }; use crate::{ - db::HirDatabase, - ty::{ - method_resolution::{self, implements_trait}, - InEnvironment, TraitEnvironment, Ty, - }, - Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, ImplBlock, Local, - MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, + db::HirDatabase, Adt, AssocItem, Const, DefWithBody, Enum, EnumVariant, FromSource, Function, + ImplBlock, Local, MacroDef, Name, Path, ScopeDef, Static, Struct, Trait, Type, TypeAlias, + TypeParam, }; fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option { @@ -100,7 +100,7 @@ pub struct SourceAnalyzer { resolver: Resolver, body_owner: Option, body_source_map: Option>, - infer: Option>, + infer: Option>, scopes: Option>, } @@ -376,7 +376,7 @@ impl SourceAnalyzer { // There should be no inference vars in types passed here // FIXME check that? // FIXME replace Unknown by bound vars here - let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; + let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 }; method_resolution::iterate_method_candidates( &canonical, db, @@ -400,7 +400,7 @@ impl SourceAnalyzer { // There should be no inference vars in types passed here // FIXME check that? // FIXME replace Unknown by bound vars here - let canonical = crate::ty::Canonical { value: ty.ty.value.clone(), num_vars: 0 }; + let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 }; method_resolution::iterate_method_candidates( &canonical, db, @@ -418,7 +418,7 @@ impl SourceAnalyzer { // ) -> impl Iterator + 'a { // // There should be no inference vars in types passed here // // FIXME check that? - // let canonical = crate::ty::Canonical { value: ty, num_vars: 0 }; + // let canonical = Canonical { value: ty, num_vars: 0 }; // let krate = self.resolver.krate(); // let environment = TraitEnvironment::lower(db, &self.resolver); // let ty = crate::ty::InEnvironment { value: canonical, environment }; @@ -440,7 +440,7 @@ impl SourceAnalyzer { _ => return false, }; - let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; + let canonical_ty = Canonical { value: ty, num_vars: 0 }; implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) } diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs deleted file mode 100644 index 4ed69c00dc..0000000000 --- a/crates/ra_hir/src/ty.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! The type system. We currently use this to infer types for completion, hover -//! information and various assists. - -pub use hir_ty::*; diff --git a/crates/ra_ide/src/parent_module.rs b/crates/ra_ide/src/parent_module.rs index aef3fa3df0..f5a788c07c 100644 --- a/crates/ra_ide/src/parent_module.rs +++ b/crates/ra_ide/src/parent_module.rs @@ -30,7 +30,7 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec { None => return Vec::new(), }; let krate = module.krate(); - vec![krate.crate_id()] + vec![krate.into()] } #[cfg(test)] From e2cc55207619f987fd5cc274628b8e49e15ec856 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:51:25 +0100 Subject: [PATCH 100/312] Remove dead code --- crates/ra_hir/src/code_model.rs | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3d956afa74..7ac1bf461a 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -507,30 +507,6 @@ impl Function { db.function_data(self.id).params.clone() } - /// The containing impl block, if this is a method. - pub fn impl_block(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::ImplBlock(it)) => Some(it), - _ => None, - } - } - - /// The containing trait, if this is a trait method definition. - pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::Trait(it)) => Some(it), - _ => None, - } - } - - pub fn container(self, db: &impl DefDatabase) -> Option { - match self.id.lookup(db).container { - ContainerId::TraitId(it) => Some(Container::Trait(it.into())), - ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - ContainerId::ModuleId(_) => None, - } - } - pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { let infer = db.infer(self.id.into()); infer.add_diagnostics(db, self.id, sink); @@ -709,15 +685,6 @@ impl AssocItem { AssocItem::TypeAlias(t) => t.module(db), } } - - pub fn container(self, db: &impl DefDatabase) -> Container { - match self { - AssocItem::Function(f) => f.container(db), - AssocItem::Const(c) => c.container(db), - AssocItem::TypeAlias(t) => t.container(db), - } - .expect("AssocItem without container") - } } #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] From 91f28e43a2686d0ac06f73b5fed11351aad428a9 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 8 Dec 2019 09:26:17 +0100 Subject: [PATCH 101/312] Fix expansion of format_args --- crates/ra_hir_expand/src/builtin_macro.rs | 19 +++++++++++++------ crates/ra_ide/src/goto_definition.rs | 1 - 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index c7071fe85a..ec5ace757c 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -208,15 +208,20 @@ fn format_args_expand( _id: MacroCallId, tt: &tt::Subtree, ) -> Result { - // We expand `format_args!("", arg1, arg2)` to - // `std::fmt::Arguments::new_v1(&[], &[&arg1, &arg2])`, + // We expand `format_args!("", a1, a2)` to + // ``` + // std::fmt::Arguments::new_v1(&[], &[ + // std::fmt::ArgumentV1::new(&arg1,std::fmt::Display::fmt), + // std::fmt::ArgumentV1::new(&arg2,std::fmt::Display::fmt), + // ]) + // ```, // which is still not really correct, but close enough for now let mut args = Vec::new(); let mut current = Vec::new(); for tt in tt.token_trees.iter().cloned() { match tt { tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { - args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + args.push(current); current = Vec::new(); } _ => { @@ -225,13 +230,15 @@ fn format_args_expand( } } if !current.is_empty() { - args.push(tt::Subtree { delimiter: tt::Delimiter::None, token_trees: current }); + args.push(current); } if args.is_empty() { return Err(mbe::ExpandError::NoMatchingRule); } let _format_string = args.remove(0); - let arg_tts = args.into_iter().flat_map(|arg| (quote! { & #arg , }).token_trees); + let arg_tts = args.into_iter().flat_map(|arg| { + quote! { std::fmt::ArgumentV1::new(&(##arg), std::fmt::Display::fmt), } + }.token_trees).collect::>(); let expanded = quote! { std::fmt::Arguments::new_v1(&[], &[##arg_tts]) }; @@ -360,6 +367,6 @@ mod tests { BuiltinFnLikeExpander::FormatArgs, ); - assert_eq!(expanded, r#"std::fmt::Arguments::new_v1(&[] ,&[&arg1(a,b,c),&arg2,])"#); + assert_eq!(expanded, r#"std::fmt::Arguments::new_v1(&[] ,&[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#); } } diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 1b968134d6..077b0beda6 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -693,7 +693,6 @@ mod tests { ); } - #[should_panic] // currently failing because of expr mapping problems #[test] fn goto_through_format() { check_goto( From 2223620313e94deb04d1565a75004579aa1a9e07 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 8 Dec 2019 11:22:39 +0100 Subject: [PATCH 102/312] Fix range in goto_through_format test --- crates/ra_ide/src/goto_definition.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 077b0beda6..b93d6a931a 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -717,7 +717,7 @@ mod tests { format!(\"{}\", fo<|>o()) } ", - "foo FN_DEF FileId(1) [359; 376) [362; 365)", + "foo FN_DEF FileId(1) [398; 415) [401; 404)", ); } From 5e096def15e992938b0e2838ae6c344939aa10f2 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 8 Dec 2019 12:50:49 +0100 Subject: [PATCH 103/312] Expand macros in blocks to expressions for now Expanding to statements isn't handled properly yet and breaks things. --- crates/ra_hir_def/src/body/lower.rs | 7 ++++--- crates/ra_hir_expand/src/db.rs | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 71c08f0247..cc068ff94f 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -437,9 +437,7 @@ where None => self.alloc_expr(Expr::Missing, syntax_ptr), } } - - // FIXME implement HIR for these: - ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), + // FIXME expand to statements in statement position ast::Expr::MacroCall(e) => match self.expander.enter_expand(self.db, e) { Some((mark, expansion)) => { let id = self.collect_expr(expansion); @@ -448,6 +446,9 @@ where } None => self.alloc_expr(Expr::Missing, syntax_ptr), }, + + // FIXME implement HIR for these: + ast::Expr::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), } } diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 4bdb41619c..f68aca7898 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -183,8 +183,8 @@ fn to_fragment_kind(db: &dyn AstDatabase, macro_call_id: MacroCallId) -> Fragmen // FIXME: Handle Pattern FragmentKind::Expr } - EXPR_STMT => FragmentKind::Statements, - BLOCK => FragmentKind::Statements, + // FIXME: Expand to statements in appropriate positions; HIR lowering needs to handle that + EXPR_STMT | BLOCK => FragmentKind::Expr, ARG_LIST => FragmentKind::Expr, TRY_EXPR => FragmentKind::Expr, TUPLE_EXPR => FragmentKind::Expr, From d0c9bb0abf764a3143fc0d13297d73184bc10397 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 8 Dec 2019 11:23:05 +0100 Subject: [PATCH 104/312] Fix coercion from &Foo to an inference variable in a reference We didn't try to unify within the reference, but we should. --- crates/ra_hir_ty/src/infer/coerce.rs | 6 ++++- crates/ra_hir_ty/src/tests/coercion.rs | 37 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 9daa77cfa9..0f4dac45ed 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -332,7 +332,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // It will not recurse to `coerce`. return self.table.unify_substs(st1, st2, 0); } - _ => {} + _ => { + if self.table.unify_inner_trivial(&derefed_ty, &to_ty) { + return true; + } + } } } diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 58b22396fc..ac9e3872a5 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs @@ -403,3 +403,40 @@ fn test() { "### ); } + +#[test] +fn coerce_autoderef_generic() { + assert_snapshot!( + infer_with_mismatches(r#" +struct Foo; +fn takes_ref(x: &T) -> T { *x } +fn test() { + takes_ref(&Foo); + takes_ref(&&Foo); + takes_ref(&&&Foo); +} +"#, true), + @r###" + [29; 30) 'x': &T + [41; 47) '{ *x }': T + [43; 45) '*x': T + [44; 45) 'x': &T + [58; 127) '{ ...oo); }': () + [64; 73) 'takes_ref': fn takes_ref(&T) -> T + [64; 79) 'takes_ref(&Foo)': Foo + [74; 78) '&Foo': &Foo + [75; 78) 'Foo': Foo + [85; 94) 'takes_ref': fn takes_ref<&Foo>(&T) -> T + [85; 101) 'takes_...&&Foo)': &Foo + [95; 100) '&&Foo': &&Foo + [96; 100) '&Foo': &Foo + [97; 100) 'Foo': Foo + [107; 116) 'takes_ref': fn takes_ref<&&Foo>(&T) -> T + [107; 124) 'takes_...&&Foo)': &&Foo + [117; 123) '&&&Foo': &&&Foo + [118; 123) '&&Foo': &&Foo + [119; 123) '&Foo': &Foo + [120; 123) 'Foo': Foo + "### + ); +} From 3a95d01d0cbc5ac2d789b3c70f4472a609fc5af4 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 8 Dec 2019 20:33:42 +0800 Subject: [PATCH 105/312] Delay legacy macro expansion --- crates/ra_hir_def/src/nameres/collector.rs | 206 ++++++--------------- 1 file changed, 57 insertions(+), 149 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 3ff071f9ee..a80067979f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -12,7 +12,7 @@ use hir_expand::{ use ra_cfg::CfgOptions; use ra_db::{CrateId, FileId}; use ra_syntax::ast; -use rustc_hash::{FxHashMap, FxHashSet}; +use rustc_hash::FxHashMap; use test_utils::tested_by; use crate::{ @@ -63,42 +63,12 @@ pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> C unexpanded_macros: Vec::new(), unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), - macro_stack_monitor: MacroStackMonitor::default(), - poison_macros: FxHashSet::default(), cfg_options, }; collector.collect(); collector.finish() } -#[derive(Default)] -struct MacroStackMonitor { - counts: FxHashMap, - - /// Mainly use for test - validator: Option bool>>, -} - -impl MacroStackMonitor { - fn increase(&mut self, macro_def_id: MacroDefId) { - *self.counts.entry(macro_def_id).or_default() += 1; - } - - fn decrease(&mut self, macro_def_id: MacroDefId) { - *self.counts.entry(macro_def_id).or_default() -= 1; - } - - fn is_poison(&self, macro_def_id: MacroDefId) -> bool { - let cur = *self.counts.get(¯o_def_id).unwrap_or(&0); - - if let Some(validator) = &self.validator { - validator(cur) - } else { - cur > 100 - } - } -} - #[derive(Copy, Clone, Debug, Eq, PartialEq)] enum PartialResolvedImport { /// None of any namespaces is resolved @@ -127,6 +97,14 @@ struct ImportDirective { status: PartialResolvedImport, } +#[derive(Clone, Debug, Eq, PartialEq)] +struct MacroDirective { + module_id: LocalModuleId, + ast_id: AstId, + path: Path, + legacy: Option, +} + /// Walks the tree of module recursively struct DefCollector<'a, DB> { db: &'a DB, @@ -134,25 +112,9 @@ struct DefCollector<'a, DB> { glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, - unexpanded_macros: Vec<(LocalModuleId, AstId, Path)>, + unexpanded_macros: Vec, unexpanded_attribute_macros: Vec<(LocalModuleId, AstId, Path)>, mod_dirs: FxHashMap, - - /// Some macro use `$tt:tt which mean we have to handle the macro perfectly - /// To prevent stack overflow, we add a deep counter here for prevent that. - macro_stack_monitor: MacroStackMonitor, - /// Some macros are not well-behavior, which leads to infinite loop - /// e.g. macro_rules! foo { ($ty:ty) => { foo!($ty); } } - /// We mark it down and skip it in collector - /// - /// FIXME: - /// Right now it only handle a poison macro in a single crate, - /// such that if other crate try to call that macro, - /// the whole process will do again until it became poisoned in that crate. - /// We should handle this macro set globally - /// However, do we want to put it as a global variable? - poison_macros: FxHashSet, - cfg_options: &'a CfgOptions, } @@ -556,18 +518,24 @@ where std::mem::replace(&mut self.unexpanded_attribute_macros, Vec::new()); let mut resolved = Vec::new(); let mut res = ReachedFixedPoint::Yes; - macros.retain(|(module_id, ast_id, path)| { + macros.retain(|directive| { + if let Some(call_id) = directive.legacy { + res = ReachedFixedPoint::No; + resolved.push((directive.module_id, call_id)); + return false; + } + let resolved_res = self.def_map.resolve_path_fp_with_macro( self.db, ResolveMode::Other, - *module_id, - path, + directive.module_id, + &directive.path, BuiltinShadowMode::Module, ); if let Some(def) = resolved_res.resolved_def.take_macros() { - let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(*ast_id)); - resolved.push((*module_id, call_id, def)); + let call_id = def.as_call_id(self.db, MacroCallKind::FnLike(directive.ast_id)); + resolved.push((directive.module_id, call_id)); res = ReachedFixedPoint::No; return false; } @@ -579,7 +547,7 @@ where if let Some(def) = resolved_res { let call_id = def.as_call_id(self.db, MacroCallKind::Attr(*ast_id)); - resolved.push((*module_id, call_id, def)); + resolved.push((*module_id, call_id)); res = ReachedFixedPoint::No; return false; } @@ -590,8 +558,8 @@ where self.unexpanded_macros = macros; self.unexpanded_attribute_macros = attribute_macros; - for (module_id, macro_call_id, macro_def_id) in resolved { - self.collect_macro_expansion(module_id, macro_call_id, macro_def_id); + for (module_id, macro_call_id) in resolved { + self.collect_macro_expansion(module_id, macro_call_id); } res @@ -611,36 +579,18 @@ where None } - fn collect_macro_expansion( - &mut self, - module_id: LocalModuleId, - macro_call_id: MacroCallId, - macro_def_id: MacroDefId, - ) { - if self.poison_macros.contains(¯o_def_id) { - return; + fn collect_macro_expansion(&mut self, module_id: LocalModuleId, macro_call_id: MacroCallId) { + let file_id: HirFileId = macro_call_id.as_file(); + let raw_items = self.db.raw_items(file_id); + let mod_dir = self.mod_dirs[&module_id].clone(); + ModCollector { + def_collector: &mut *self, + file_id, + module_id, + raw_items: &raw_items, + mod_dir, } - - self.macro_stack_monitor.increase(macro_def_id); - - if !self.macro_stack_monitor.is_poison(macro_def_id) { - let file_id: HirFileId = macro_call_id.as_file(); - let raw_items = self.db.raw_items(file_id); - let mod_dir = self.mod_dirs[&module_id].clone(); - ModCollector { - def_collector: &mut *self, - file_id, - module_id, - raw_items: &raw_items, - mod_dir, - } - .collect(raw_items.items()); - } else { - log::error!("Too deep macro expansion: {:?}", macro_call_id); - self.poison_macros.insert(macro_def_id); - } - - self.macro_stack_monitor.decrease(macro_def_id); + .collect(raw_items.items()); } fn finish(self) -> CrateDefMap { @@ -908,15 +858,20 @@ where return; } - // Case 2: try to resolve in legacy scope and expand macro_rules, triggering - // recursive item collection. + // Case 2: try to resolve in legacy scope and expand macro_rules if let Some(macro_def) = mac.path.as_ident().and_then(|name| { self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) }) { let macro_call_id = macro_def.as_call_id(self.def_collector.db, MacroCallKind::FnLike(ast_id)); - self.def_collector.collect_macro_expansion(self.module_id, macro_call_id, macro_def); + self.def_collector.unexpanded_macros.push(MacroDirective { + module_id: self.module_id, + path: mac.path.clone(), + ast_id, + legacy: Some(macro_call_id), + }); + return; } @@ -926,7 +881,13 @@ where if path.is_ident() { path.kind = PathKind::Self_; } - self.def_collector.unexpanded_macros.push((self.module_id, ast_id, path)); + + self.def_collector.unexpanded_macros.push(MacroDirective { + module_id: self.module_id, + path, + ast_id, + legacy: None, + }); } fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { @@ -951,19 +912,13 @@ fn is_macro_rules(path: &Path) -> bool { #[cfg(test)] mod tests { + use crate::{db::DefDatabase, test_db::TestDB}; use ra_arena::Arena; use ra_db::{fixture::WithFixture, SourceDatabase}; - use rustc_hash::FxHashSet; - - use crate::{db::DefDatabase, test_db::TestDB}; use super::*; - fn do_collect_defs( - db: &impl DefDatabase, - def_map: CrateDefMap, - monitor: MacroStackMonitor, - ) -> (CrateDefMap, FxHashSet) { + fn do_collect_defs(db: &impl DefDatabase, def_map: CrateDefMap) -> CrateDefMap { let mut collector = DefCollector { db, def_map, @@ -973,19 +928,13 @@ mod tests { unexpanded_macros: Vec::new(), unexpanded_attribute_macros: Vec::new(), mod_dirs: FxHashMap::default(), - macro_stack_monitor: monitor, - poison_macros: FxHashSet::default(), cfg_options: &CfgOptions::default(), }; collector.collect(); - (collector.def_map, collector.poison_macros) + collector.def_map } - fn do_limited_resolve( - code: &str, - limit: u32, - poison_limit: u32, - ) -> (CrateDefMap, FxHashSet) { + fn do_resolve(code: &str) -> CrateDefMap { let (db, _file_id) = TestDB::with_single_file(&code); let krate = db.test_crate(); @@ -1003,59 +952,18 @@ mod tests { diagnostics: Vec::new(), } }; - - let mut monitor = MacroStackMonitor::default(); - monitor.validator = Some(Box::new(move |count| { - assert!(count < limit); - count >= poison_limit - })); - - do_collect_defs(&db, def_map, monitor) + do_collect_defs(&db, def_map) } #[test] - fn test_macro_expand_limit_width() { - do_limited_resolve( + fn test_macro_expand_will_stop() { + do_resolve( r#" macro_rules! foo { ($($ty:ty)*) => { foo!($($ty)*, $($ty)*); } } foo!(KABOOM); "#, - 16, - 1000, ); } - - #[test] - fn test_macro_expand_poisoned() { - let (_, poison_macros) = do_limited_resolve( - r#" - macro_rules! foo { - ($ty:ty) => { foo!($ty); } - } -foo!(KABOOM); - "#, - 100, - 16, - ); - - assert_eq!(poison_macros.len(), 1); - } - - #[test] - fn test_macro_expand_normal() { - let (_, poison_macros) = do_limited_resolve( - r#" - macro_rules! foo { - ($ident:ident) => { struct $ident {} } - } -foo!(Bar); - "#, - 16, - 16, - ); - - assert_eq!(poison_macros.len(), 0); - } } From 78e8934976fa3135c151d2b6b395ce57e832f90e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 8 Dec 2019 14:41:44 +0200 Subject: [PATCH 106/312] Code: check whether the LSP binary is in PATH --- README.md | 3 ++- docs/user/README.md | 17 ++++++++++++++++- editors/code/package-lock.json | 5 +++++ editors/code/package.json | 1 + editors/code/src/extension.ts | 12 ++++++++---- editors/code/src/server.ts | 11 +++++++++-- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 74c971c0d3..979e4ef88a 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ $ cargo xtask install $ cargo xtask install --server ``` -For non-standard setup of VS Code and other editors, see [./docs/user](./docs/user). +For non-standard setup of VS Code and other editors, or if the language server +cannot start, see [./docs/user](./docs/user). ## Documentation diff --git a/docs/user/README.md b/docs/user/README.md index 5ec8fb25d1..04c3493426 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -204,4 +204,19 @@ Installation: * You can now invoke the command palette and type LSP enable to locally/globally enable the rust-analyzer LSP (type LSP enable, then choose either locally or globally, then select rust-analyzer) -* Note that `ra_lsp_server` binary must be in `$PATH` for this to work. If it's not the case, you can specify full path to the binary, which is typically `.cargo/bin/ra_lsp_server`. +### Setting up the `PATH` variable + +On Unix systems, `rustup` adds `~/.cargo/bin` to `PATH` by modifying the shell's +startup file. Depending on your configuration, your Desktop Environment might not +actually load it. If you find that `rust-analyzer` only runs when starting the +editor from the terminal, you will have to set up your `PATH` variable manually. + +There are a couple of ways to do that: + +- for Code, set `rust-analyzer.raLspServerPath` to `~/.cargo/bin` (the `~` is + automatically resolved by the extension) +- copy the binary to a location that is already in `PATH`, e.g. `/usr/local/bin` +- on Linux, use PAM to configure the `PATH` variable, by e.g. putting + `PATH DEFAULT=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:@{HOME}/.cargo/bin:@{HOME}/.local/bin` + in your `~/.pam_environment` file; note that this might interfere with other + defaults set by the system administrator via `/etc/environment`. diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 2ceac60a09..099aaaaa2a 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -763,6 +763,11 @@ "chalk": "^2.0.1" } }, + "lookpath": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.3.tgz", + "integrity": "sha512-XIdgzlX26g10XnzyZdO/4obybEmfGnZyWQZ2DgmmEfVB79X+n3lhUoIzMe501C6s7RmCpAo66OPegWc+CsxYMg==" + }, "magic-string": { "version": "0.25.3", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 94887674ba..5dea8fac0a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -31,6 +31,7 @@ "singleQuote": true }, "dependencies": { + "lookpath": "^1.0.3", "seedrandom": "^3.0.1", "vscode-languageclient": "^5.3.0-next.4" }, diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 683497dfd4..6637c3bf0b 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -14,7 +14,7 @@ import * as events from './events'; import * as notifications from './notifications'; import { Server } from './server'; -export function activate(context: vscode.ExtensionContext) { +export async function activate(context: vscode.ExtensionContext) { function disposeOnDeactivation(disposable: vscode.Disposable) { context.subscriptions.push(disposable); } @@ -159,7 +159,11 @@ export function activate(context: vscode.ExtensionContext) { }); // Start the language server, finally! - startServer(); + try { + await startServer(); + } catch (e) { + vscode.window.showErrorMessage(e.message); + } if (Server.config.displayInlayHints) { const hintsUpdater = new HintsUpdater(); @@ -204,10 +208,10 @@ export function deactivate(): Thenable { return Server.client.stop(); } -async function reloadServer(startServer: () => void) { +async function reloadServer(startServer: () => Promise) { if (Server.client != null) { vscode.window.showInformationMessage('Reloading rust-analyzer...'); await Server.client.stop(); - startServer(); + await startServer(); } } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 7907b70bc5..e717ab294d 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -1,3 +1,4 @@ +import { lookpath } from 'lookpath'; import { homedir } from 'os'; import * as lc from 'vscode-languageclient'; @@ -17,7 +18,7 @@ export class Server { public static config = new Config(); public static client: lc.LanguageClient; - public static start( + public static async start( notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]> ) { // '.' Is the fallback if no folder is open @@ -27,8 +28,14 @@ export class Server { folder = workspace.workspaceFolders[0].uri.fsPath.toString(); } + const command = expandPathResolving(this.config.raLspServerPath); + if (!(await lookpath(command))) { + throw new Error( + `Cannot find rust-analyzer server \`${command}\` in PATH.` + ); + } const run: lc.Executable = { - command: expandPathResolving(this.config.raLspServerPath), + command, options: { cwd: folder } }; const serverOptions: lc.ServerOptions = { From 74c7c7a8b1faa0da6a0880916a5e2e5c2b9c1d3f Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 8 Dec 2019 23:13:56 +0800 Subject: [PATCH 107/312] Use rustup toolchain instead of rustup install --- xtask/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 7332a40729..190baeddfc 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -79,7 +79,7 @@ pub fn run_rustfmt(mode: Mode) -> Result<()> { } pub fn install_rustfmt() -> Result<()> { - run(&format!("rustup install {}", TOOLCHAIN), ".")?; + run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; run(&format!("rustup component add rustfmt --toolchain {}", TOOLCHAIN), ".") } @@ -125,7 +125,7 @@ pub fn run_clippy() -> Result<()> { } pub fn install_clippy() -> Result<()> { - run(&format!("rustup install {}", TOOLCHAIN), ".")?; + run(&format!("rustup toolchain install {}", TOOLCHAIN), ".")?; run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".") } From 6805bb01e203e7a1cbc145382a16c0069a5de6d5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:57:13 +0100 Subject: [PATCH 108/312] Cleanup module structure --- crates/ra_hir/src/code_model.rs | 3 --- .../ra_hir/src/{code_model/src.rs => has_source.rs} | 0 crates/ra_hir/src/lib.rs | 12 +++++++----- 3 files changed, 7 insertions(+), 8 deletions(-) rename crates/ra_hir/src/{code_model/src.rs => has_source.rs} (100%) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 7ac1bf461a..fd30971b0a 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -1,7 +1,4 @@ //! FIXME: write short doc here - -pub(crate) mod src; - use std::sync::Arc; use either::Either; diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/has_source.rs similarity index 100% rename from crates/ra_hir/src/code_model/src.rs rename to crates/ra_hir/src/has_source.rs diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index bb22882b13..946299ba08 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -36,16 +36,18 @@ pub mod diagnostics; mod from_id; mod code_model; -pub mod from_source; +mod has_source; +mod from_source; pub use crate::{ code_model::{ - src::HasSource, Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, - DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs, - ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, - StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, + Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, + EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, + MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, + TypeParam, Union, VariantDef, }, from_source::FromSource, + has_source::HasSource, source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, }; From a1639d0d1ef201b2b9a425eddecfb41a25f10931 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 12:58:43 +0100 Subject: [PATCH 109/312] Remove more dead code --- crates/ra_assists/src/test_db.rs | 2 - crates/ra_hir/src/debug.rs | 94 -------------------------------- crates/ra_hir/src/lib.rs | 2 - crates/ra_ide/src/db.rs | 14 +---- 4 files changed, 1 insertion(+), 111 deletions(-) delete mode 100644 crates/ra_hir/src/debug.rs diff --git a/crates/ra_assists/src/test_db.rs b/crates/ra_assists/src/test_db.rs index 523259fd46..d5249f3088 100644 --- a/crates/ra_assists/src/test_db.rs +++ b/crates/ra_assists/src/test_db.rs @@ -43,5 +43,3 @@ impl FileLoader for TestDB { FileLoaderDelegate(self).relevant_crates(file_id) } } - -impl hir::debug::HirDebugHelper for TestDB {} diff --git a/crates/ra_hir/src/debug.rs b/crates/ra_hir/src/debug.rs deleted file mode 100644 index 6cd5c8cb97..0000000000 --- a/crates/ra_hir/src/debug.rs +++ /dev/null @@ -1,94 +0,0 @@ -//! XXX: This does not work at the moment. -//! -//! printf debugging infrastructure for rust-analyzer. -//! -//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`, -//! you usually get back a numeric ID, which doesn't tell you much: -//! `Module(92)`. -//! -//! This module adds convenience `debug` methods to various types, which resolve -//! the id to a human-readable location info: -//! -//! ```not_rust -//! eprintln!("{:?}", module.debug(db)); -//! => -//! Module { name: collections, path: "liballoc/collections/mod.rs" } -//! ``` -//! -//! Note that to get this info, we might need to execute queries! So -//! -//! * don't use the `debug` methods for logging -//! * when debugging, be aware that interference is possible. - -use std::fmt; - -use hir_expand::HirFileId; -use ra_db::{CrateId, FileId}; - -use crate::{db::HirDatabase, Crate, Module, Name}; - -impl Crate { - pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { - debug_fn(move |fmt| db.debug_crate(self, fmt)) - } -} - -impl Module { - pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ { - debug_fn(move |fmt| db.debug_module(self, fmt)) - } -} - -pub trait HirDebugHelper: HirDatabase { - fn crate_name(&self, _krate: CrateId) -> Option { - None - } - fn file_path(&self, _file_id: FileId) -> Option { - None - } -} - -pub trait HirDebugDatabase { - fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; - fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; - fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; -} - -impl HirDebugDatabase for DB { - fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut builder = fmt.debug_tuple("Crate"); - match self.crate_name(krate.id) { - Some(name) => builder.field(&name), - None => builder.field(&krate.id), - } - .finish() - } - - fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let file_id = module.definition_source(self).file_id.original_file(self); - let path = self.file_path(file_id).unwrap_or_else(|| "N/A".to_string()); - fmt.debug_struct("Module") - .field("name", &module.name(self).unwrap_or_else(Name::missing)) - .field("path", &path) - .finish() - } - - fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - let original = file_id.original_file(self); - let path = self.file_path(original).unwrap_or_else(|| "N/A".to_string()); - let is_macro = file_id != original.into(); - fmt.debug_struct("HirFileId").field("path", &path).field("macro", &is_macro).finish() - } -} - -fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug { - struct DebugFn(F); - - impl) -> fmt::Result> fmt::Debug for DebugFn { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - (&self.0)(fmt) - } - } - - DebugFn(f) -} diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 946299ba08..e7602ee305 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -26,8 +26,6 @@ macro_rules! impl_froms { } } -pub mod debug; - pub mod db; pub mod source_binder; diff --git a/crates/ra_ide/src/db.rs b/crates/ra_ide/src/db.rs index f739ebecd3..47d0aed6fb 100644 --- a/crates/ra_ide/src/db.rs +++ b/crates/ra_ide/src/db.rs @@ -5,7 +5,7 @@ use std::sync::Arc; use ra_db::{ salsa::{self, Database, Durability}, Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, RelativePath, - SourceDatabase, SourceDatabaseExt, SourceRootId, + SourceDatabase, SourceRootId, }; use rustc_hash::FxHashMap; @@ -49,18 +49,6 @@ impl FileLoader for RootDatabase { } } -impl hir::debug::HirDebugHelper for RootDatabase { - fn crate_name(&self, krate: CrateId) -> Option { - self.debug_data.crate_names.get(&krate).cloned() - } - fn file_path(&self, file_id: FileId) -> Option { - let source_root_id = self.file_source_root(file_id); - let source_root_path = self.debug_data.root_paths.get(&source_root_id)?; - let file_path = self.file_relative_path(file_id); - Some(format!("{}/{}", source_root_path, file_path)) - } -} - impl salsa::Database for RootDatabase { fn salsa_runtime(&self) -> &salsa::Runtime { &self.runtime From 61c3887b70820283cb759127e3aecf7cbdbdc8c1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 8 Dec 2019 17:50:43 +0100 Subject: [PATCH 110/312] Remove one more Ty --- crates/ra_hir/src/code_model.rs | 5 ----- crates/ra_hir/src/source_binder.rs | 4 ++-- crates/ra_ide/src/completion/complete_dot.rs | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index fd30971b0a..c013ff99bb 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -986,11 +986,6 @@ impl Type { None } - // FIXME: remove - pub fn into_ty(self) -> Ty { - self.ty.value - } - pub fn as_adt(&self) -> Option { let (adt, _subst) = self.ty.value.as_adt()?; Some(adt.into()) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 9efd0477c1..44d1850038 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -427,7 +427,7 @@ impl SourceAnalyzer { /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. - pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { + pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool { let std_future_path = known::std_future_future(); let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { @@ -440,7 +440,7 @@ impl SourceAnalyzer { _ => return false, }; - let canonical_ty = Canonical { value: ty, num_vars: 0 }; + let canonical_ty = Canonical { value: ty.ty.value, num_vars: 0 }; implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait) } diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index a52eb0ee4a..294964887a 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs @@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { complete_methods(acc, ctx, &receiver_ty); // Suggest .await syntax for types that implement Future trait - if ctx.analyzer.impls_future(ctx.db, receiver_ty.into_ty()) { + if ctx.analyzer.impls_future(ctx.db, receiver_ty) { CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") .detail("expr.await") .insert_text("await") From c7dc067104c602e18264be0fab2eb197366ac827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 8 Dec 2019 20:27:50 +0200 Subject: [PATCH 111/312] Code: bump deps --- editors/code/package-lock.json | 631 ++++++++++++------------------- editors/code/package.json | 26 +- editors/code/src/extension.ts | 7 +- editors/code/src/highlighting.ts | 7 +- 4 files changed, 253 insertions(+), 418 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 099aaaaa2a..4e8ed70488 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -60,9 +60,9 @@ "dev": true }, "@types/node": { - "version": "10.14.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.13.tgz", - "integrity": "sha512-yN/FNNW1UYsRR1wwAoyOwqvDuLDtVXnaJTZ898XIw/Q5cCaeVAlVwvsmXLX5PuiScBYwZsZU4JYSHB3TvfdwvQ==", + "version": "10.17.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz", + "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==", "dev": true }, "@types/resolve": { @@ -81,9 +81,9 @@ "dev": true }, "@types/vscode": { - "version": "1.37.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.37.0.tgz", - "integrity": "sha512-PRfeuqYuzk3vjf+puzxltIUWC+AhEGYpFX29/37w30DQSQnpf5AgMVf7GDBAdmTbWTBou+EMFz/Ne6XCM/KxzQ==", + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.40.0.tgz", + "integrity": "sha512-5kEIxL3qVRkwhlMerxO7XuMffa+0LBl+iG2TcRa0NsdoeSFLkt/9hJ02jsi/Kvc6y8OVF2N2P2IHP5S4lWf/5w==", "dev": true }, "acorn": { @@ -198,6 +198,17 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "cheerio": { @@ -215,22 +226,44 @@ } }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } } }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -247,9 +280,9 @@ "dev": true }, "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, "concat-map": { @@ -258,19 +291,6 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -290,12 +310,12 @@ "dev": true }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, "decamelize": { @@ -372,15 +392,6 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, "entities": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", @@ -388,23 +399,27 @@ "dev": true }, "es-abstract": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", - "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "version": "1.16.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.3.tgz", + "integrity": "sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", + "has-symbols": "^1.0.1", "is-callable": "^1.1.4", "is-regex": "^1.0.4", - "object-keys": "^1.0.12" + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "string.prototype.trimleft": "^2.1.0", + "string.prototype.trimright": "^2.1.0" } }, "es-to-primitive": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, "requires": { "is-callable": "^1.1.4", @@ -452,26 +467,11 @@ "dev": true }, "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, - "execa": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "requires": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -517,19 +517,10 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -562,9 +553,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", "dev": true }, "he": { @@ -595,6 +586,23 @@ "requires": { "agent-base": "4", "debug": "3.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "https-proxy-agent": { @@ -618,9 +626,9 @@ } }, "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, "interpret": { @@ -629,16 +637,10 @@ "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", "dev": true }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "is-buffer": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.3.tgz", - "integrity": "sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", "dev": true }, "is-callable": { @@ -683,19 +685,13 @@ "has": "^1.0.1" } }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", "dev": true, "requires": { - "has-symbols": "^1.0.0" + "has-symbols": "^1.0.1" } }, "isexe": { @@ -720,15 +716,6 @@ "esprima": "^4.0.0" } }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -777,15 +764,6 @@ "sourcemap-codec": "^1.4.4" } }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, "markdown-it": { "version": "8.4.2", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", @@ -805,29 +783,12 @@ "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", "dev": true }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", "dev": true }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -853,9 +814,9 @@ } }, "mocha": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.0.tgz", - "integrity": "sha512-qwfFgY+7EKAAUAdv7VYMZQknI7YJSGesxHyhn6qD52DV8UcSZs5XwCifcZGMVIE4a5fbmhvbotxC0DLQ0oKohQ==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-6.2.2.tgz", + "integrity": "sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A==", "dev": true, "requires": { "ansi-colors": "3.2.3", @@ -878,20 +839,11 @@ "supports-color": "6.0.0", "which": "1.3.1", "wide-align": "1.1.3", - "yargs": "13.2.2", - "yargs-parser": "13.0.0", - "yargs-unparser": "1.5.0" + "yargs": "13.3.0", + "yargs-parser": "13.1.1", + "yargs-unparser": "1.6.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -905,28 +857,13 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", "dev": true }, "mute-stream": { @@ -935,12 +872,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true - }, "node-environment-flags": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.5.tgz", @@ -951,15 +882,6 @@ "semver": "^5.7.0" } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -969,10 +891,10 @@ "boolbase": "~1.0.0" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "object-inspect": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", "dev": true }, "object-keys": { @@ -1024,17 +946,6 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", - "dev": true, - "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" - } - }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -1051,24 +962,6 @@ "os-tmpdir": "^1.0.0" } }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, "p-limit": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", @@ -1123,12 +1016,6 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -1142,21 +1029,11 @@ "dev": true }, "prettier": { - "version": "1.18.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz", - "integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -1217,9 +1094,9 @@ } }, "rollup": { - "version": "1.23.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.23.1.tgz", - "integrity": "sha512-95C1GZQpr/NIA0kMUQmSjuMDQ45oZfPgDBcN0yZwBG7Kee//m7H68vgIyg+SPuyrTZ5PrXfyLK80OzXeKG5dAA==", + "version": "1.27.9", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.9.tgz", + "integrity": "sha512-8AfW4cJTPZfG6EXWwT/ujL4owUsDI1Xl8J1t+hvK4wDX81F5I4IbwP9gvGbHzxnV19fnU4rRABZQwZSX9J402Q==", "dev": true, "requires": { "@types/estree": "*", @@ -1318,14 +1195,15 @@ "dev": true }, "seedrandom": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.1.tgz", - "integrity": "sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg==" + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" }, "semver": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.0.tgz", - "integrity": "sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA==" + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true }, "set-blocking": { "version": "2.0.0", @@ -1333,21 +1211,6 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, "shelljs": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.3.tgz", @@ -1378,12 +1241,6 @@ } } }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, "sourcemap-codec": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", @@ -1406,6 +1263,26 @@ "strip-ansi": "^4.0.0" } }, + "string.prototype.trimleft": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", + "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimright": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", + "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "function-bind": "^1.1.1" + } + }, "string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1424,12 +1301,6 @@ "ansi-regex": "^3.0.0" } }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", @@ -1437,9 +1308,9 @@ "dev": true }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -1461,16 +1332,16 @@ "dev": true }, "tslint": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.18.0.tgz", - "integrity": "sha512-Q3kXkuDEijQ37nXZZLKErssQVnwCV/+23gFEMROi8IlbaBG6tXqLPQJ5Wjcyt/yHPKBC+hD5SzuGaMora+ZS6w==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "builtin-modules": "^1.1.1", "chalk": "^2.3.0", "commander": "^2.12.1", - "diff": "^3.2.0", + "diff": "^4.0.1", "glob": "^7.1.1", "js-yaml": "^3.13.1", "minimatch": "^3.0.4", @@ -1479,6 +1350,14 @@ "semver": "^5.3.0", "tslib": "^1.8.0", "tsutils": "^2.29.0" + }, + "dependencies": { + "diff": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", + "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "dev": true + } } }, "tslint-config-prettier": { @@ -1513,9 +1392,9 @@ } }, "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==", "dev": true }, "uc.micro": { @@ -1543,9 +1422,9 @@ "dev": true }, "vsce": { - "version": "1.67.1", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.67.1.tgz", - "integrity": "sha512-Y/0fnfaLs2cCfytTGmy4Cp1bf9BaxHO7020YePdUwxjAlPlZ9+lm74M9yEFEWXTIug0L0sMax1WMz0TnozIqxg==", + "version": "1.70.0", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.70.0.tgz", + "integrity": "sha512-mBTbVrWL348jODwfmaR+yXrlzb8EABGCT067C4shKOXriWiuMQi4/uCbFm6TUBcfnzTYLJv+DKa0VnKU8yEAjA==", "dev": true, "requires": { "azure-devops-node-api": "^7.2.0", @@ -1571,41 +1450,48 @@ } }, "vscode-jsonrpc": { - "version": "4.1.0-next.3", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-4.1.0-next.3.tgz", - "integrity": "sha512-Z6oxBiMks2+UADV1QHXVooSakjyhI+eHTnXzDyVvVMmegvSfkXk2w6mPEdSkaNHFBdtWW7n20H1yw2nA3A17mg==" + "version": "5.0.0-next.5", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-5.0.0-next.5.tgz", + "integrity": "sha512-k9akfglxWgr0dtLNscq2uBq48XJwnhf4EaDxn05KQowRwR0DkNML0zeYqFRLtXZe6x5vpL5ppyu4o6GqL+23YQ==" }, "vscode-languageclient": { - "version": "5.3.0-next.4", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-5.3.0-next.4.tgz", - "integrity": "sha512-RODuzXErVpJRSgHv+Xei8fwQtZ/iZOWPCqlLl07NTtkzgTAepJf9r4EioZVuTviGJ5DEJ9xs0bjrit8shKtW6Q==", + "version": "6.0.0-next.8", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.8.tgz", + "integrity": "sha512-452jskmuT7YKYnPd5uh7aELK4M25OITcnBq4ylPIyUtE5LQRgA9N9pR9NrviTTX/Hh6q6VGzm70OK9SpMO/zcA==", "requires": { - "semver": "^5.5.0", - "vscode-languageserver-protocol": "3.15.0-next.4" + "semver": "^6.3.0", + "vscode-languageserver-protocol": "^3.15.0-next.13" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } } }, "vscode-languageserver-protocol": { - "version": "3.15.0-next.4", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.4.tgz", - "integrity": "sha512-4AgisQ8GWa3irdRu3/UNr3brcSSm0oobmoV1eSOnV7JM32lYyXDnSKB7RuTTXvaAjD/0xQJLEGhkyGHS5gbywA==", + "version": "3.15.0-next.13", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.13.tgz", + "integrity": "sha512-2UGxOKc5VHav15n3zY5dtaOXGL/JuV0K2Mem/n6lhF8i3vaqIAnKv004SPU0flYHXIfCcQM7kCL+nwWVJ1K1qw==", "requires": { - "vscode-jsonrpc": "^4.1.0-next.1", - "vscode-languageserver-types": "3.15.0-next.1" + "vscode-jsonrpc": "^5.0.0-next.5", + "vscode-languageserver-types": "^3.15.0-next.9" } }, "vscode-languageserver-types": { - "version": "3.15.0-next.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.1.tgz", - "integrity": "sha512-R0kzmaI8gOGEoU7b9huYQAzgZzRQ/5Q8HKjsIUdfz0MjXcBZ4tr1ik1So1p1O5kGrI1VTCd22Fw/wI7ECGoIPw==" + "version": "3.15.0-next.9", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.15.0-next.9.tgz", + "integrity": "sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw==" }, "vscode-test": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.0.tgz", - "integrity": "sha512-aowqgc8gZe0eflzVUXsBjBrlsJ8eC35kfgfSEeHu9PKA1vQKm/3rVK43TlbxGue8hKtZBElNAJ5QuYklR/vLJA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.3.tgz", + "integrity": "sha512-mKRTNso33NaUULiPBFg6zRjyntjcCpIgkrogyPQuKlvoQREQR8jLKN5UD4L5rkTSD+oBhcKtaLR2/g34FexURw==", "dev": true, "requires": { "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^2.2.4", "rimraf": "^2.6.3" } }, @@ -1634,48 +1520,40 @@ } }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" } } } @@ -1693,22 +1571,21 @@ "dev": true }, "yargs": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.2.tgz", - "integrity": "sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA==", + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", "dev": true, "requires": { - "cliui": "^4.0.0", + "cliui": "^5.0.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" + "yargs-parser": "^13.1.1" }, "dependencies": { "ansi-regex": { @@ -1740,9 +1617,9 @@ } }, "yargs-parser": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.0.0.tgz", - "integrity": "sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -1750,58 +1627,14 @@ } }, "yargs-unparser": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.5.0.tgz", - "integrity": "sha512-HK25qidFTCVuj/D1VfNiEndpLIeJN78aqgR23nL3y4N0U/91cOAzqfHlF8n2BvoNDcZmJKin3ddNSvOxSr8flw==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", "dev": true, "requires": { "flat": "^4.1.0", - "lodash": "^4.17.11", - "yargs": "^12.0.5" - }, - "dependencies": { - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", - "dev": true, - "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", - "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - } - }, - "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } + "lodash": "^4.17.15", + "yargs": "^13.3.0" } }, "yauzl": { diff --git a/editors/code/package.json b/editors/code/package.json index 5dea8fac0a..84a45945fd 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -13,7 +13,7 @@ "Other" ], "engines": { - "vscode": "^1.37.0" + "vscode": "^1.40.0" }, "scripts": { "vscode:prepublish": "npm run compile", @@ -32,28 +32,28 @@ }, "dependencies": { "lookpath": "^1.0.3", - "seedrandom": "^3.0.1", - "vscode-languageclient": "^5.3.0-next.4" + "seedrandom": "^3.0.5", + "vscode-languageclient": "^6.0.0-next.8" }, "devDependencies": { "@types/glob": "^7.1.1", "@types/mocha": "^5.2.7", - "@types/node": "^10.14.13", + "@types/node": "^10.17.6", "@types/seedrandom": "^2.4.28", - "@types/vscode": "^1.37.0", - "glob": "^7.1.4", - "mocha": "^6.2.0", - "prettier": "^1.18.2", - "rollup": "^1.23.1", + "@types/vscode": "^1.40.0", + "glob": "^7.1.6", + "mocha": "^6.2.2", + "prettier": "^1.19.1", + "rollup": "^1.27.9", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-typescript": "^1.0.1", "shx": "^0.3.1", - "tslint": "^5.18.0", + "tslint": "^5.20.1", "tslint-config-prettier": "^1.18.0", - "typescript": "^3.5.3", - "vsce": "^1.67.0", - "vscode-test": "^1.2.0" + "typescript": "^3.7.3", + "vsce": "^1.70.0", + "vscode-test": "^1.2.3" }, "activationEvents": [ "onLanguage:rust", diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index 6637c3bf0b..a78aa3b425 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -89,9 +89,10 @@ export async function activate(context: vscode.ExtensionContext) { } // Notifications are events triggered by the language server - const allNotifications: Iterable< - [string, lc.GenericNotificationHandler] - > = [ + const allNotifications: Iterable<[ + string, + lc.GenericNotificationHandler + ]> = [ [ 'rust-analyzer/publishDecorations', notifications.publishDecorations.handle diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index d21d8a06af..48f2a2547d 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -40,9 +40,10 @@ export class Highlighter { return [tag, decor]; }; - const decorations: Iterable< - [string, vscode.TextEditorDecorationType] - > = [ + const decorations: Iterable<[ + string, + vscode.TextEditorDecorationType + ]> = [ decoration('comment'), decoration('string'), decoration('keyword'), From ee2bc73d2a8bb5479019609b495c65d1d6132d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Sun, 8 Dec 2019 21:08:46 +0200 Subject: [PATCH 112/312] Code: don't check for ra_lsp_server on Windows --- editors/code/src/server.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index e717ab294d..b346c08288 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -1,5 +1,5 @@ import { lookpath } from 'lookpath'; -import { homedir } from 'os'; +import { homedir, platform } from 'os'; import * as lc from 'vscode-languageclient'; import { window, workspace } from 'vscode'; @@ -29,10 +29,14 @@ export class Server { } const command = expandPathResolving(this.config.raLspServerPath); - if (!(await lookpath(command))) { - throw new Error( - `Cannot find rust-analyzer server \`${command}\` in PATH.` - ); + // FIXME: remove check when the following issue is fixed: + // https://github.com/otiai10/lookpath/issues/4 + if (platform() !== 'win32') { + if (!(await lookpath(command))) { + throw new Error( + `Cannot find rust-analyzer server \`${command}\` in PATH.` + ); + } } const run: lc.Executable = { command, From 81ce9833a59756b85c0528cbc76dfb4b272d651c Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Mon, 9 Dec 2019 03:58:43 +0800 Subject: [PATCH 113/312] Add rollup sourcemap and fix launch.json --- .vscode/launch.json | 2 +- editors/code/package-lock.json | 53 ++++++++++++++++++++++++++++++++++ editors/code/package.json | 1 + editors/code/rollup.config.js | 3 ++ 4 files changed, 58 insertions(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 9aafc8bd33..0cf3984a9a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -16,7 +16,7 @@ "env": { "__RA_LSP_SERVER_DEBUG": "${workspaceFolder}/target/debug/ra_lsp_server" }, - "outFiles": ["${workspaceFolder}/editors/code/out/**/*.js"], + "outFiles": ["${workspaceFolder}/editors/code/bundle/**/*.js"], "preLaunchTask": "Build All" }, { diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 4e8ed70488..b1baa437e9 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -131,6 +131,12 @@ "sprintf-js": "~1.0.2" } }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, "azure-devops-node-api": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-7.2.0.tgz", @@ -324,6 +330,12 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -1084,6 +1096,12 @@ "path-parse": "^1.0.6" } }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -1158,6 +1176,16 @@ } } }, + "rollup-plugin-sourcemaps": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.4.2.tgz", + "integrity": "sha1-YhJaqUCHqt97g+9N+vYptHMTXoc=", + "dev": true, + "requires": { + "rollup-pluginutils": "^2.0.1", + "source-map-resolve": "^0.5.0" + } + }, "rollup-plugin-typescript": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rollup-plugin-typescript/-/rollup-plugin-typescript-1.0.1.tgz", @@ -1241,6 +1269,25 @@ } } }, + "source-map-resolve": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-url": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", + "dev": true + }, "sourcemap-codec": { "version": "1.4.6", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", @@ -1409,6 +1456,12 @@ "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=", "dev": true }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, "url-join": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-1.1.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 84a45945fd..ae2049c570 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -48,6 +48,7 @@ "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-typescript": "^1.0.1", + "rollup-plugin-sourcemaps": "^0.4.2", "shx": "^0.3.1", "tslint": "^5.20.1", "tslint-config-prettier": "^1.18.0", diff --git a/editors/code/rollup.config.js b/editors/code/rollup.config.js index a023b8c3fe..1b222bbe78 100644 --- a/editors/code/rollup.config.js +++ b/editors/code/rollup.config.js @@ -1,12 +1,14 @@ import typescript from 'rollup-plugin-typescript'; import resolve from 'rollup-plugin-node-resolve'; import commonjs from 'rollup-plugin-commonjs'; +import sourcemaps from 'rollup-plugin-sourcemaps' import nodeBuiltins from 'builtin-modules'; export default { input: './src/extension.ts', plugins: [ typescript(), + sourcemaps(), resolve(), commonjs({ namedExports: { @@ -22,6 +24,7 @@ export default { ], output: { file: './bundle/extension.js', + sourcemap: true, format: 'cjs', } }; From 5a012fb9fd87404515033b2a5e025f2b7ec44b29 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 9 Dec 2019 15:59:04 +0100 Subject: [PATCH 114/312] Implement `ra_lsp_server --version` --- crates/ra_lsp_server/build.rs | 15 +++++++++++++++ crates/ra_lsp_server/src/main.rs | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 crates/ra_lsp_server/build.rs diff --git a/crates/ra_lsp_server/build.rs b/crates/ra_lsp_server/build.rs new file mode 100644 index 0000000000..05f9772c04 --- /dev/null +++ b/crates/ra_lsp_server/build.rs @@ -0,0 +1,15 @@ +//! Just embed git-hash to `--version` + +use std::process::Command; + +fn main() { + let rev = rev().unwrap_or_else(|| "???????".to_string()); + println!("cargo:rustc-env=REV={}", rev) +} + +fn rev() -> Option { + let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().ok()?; + let stdout = String::from_utf8(output.stdout).ok()?; + let short_hash = stdout.get(0..7)?; + Some(short_hash.to_owned()) +} diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 8076a7fa5c..cdd925c9f3 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs @@ -6,7 +6,10 @@ use ra_prof; fn main() -> Result<()> { setup_logging()?; - run_server()?; + match Args::parse()? { + Args::Version => println!("rust-analyzer {}", env!("REV")), + Args::Run => run_server()?, + } Ok(()) } @@ -22,6 +25,19 @@ fn setup_logging() -> Result<()> { Ok(()) } +enum Args { + Version, + Run, +} + +impl Args { + fn parse() -> Result { + let res = + if std::env::args().any(|it| it == "--version") { Args::Version } else { Args::Run }; + Ok(res) + } +} + fn run_server() -> Result<()> { log::info!("lifecycle: server started"); From 7ac4ea7fec018f76eed5b5c10fc96ba3d9b969be Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 9 Dec 2019 18:05:49 +0100 Subject: [PATCH 115/312] Allow disabling sysroot Might be helpful for debugging --- editors/code/src/config.ts | 5 +++++ editors/code/src/server.ts | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 95c3f42e50..fb9e55dd6f 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -26,6 +26,8 @@ export class Config { public excludeGlobs = []; public useClientWatching = false; public featureFlags = {}; + // for internal use + public withSysroot: null | boolean = null; public cargoWatchOptions: CargoWatchOptions = { enableOnStartup: 'ask', trace: 'off', @@ -148,5 +150,8 @@ export class Config { if (config.has('featureFlags')) { this.featureFlags = config.get('featureFlags') || {}; } + if (config.has('withSysroot')) { + this.withSysroot = config.get('withSysroot') || false; + } } } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index b346c08288..e767b6f1b0 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -57,7 +57,8 @@ export class Server { maxInlayHintLength: Server.config.maxInlayHintLength, excludeGlobs: Server.config.excludeGlobs, useClientWatching: Server.config.useClientWatching, - featureFlags: Server.config.featureFlags + featureFlags: Server.config.featureFlags, + withSysroot: Server.config.withSysroot }, traceOutputChannel }; From b683cbd93db65f5421ef9b7617a2abfe93928af0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 9 Dec 2019 18:42:45 +0100 Subject: [PATCH 116/312] Report correct original range in goto_definition --- crates/ra_ide/src/goto_definition.rs | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index b93d6a931a..cfe62037fc 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -19,25 +19,23 @@ pub(crate) fn goto_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; - let token = descend_into_macros(db, position.file_id, token); + let original_token = + file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + let token = descend_into_macros(db, position.file_id, original_token.clone()); - let res = match_ast! { + let nav_targets = match_ast! { match (token.value.parent()) { ast::NameRef(name_ref) => { - let navs = reference_definition(db, token.with_value(&name_ref)).to_vec(); - RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) + reference_definition(db, token.with_value(&name_ref)).to_vec() }, ast::Name(name) => { - let navs = name_definition(db, token.with_value(&name))?; - RangeInfo::new(name.syntax().text_range(), navs) - + name_definition(db, token.with_value(&name))? }, _ => return None, } }; - Some(res) + Some(RangeInfo::new(original_token.text_range(), nav_targets)) } #[derive(Debug)] From 273299693b85996878907ad256ed55f072ec3f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 9 Dec 2019 20:57:55 +0200 Subject: [PATCH 117/312] Code: enable prettier trailing commas --- editors/code/package.json | 3 +- editors/code/src/commands/analyzer_status.ts | 14 ++--- .../code/src/commands/apply_source_change.ts | 8 +-- editors/code/src/commands/cargo_watch.ts | 34 +++++------ editors/code/src/commands/expand_macro.ts | 10 ++-- editors/code/src/commands/index.ts | 2 +- editors/code/src/commands/inlay_hints.ts | 34 +++++------ editors/code/src/commands/join_lines.ts | 6 +- editors/code/src/commands/matching_brace.ts | 6 +- editors/code/src/commands/on_enter.ts | 8 +-- editors/code/src/commands/parent_module.ts | 6 +- editors/code/src/commands/runnables.ts | 36 ++++++------ editors/code/src/commands/syntaxTree.ts | 10 ++-- editors/code/src/commands/watch_status.ts | 2 +- editors/code/src/config.ts | 22 ++++---- .../src/events/change_active_text_editor.ts | 6 +- .../code/src/events/change_text_document.ts | 2 +- editors/code/src/extension.ts | 56 +++++++++---------- editors/code/src/highlighting.ts | 16 +++--- .../src/notifications/publish_decorations.ts | 2 +- editors/code/src/server.ts | 22 ++++---- .../utils/diagnotics/SuggestedFix.test.ts | 26 ++++----- .../diagnotics/SuggestedFixCollection.test.ts | 20 +++---- .../src/test/utils/diagnotics/rust.test.ts | 52 ++++++++--------- .../src/test/utils/diagnotics/vscode.test.ts | 24 ++++---- editors/code/src/test/utils/index.ts | 2 +- .../src/utils/diagnostics/SuggestedFix.ts | 4 +- .../diagnostics/SuggestedFixCollection.ts | 6 +- editors/code/src/utils/diagnostics/rust.ts | 20 +++---- editors/code/src/utils/diagnostics/vscode.ts | 2 +- editors/code/src/utils/processes.ts | 4 +- 31 files changed, 233 insertions(+), 232 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index ae2049c570..7bc08ec31f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -27,8 +27,9 @@ "travis": "npm run compile && npm run test && npm run lint && npm run prettier -- --write && git diff --exit-code" }, "prettier": { + "singleQuote": true, "tabWidth": 4, - "singleQuote": true + "trailingComma": "all" }, "dependencies": { "lookpath": "^1.0.3", diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts index 63f82c92d8..9e4ce0eb3c 100644 --- a/editors/code/src/commands/analyzer_status.ts +++ b/editors/code/src/commands/analyzer_status.ts @@ -9,7 +9,7 @@ export class TextDocumentContentProvider public syntaxTree: string = 'Not available'; public provideTextDocumentContent( - uri: vscode.Uri + uri: vscode.Uri, ): vscode.ProviderResult { const editor = vscode.window.activeTextEditor; if (editor == null) { @@ -17,7 +17,7 @@ export class TextDocumentContentProvider } return Server.client.sendRequest( 'rust-analyzer/analyzerStatus', - null + null, ); } @@ -35,8 +35,8 @@ export function makeCommand(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.workspace.registerTextDocumentContentProvider( 'rust-analyzer-status', - textDocumentContentProvider - ) + textDocumentContentProvider, + ), ); context.subscriptions.push({ @@ -44,21 +44,21 @@ export function makeCommand(context: vscode.ExtensionContext) { if (poller != null) { clearInterval(poller); } - } + }, }); return async function handle() { if (poller == null) { poller = setInterval( () => textDocumentContentProvider.eventEmitter.fire(statusUri), - 1000 + 1000, ); } const document = await vscode.workspace.openTextDocument(statusUri); return vscode.window.showTextDocument( document, vscode.ViewColumn.Two, - true + true, ); }; } diff --git a/editors/code/src/commands/apply_source_change.ts b/editors/code/src/commands/apply_source_change.ts index dcd074b8bc..8167398b1c 100644 --- a/editors/code/src/commands/apply_source_change.ts +++ b/editors/code/src/commands/apply_source_change.ts @@ -11,7 +11,7 @@ export interface SourceChange { export async function handle(change: SourceChange) { const wsEdit = Server.client.protocol2CodeConverter.asWorkspaceEdit( - change.workspaceEdit + change.workspaceEdit, ); let created; let moved; @@ -33,10 +33,10 @@ export async function handle(change: SourceChange) { await vscode.window.showTextDocument(doc); } else if (toReveal) { const uri = Server.client.protocol2CodeConverter.asUri( - toReveal.textDocument.uri + toReveal.textDocument.uri, ); const position = Server.client.protocol2CodeConverter.asPosition( - toReveal.position + toReveal.position, ); const editor = vscode.window.activeTextEditor; if (!editor || editor.document.uri.toString() !== uri.toString()) { @@ -48,7 +48,7 @@ export async function handle(change: SourceChange) { editor.selection = new vscode.Selection(position, position); editor.revealRange( new vscode.Range(position, position), - vscode.TextEditorRevealType.Default + vscode.TextEditorRevealType.Default, ); } } diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 59d4ba97a2..512362eb18 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts @@ -9,13 +9,13 @@ import { StatusDisplay } from './watch_status'; import { mapRustDiagnosticToVsCode, - RustDiagnostic + RustDiagnostic, } from '../utils/diagnostics/rust'; import SuggestedFixCollection from '../utils/diagnostics/SuggestedFixCollection'; import { areDiagnosticsEqual } from '../utils/diagnostics/vscode'; export async function registerCargoWatchProvider( - subscriptions: vscode.Disposable[] + subscriptions: vscode.Disposable[], ): Promise { let cargoExists = false; @@ -30,7 +30,7 @@ export async function registerCargoWatchProvider( if (!cargoExists) { vscode.window.showErrorMessage( - `Couldn\'t find \'Cargo.toml\' at ${cargoTomlPath}` + `Couldn\'t find \'Cargo.toml\' at ${cargoTomlPath}`, ); return; } @@ -52,13 +52,13 @@ export class CargoWatchProvider implements vscode.Disposable { constructor() { this.diagnosticCollection = vscode.languages.createDiagnosticCollection( - 'rustc' + 'rustc', ); this.statusDisplay = new StatusDisplay( - Server.config.cargoWatchOptions.command + Server.config.cargoWatchOptions.command, ); this.outputChannel = vscode.window.createOutputChannel( - 'Cargo Watch Trace' + 'Cargo Watch Trace', ); // Track `rustc`'s suggested fixes so we can convert them to code actions @@ -68,15 +68,15 @@ export class CargoWatchProvider implements vscode.Disposable { this.suggestedFixCollection, { providedCodeActionKinds: - SuggestedFixCollection.PROVIDED_CODE_ACTION_KINDS - } + SuggestedFixCollection.PROVIDED_CODE_ACTION_KINDS, + }, ); } public start() { if (this.cargoProcess) { vscode.window.showInformationMessage( - 'Cargo Watch is already running' + 'Cargo Watch is already running', ); return; } @@ -95,7 +95,7 @@ export class CargoWatchProvider implements vscode.Disposable { const ignoreFlags = Server.config.cargoWatchOptions.ignore.reduce( (flags, pattern) => [...flags, '--ignore', pattern], - [] as string[] + [] as string[], ); // Start the cargo watch with json message @@ -105,8 +105,8 @@ export class CargoWatchProvider implements vscode.Disposable { { stdio: ['ignore', 'pipe', 'pipe'], cwd: vscode.workspace.rootPath, - windowsVerbatimArguments: true - } + windowsVerbatimArguments: true, + }, ); const stdoutData = new LineBuffer(); @@ -130,7 +130,7 @@ export class CargoWatchProvider implements vscode.Disposable { this.cargoProcess.on('error', (err: Error) => { this.logError( - 'Error on cargo-watch process : {\n' + err.message + '}\n' + 'Error on cargo-watch process : {\n' + err.message + '}\n', ); }); @@ -223,12 +223,12 @@ export class CargoWatchProvider implements vscode.Disposable { const fileUri = location.uri; const diagnostics: vscode.Diagnostic[] = [ - ...(this.diagnosticCollection!.get(fileUri) || []) + ...(this.diagnosticCollection!.get(fileUri) || []), ]; // If we're building multiple targets it's possible we've already seen this diagnostic const isDuplicate = diagnostics.some(d => - areDiagnosticsEqual(d, diagnostic) + areDiagnosticsEqual(d, diagnostic), ); if (isDuplicate) { return; @@ -241,7 +241,7 @@ export class CargoWatchProvider implements vscode.Disposable { for (const suggestedFix of suggestedFixes) { this.suggestedFixCollection.addSuggestedFixForDiagnostic( suggestedFix, - diagnostic + diagnostic, ); } @@ -249,7 +249,7 @@ export class CargoWatchProvider implements vscode.Disposable { vscode.commands.executeCommand( 'vscode.executeCodeActionProvider', fileUri, - diagnostic.range + diagnostic.range, ); } } diff --git a/editors/code/src/commands/expand_macro.ts b/editors/code/src/commands/expand_macro.ts index 34e0c8fb33..842898020b 100644 --- a/editors/code/src/commands/expand_macro.ts +++ b/editors/code/src/commands/expand_macro.ts @@ -3,7 +3,7 @@ import { Position, TextDocumentIdentifier } from 'vscode-languageclient'; import { Server } from '../server'; export const expandMacroUri = vscode.Uri.parse( - 'rust-analyzer://expandMacro/[EXPANSION].rs' + 'rust-analyzer://expandMacro/[EXPANSION].rs', ); export class ExpandMacroContentProvider @@ -11,7 +11,7 @@ export class ExpandMacroContentProvider public eventEmitter = new vscode.EventEmitter(); public provideTextDocumentContent( - uri: vscode.Uri + uri: vscode.Uri, ): vscode.ProviderResult { async function handle() { const editor = vscode.window.activeTextEditor; @@ -22,11 +22,11 @@ export class ExpandMacroContentProvider const position = editor.selection.active; const request: MacroExpandParams = { textDocument: { uri: editor.document.uri.toString() }, - position + position, }; const expanded = await Server.client.sendRequest( 'rust-analyzer/expandMacro', - request + request, ); if (expanded == null) { @@ -58,7 +58,7 @@ export function createHandle(provider: ExpandMacroContentProvider) { return vscode.window.showTextDocument( document, vscode.ViewColumn.Two, - true + true, ); }; } diff --git a/editors/code/src/commands/index.ts b/editors/code/src/commands/index.ts index 2ade6d331a..13a696758b 100644 --- a/editors/code/src/commands/index.ts +++ b/editors/code/src/commands/index.ts @@ -19,5 +19,5 @@ export { runnables, syntaxTree, onEnter, - inlayHints + inlayHints, }; diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts index 0dbdd94fba..ac7dcce604 100644 --- a/editors/code/src/commands/inlay_hints.ts +++ b/editors/code/src/commands/inlay_hints.ts @@ -15,8 +15,8 @@ interface InlayHint { const typeHintDecorationType = vscode.window.createTextEditorDecorationType({ after: { - color: new vscode.ThemeColor('ralsp.inlayHint') - } + color: new vscode.ThemeColor('ralsp.inlayHint'), + }, }); export class HintsUpdater { @@ -26,13 +26,13 @@ export class HintsUpdater { if (this.displayHints !== displayHints) { this.displayHints = displayHints; return this.refreshVisibleEditorsHints( - displayHints ? undefined : [] + displayHints ? undefined : [], ); } } public async refreshHintsForVisibleEditors( - cause?: TextDocumentChangeEvent + cause?: TextDocumentChangeEvent, ): Promise { if (!this.displayHints) { return; @@ -48,21 +48,21 @@ export class HintsUpdater { } private async refreshVisibleEditorsHints( - newDecorations?: vscode.DecorationOptions[] + newDecorations?: vscode.DecorationOptions[], ) { const promises: Array> = []; for (const rustEditor of vscode.window.visibleTextEditors.filter( - editor => this.isRustDocument(editor.document) + editor => this.isRustDocument(editor.document), )) { if (newDecorations !== undefined) { promises.push( Promise.resolve( rustEditor.setDecorations( typeHintDecorationType, - newDecorations - ) - ) + newDecorations, + ), + ), ); } else { promises.push(this.updateDecorationsFromServer(rustEditor)); @@ -79,7 +79,7 @@ export class HintsUpdater { } private async updateDecorationsFromServer( - editor: TextEditor + editor: TextEditor, ): Promise { const newHints = await this.queryHints(editor.document.uri.toString()); if (newHints !== null) { @@ -87,20 +87,20 @@ export class HintsUpdater { range: hint.range, renderOptions: { after: { - contentText: `: ${hint.label}` - } - } + contentText: `: ${hint.label}`, + }, + }, })); return editor.setDecorations( typeHintDecorationType, - newDecorations + newDecorations, ); } } private async queryHints(documentUri: string): Promise { const request: InlayHintsParams = { - textDocument: { uri: documentUri } + textDocument: { uri: documentUri }, }; const client = Server.client; return client @@ -108,8 +108,8 @@ export class HintsUpdater { .then(() => client.sendRequest( 'rust-analyzer/inlayHints', - request - ) + request, + ), ); } } diff --git a/editors/code/src/commands/join_lines.ts b/editors/code/src/commands/join_lines.ts index 0d4b12f4d8..134ddc8016 100644 --- a/editors/code/src/commands/join_lines.ts +++ b/editors/code/src/commands/join_lines.ts @@ -4,7 +4,7 @@ import { Range, TextDocumentIdentifier } from 'vscode-languageclient'; import { Server } from '../server'; import { handle as applySourceChange, - SourceChange + SourceChange, } from './apply_source_change'; interface JoinLinesParams { @@ -19,11 +19,11 @@ export async function handle() { } const request: JoinLinesParams = { range: Server.client.code2ProtocolConverter.asRange(editor.selection), - textDocument: { uri: editor.document.uri.toString() } + textDocument: { uri: editor.document.uri.toString() }, }; const change = await Server.client.sendRequest( 'rust-analyzer/joinLines', - request + request, ); await applySourceChange(change); } diff --git a/editors/code/src/commands/matching_brace.ts b/editors/code/src/commands/matching_brace.ts index d86faf4051..364208cc75 100644 --- a/editors/code/src/commands/matching_brace.ts +++ b/editors/code/src/commands/matching_brace.ts @@ -17,15 +17,15 @@ export async function handle() { textDocument: { uri: editor.document.uri.toString() }, offsets: editor.selections.map(s => { return Server.client.code2ProtocolConverter.asPosition(s.active); - }) + }), }; const response = await Server.client.sendRequest( 'rust-analyzer/findMatchingBrace', - request + request, ); editor.selections = editor.selections.map((sel, idx) => { const active = Server.client.protocol2CodeConverter.asPosition( - response[idx] + response[idx], ); const anchor = sel.isEmpty ? active : sel.anchor; return new vscode.Selection(anchor, active); diff --git a/editors/code/src/commands/on_enter.ts b/editors/code/src/commands/on_enter.ts index 16dcb70c81..772c64b3c7 100644 --- a/editors/code/src/commands/on_enter.ts +++ b/editors/code/src/commands/on_enter.ts @@ -3,7 +3,7 @@ import * as lc from 'vscode-languageclient'; import { Server } from '../server'; import { handle as applySourceChange, - SourceChange + SourceChange, } from './apply_source_change'; export async function handle(event: { text: string }): Promise { @@ -18,12 +18,12 @@ export async function handle(event: { text: string }): Promise { const request: lc.TextDocumentPositionParams = { textDocument: { uri: editor.document.uri.toString() }, position: Server.client.code2ProtocolConverter.asPosition( - editor.selection.active - ) + editor.selection.active, + ), }; const change = await Server.client.sendRequest( 'rust-analyzer/onEnter', - request + request, ); if (!change) { return false; diff --git a/editors/code/src/commands/parent_module.ts b/editors/code/src/commands/parent_module.ts index 9d30b7b59a..ad49e1bdbb 100644 --- a/editors/code/src/commands/parent_module.ts +++ b/editors/code/src/commands/parent_module.ts @@ -11,12 +11,12 @@ export async function handle() { const request: lc.TextDocumentPositionParams = { textDocument: { uri: editor.document.uri.toString() }, position: Server.client.code2ProtocolConverter.asPosition( - editor.selection.active - ) + editor.selection.active, + ), }; const response = await Server.client.sendRequest( 'rust-analyzer/parentModule', - request + request, ); const loc = response[0]; if (loc == null) { diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index ac59bf60db..9b1c6643d4 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts @@ -46,17 +46,17 @@ function createTask(spec: Runnable): vscode.Task { label: spec.label, command: spec.bin, args: spec.args, - env: spec.env + env: spec.env, }; const execOption: vscode.ShellExecutionOptions = { cwd: spec.cwd || '.', - env: definition.env + env: definition.env, }; const exec = new vscode.ShellExecution( definition.command, definition.args, - execOption + execOption, ); const f = vscode.workspace.workspaceFolders![0]; @@ -66,7 +66,7 @@ function createTask(spec: Runnable): vscode.Task { definition.label, TASK_SOURCE, exec, - ['$rustc'] + ['$rustc'], ); t.presentationOptions.clear = true; return t; @@ -79,17 +79,17 @@ export async function handle() { return; } const textDocument: lc.TextDocumentIdentifier = { - uri: editor.document.uri.toString() + uri: editor.document.uri.toString(), }; const params: RunnablesParams = { textDocument, position: Server.client.code2ProtocolConverter.asPosition( - editor.selection.active - ) + editor.selection.active, + ), }; const runnables = await Server.client.sendRequest( 'rust-analyzer/runnables', - params + params, ); const items: RunnableQuickPick[] = []; if (prevRunnable) { @@ -124,7 +124,7 @@ export async function handleSingle(runnable: Runnable) { task.presentationOptions = { reveal: vscode.TaskRevealKind.Always, panel: vscode.TaskPanelKind.Dedicated, - clear: true + clear: true, }; return vscode.tasks.executeTask(task); @@ -136,7 +136,7 @@ export async function handleSingle(runnable: Runnable) { * that, when accepted, allow us to `cargo install cargo-watch` and then run it. */ export async function interactivelyStartCargoWatch( - context: vscode.ExtensionContext + context: vscode.ExtensionContext, ): Promise { if (Server.config.cargoWatchOptions.enableOnStartup === 'disabled') { return; @@ -146,7 +146,7 @@ export async function interactivelyStartCargoWatch( const watch = await vscode.window.showInformationMessage( 'Start watching changes with cargo? (Executes `cargo watch`, provides inline diagnostics)', 'yes', - 'no' + 'no', ); if (watch !== 'yes') { return; @@ -157,12 +157,12 @@ export async function interactivelyStartCargoWatch( } export async function startCargoWatch( - context: vscode.ExtensionContext + context: vscode.ExtensionContext, ): Promise { const execPromise = util.promisify(child_process.exec); const { stderr, code = 0 } = await execPromise( - 'cargo watch --version' + 'cargo watch --version', ).catch(e => e); if (stderr.includes('no such subcommand: `watch`')) { @@ -171,7 +171,7 @@ export async function startCargoWatch( const install = await vscode.window.showInformationMessage( msg, 'yes', - 'no' + 'no', ); if (install !== 'yes') { return; @@ -192,20 +192,20 @@ export async function startCargoWatch( label, bin: 'cargo', args: ['install', 'cargo-watch'], - env: {} - }) + env: {}, + }), ); await taskFinished; const output = await execPromise('cargo watch --version').catch(e => e); if (output.stderr !== '') { vscode.window.showErrorMessage( - `Couldn't install \`cargo-\`watch: ${output.stderr}` + `Couldn't install \`cargo-\`watch: ${output.stderr}`, ); return; } } else if (code !== 0) { vscode.window.showErrorMessage( - `\`cargo watch\` failed with ${code}: ${stderr}` + `\`cargo watch\` failed with ${code}: ${stderr}`, ); return; } diff --git a/editors/code/src/commands/syntaxTree.ts b/editors/code/src/commands/syntaxTree.ts index 2f50fe14b3..89a80550ce 100644 --- a/editors/code/src/commands/syntaxTree.ts +++ b/editors/code/src/commands/syntaxTree.ts @@ -11,7 +11,7 @@ export class SyntaxTreeContentProvider public syntaxTree: string = 'Not available'; public provideTextDocumentContent( - uri: vscode.Uri + uri: vscode.Uri, ): vscode.ProviderResult { const editor = vscode.window.activeTextEditor; if (editor == null) { @@ -25,17 +25,17 @@ export class SyntaxTreeContentProvider range = editor.selection.isEmpty ? undefined : Server.client.code2ProtocolConverter.asRange( - editor.selection + editor.selection, ); } const request: SyntaxTreeParams = { textDocument: { uri: editor.document.uri.toString() }, - range + range, }; return Server.client.sendRequest( 'rust-analyzer/syntaxTree', - request + request, ); } @@ -70,7 +70,7 @@ export function createHandle(provider: SyntaxTreeContentProvider) { return vscode.window.showTextDocument( document, vscode.ViewColumn.Two, - true + true, ); }; } diff --git a/editors/code/src/commands/watch_status.ts b/editors/code/src/commands/watch_status.ts index 6c1f9041ba..8d64394c7b 100644 --- a/editors/code/src/commands/watch_status.ts +++ b/editors/code/src/commands/watch_status.ts @@ -13,7 +13,7 @@ export class StatusDisplay implements vscode.Disposable { constructor(command: string) { this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, - 10 + 10, ); this.command = command; this.statusBarItem.hide(); diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index fb9e55dd6f..2d3b6a54ea 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -33,14 +33,14 @@ export class Config { trace: 'off', arguments: '', command: '', - ignore: [] + ignore: [], }; private prevEnhancedTyping: null | boolean = null; constructor() { vscode.workspace.onDidChangeConfiguration(_ => - this.userConfigChanged() + this.userConfigChanged(), ); this.userConfigChanged(); } @@ -53,7 +53,7 @@ export class Config { if (config.has('rainbowHighlightingOn')) { this.rainbowHighlightingOn = config.get( - 'rainbowHighlightingOn' + 'rainbowHighlightingOn', ) as boolean; } @@ -63,7 +63,7 @@ export class Config { if (config.has('enableEnhancedTyping')) { this.enableEnhancedTyping = config.get( - 'enableEnhancedTyping' + 'enableEnhancedTyping', ) as boolean; if (this.prevEnhancedTyping === null) { @@ -78,12 +78,12 @@ export class Config { vscode.window .showInformationMessage( 'Changing enhanced typing setting requires a reload', - reloadAction + reloadAction, ) .then(selectedAction => { if (selectedAction === reloadAction) { vscode.commands.executeCommand( - 'workbench.action.reloadWindow' + 'workbench.action.reloadWindow', ); } }); @@ -104,28 +104,28 @@ export class Config { if (config.has('trace.cargo-watch')) { this.cargoWatchOptions.trace = config.get( 'trace.cargo-watch', - 'off' + 'off', ); } if (config.has('cargo-watch.arguments')) { this.cargoWatchOptions.arguments = config.get( 'cargo-watch.arguments', - '' + '', ); } if (config.has('cargo-watch.command')) { this.cargoWatchOptions.command = config.get( 'cargo-watch.command', - '' + '', ); } if (config.has('cargo-watch.ignore')) { this.cargoWatchOptions.ignore = config.get( 'cargo-watch.ignore', - [] + [], ); } @@ -138,7 +138,7 @@ export class Config { } if (config.has('maxInlayHintLength')) { this.maxInlayHintLength = config.get( - 'maxInlayHintLength' + 'maxInlayHintLength', ) as number; } if (config.has('excludeGlobs')) { diff --git a/editors/code/src/events/change_active_text_editor.ts b/editors/code/src/events/change_active_text_editor.ts index 64be562250..74b91bd487 100644 --- a/editors/code/src/events/change_active_text_editor.ts +++ b/editors/code/src/events/change_active_text_editor.ts @@ -3,7 +3,7 @@ import { TextDocumentIdentifier } from 'vscode-languageclient'; import { SyntaxTreeContentProvider, - syntaxTreeUri + syntaxTreeUri, } from '../commands/syntaxTree'; import { Decoration } from '../highlighting'; import { Server } from '../server'; @@ -21,11 +21,11 @@ export function makeHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { } const params: TextDocumentIdentifier = { - uri: editor.document.uri.toString() + uri: editor.document.uri.toString(), }; const decorations = await Server.client.sendRequest( 'rust-analyzer/decorationsRequest', - params + params, ); Server.highlighter.setHighlights(editor, decorations); }; diff --git a/editors/code/src/events/change_text_document.ts b/editors/code/src/events/change_text_document.ts index 89488bc61e..2e998e889b 100644 --- a/editors/code/src/events/change_text_document.ts +++ b/editors/code/src/events/change_text_document.ts @@ -2,7 +2,7 @@ import * as vscode from 'vscode'; import { SyntaxTreeContentProvider, - syntaxTreeUri + syntaxTreeUri, } from '../commands/syntaxTree'; export function createHandler(syntaxTreeProvider: SyntaxTreeContentProvider) { diff --git a/editors/code/src/extension.ts b/editors/code/src/extension.ts index a78aa3b425..815f3692c0 100644 --- a/editors/code/src/extension.ts +++ b/editors/code/src/extension.ts @@ -7,7 +7,7 @@ import { ExpandMacroContentProvider } from './commands/expand_macro'; import { HintsUpdater } from './commands/inlay_hints'; import { interactivelyStartCargoWatch, - startCargoWatch + startCargoWatch, } from './commands/runnables'; import { SyntaxTreeContentProvider } from './commands/syntaxTree'; import * as events from './events'; @@ -24,7 +24,7 @@ export async function activate(context: vscode.ExtensionContext) { } function overrideCommand( name: string, - f: (...args: any[]) => Promise + f: (...args: any[]) => Promise, ) { const defaultCmd = `default:${name}`; const original = (...args: any[]) => @@ -46,7 +46,7 @@ export async function activate(context: vscode.ExtensionContext) { }); } catch (_) { vscode.window.showWarningMessage( - 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings' + 'Enhanced typing feature is disabled because of incompatibility with VIM extension, consider turning off rust-analyzer.enableEnhancedTyping: https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/README.md#settings', ); } } @@ -54,14 +54,14 @@ export async function activate(context: vscode.ExtensionContext) { // Commands are requests from vscode to the language server registerCommand( 'rust-analyzer.analyzerStatus', - commands.analyzerStatus.makeCommand(context) + commands.analyzerStatus.makeCommand(context), ); registerCommand('rust-analyzer.collectGarbage', () => - Server.client.sendRequest('rust-analyzer/collectGarbage', null) + Server.client.sendRequest('rust-analyzer/collectGarbage', null), ); registerCommand( 'rust-analyzer.matchingBrace', - commands.matchingBrace.handle + commands.matchingBrace.handle, ); registerCommand('rust-analyzer.joinLines', commands.joinLines.handle); registerCommand('rust-analyzer.parentModule', commands.parentModule.handle); @@ -70,7 +70,7 @@ export async function activate(context: vscode.ExtensionContext) { registerCommand('rust-analyzer.runSingle', commands.runnables.handleSingle); registerCommand( 'rust-analyzer.applySourceChange', - commands.applySourceChange.handle + commands.applySourceChange.handle, ); registerCommand( 'rust-analyzer.showReferences', @@ -79,9 +79,9 @@ export async function activate(context: vscode.ExtensionContext) { 'editor.action.showReferences', vscode.Uri.parse(uri), Server.client.protocol2CodeConverter.asPosition(position), - locations.map(Server.client.protocol2CodeConverter.asLocation) + locations.map(Server.client.protocol2CodeConverter.asLocation), ); - } + }, ); if (Server.config.enableEnhancedTyping) { @@ -91,47 +91,47 @@ export async function activate(context: vscode.ExtensionContext) { // Notifications are events triggered by the language server const allNotifications: Iterable<[ string, - lc.GenericNotificationHandler + lc.GenericNotificationHandler, ]> = [ [ 'rust-analyzer/publishDecorations', - notifications.publishDecorations.handle - ] + notifications.publishDecorations.handle, + ], ]; const syntaxTreeContentProvider = new SyntaxTreeContentProvider(); const expandMacroContentProvider = new ExpandMacroContentProvider(); // The events below are plain old javascript events, triggered and handled by vscode vscode.window.onDidChangeActiveTextEditor( - events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider) + events.changeActiveTextEditor.makeHandler(syntaxTreeContentProvider), ); disposeOnDeactivation( vscode.workspace.registerTextDocumentContentProvider( 'rust-analyzer', - syntaxTreeContentProvider - ) + syntaxTreeContentProvider, + ), ); disposeOnDeactivation( vscode.workspace.registerTextDocumentContentProvider( 'rust-analyzer', - expandMacroContentProvider - ) + expandMacroContentProvider, + ), ); registerCommand( 'rust-analyzer.syntaxTree', - commands.syntaxTree.createHandle(syntaxTreeContentProvider) + commands.syntaxTree.createHandle(syntaxTreeContentProvider), ); registerCommand( 'rust-analyzer.expandMacro', - commands.expandMacro.createHandle(expandMacroContentProvider) + commands.expandMacro.createHandle(expandMacroContentProvider), ); vscode.workspace.onDidChangeTextDocument( events.changeTextDocument.createHandler(syntaxTreeContentProvider), null, - context.subscriptions + context.subscriptions, ); const startServer = () => Server.start(allNotifications); @@ -178,25 +178,25 @@ export async function activate(context: vscode.ExtensionContext) { editorChangeDisposable.dispose(); } return hintsUpdater.refreshHintsForVisibleEditors(); - } + }, ); disposeOnDeactivation( vscode.window.onDidChangeVisibleTextEditors(_ => - hintsUpdater.refreshHintsForVisibleEditors() - ) + hintsUpdater.refreshHintsForVisibleEditors(), + ), ); disposeOnDeactivation( vscode.workspace.onDidChangeTextDocument(e => - hintsUpdater.refreshHintsForVisibleEditors(e) - ) + hintsUpdater.refreshHintsForVisibleEditors(e), + ), ); disposeOnDeactivation( vscode.workspace.onDidChangeConfiguration(_ => hintsUpdater.toggleHintsDisplay( - Server.config.displayInlayHints - ) - ) + Server.config.displayInlayHints, + ), + ), ); }); } diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 48f2a2547d..6d50a2f2de 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -30,19 +30,19 @@ export class Highlighter { > { const decoration = ( tag: string, - textDecoration?: string + textDecoration?: string, ): [string, vscode.TextEditorDecorationType] => { const color = new vscode.ThemeColor('ralsp.' + tag); const decor = vscode.window.createTextEditorDecorationType({ color, - textDecoration + textDecoration, }); return [tag, decor]; }; const decorations: Iterable<[ string, - vscode.TextEditorDecorationType + vscode.TextEditorDecorationType, ]> = [ decoration('comment'), decoration('string'), @@ -61,7 +61,7 @@ export class Highlighter { decoration('variable'), decoration('variable.mut', 'underline'), decoration('field'), - decoration('module') + decoration('module'), ]; return new Map(decorations); @@ -118,20 +118,20 @@ export class Highlighter { colorfulIdents .get(d.bindingHash)![0] .push( - Server.client.protocol2CodeConverter.asRange(d.range) + Server.client.protocol2CodeConverter.asRange(d.range), ); } else { byTag .get(d.tag)! .push( - Server.client.protocol2CodeConverter.asRange(d.range) + Server.client.protocol2CodeConverter.asRange(d.range), ); } } for (const tag of byTag.keys()) { const dec = this.decorations.get( - tag + tag, ) as vscode.TextEditorDecorationType; const ranges = byTag.get(tag)!; editor.setDecorations(dec, ranges); @@ -141,7 +141,7 @@ export class Highlighter { const textDecoration = mut ? 'underline' : undefined; const dec = vscode.window.createTextEditorDecorationType({ light: { color: fancify(hash, 'light'), textDecoration }, - dark: { color: fancify(hash, 'dark'), textDecoration } + dark: { color: fancify(hash, 'dark'), textDecoration }, }); editor.setDecorations(dec, ranges); } diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 3180019b74..00ffb7776b 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -10,7 +10,7 @@ export interface PublishDecorationsParams { export function handle(params: PublishDecorationsParams) { const targetEditor = vscode.window.visibleTextEditors.find( - editor => editor.document.uri.toString() === params.uri + editor => editor.document.uri.toString() === params.uri, ); if (!Server.config.highlightingOn || !targetEditor) { return; diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index e767b6f1b0..2fe45f1ed6 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -19,7 +19,7 @@ export class Server { public static client: lc.LanguageClient; public static async start( - notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]> + notificationHandlers: Iterable<[string, lc.GenericNotificationHandler]>, ) { // '.' Is the fallback if no folder is open // TODO?: Workspace folders support Uri's (eg: file://test.txt). It might be a good idea to test if the uri points to a file. @@ -34,20 +34,20 @@ export class Server { if (platform() !== 'win32') { if (!(await lookpath(command))) { throw new Error( - `Cannot find rust-analyzer server \`${command}\` in PATH.` + `Cannot find rust-analyzer server \`${command}\` in PATH.`, ); } } const run: lc.Executable = { command, - options: { cwd: folder } + options: { cwd: folder }, }; const serverOptions: lc.ServerOptions = { run, - debug: run + debug: run, }; const traceOutputChannel = window.createOutputChannel( - 'Rust Analyzer Language Server Trace' + 'Rust Analyzer Language Server Trace', ); const clientOptions: lc.LanguageClientOptions = { documentSelector: [{ scheme: 'file', language: 'rust' }], @@ -58,16 +58,16 @@ export class Server { excludeGlobs: Server.config.excludeGlobs, useClientWatching: Server.config.useClientWatching, featureFlags: Server.config.featureFlags, - withSysroot: Server.config.withSysroot + withSysroot: Server.config.withSysroot, }, - traceOutputChannel + traceOutputChannel, }; Server.client = new lc.LanguageClient( 'rust-analyzer', 'Rust Analyzer Language Server', serverOptions, - clientOptions + clientOptions, ); // HACK: This is an awful way of filtering out the decorations notifications // However, pending proper support, this is the most effecitve approach @@ -80,10 +80,10 @@ export class Server { if (typeof messageOrDataObject === 'string') { if ( messageOrDataObject.includes( - 'rust-analyzer/publishDecorations' + 'rust-analyzer/publishDecorations', ) || messageOrDataObject.includes( - 'rust-analyzer/decorationsRequest' + 'rust-analyzer/decorationsRequest', ) ) { // Don't log publish decorations requests @@ -95,7 +95,7 @@ export class Server { // @ts-ignore Server.client.logObjectTrace(messageOrDataObject); } - } + }, }; Server.client.registerProposedFeatures(); Server.client.onReady().then(() => { diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts index 6c7f436f35..96ec8c614d 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts @@ -6,12 +6,12 @@ import SuggestedFix from '../../../utils/diagnostics/SuggestedFix'; const location1 = new vscode.Location( vscode.Uri.file('/file/1'), - new vscode.Range(new vscode.Position(1, 2), new vscode.Position(3, 4)) + new vscode.Range(new vscode.Position(1, 2), new vscode.Position(3, 4)), ); const location2 = new vscode.Location( vscode.Uri.file('/file/2'), - new vscode.Range(new vscode.Position(5, 6), new vscode.Position(7, 8)) + new vscode.Range(new vscode.Position(5, 6), new vscode.Position(7, 8)), ); describe('SuggestedFix', () => { @@ -20,13 +20,13 @@ describe('SuggestedFix', () => { const suggestion1 = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); const suggestion2 = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); assert(suggestion1.isEqual(suggestion2)); @@ -36,13 +36,13 @@ describe('SuggestedFix', () => { const suggestion1 = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); const suggestion2 = new SuggestedFix( 'Not the same title!', location1, - 'With this!' + 'With this!', ); assert(!suggestion1.isEqual(suggestion2)); @@ -52,13 +52,13 @@ describe('SuggestedFix', () => { const suggestion1 = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); const suggestion2 = new SuggestedFix( 'Replace me!', location1, - 'With something else!' + 'With something else!', ); assert(!suggestion1.isEqual(suggestion2)); @@ -68,13 +68,13 @@ describe('SuggestedFix', () => { const suggestion1 = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); const suggestion2 = new SuggestedFix( 'Replace me!', location2, - 'With this!' + 'With this!', ); assert(!suggestion1.isEqual(suggestion2)); @@ -85,14 +85,14 @@ describe('SuggestedFix', () => { 'Replace me!', location1, 'With this!', - SuggestionApplicability.MachineApplicable + SuggestionApplicability.MachineApplicable, ); const suggestion2 = new SuggestedFix( 'Replace me!', location2, 'With this!', - SuggestionApplicability.HasPlaceholders + SuggestionApplicability.HasPlaceholders, ); assert(!suggestion1.isEqual(suggestion2)); @@ -104,7 +104,7 @@ describe('SuggestedFix', () => { const suggestion = new SuggestedFix( 'Replace me!', location1, - 'With this!' + 'With this!', ); const codeAction = suggestion.toCodeAction(); diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts index f0328893e7..4c1467b576 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts @@ -8,20 +8,20 @@ const uri1 = vscode.Uri.file('/file/1'); const uri2 = vscode.Uri.file('/file/2'); const mockDocument1 = ({ - uri: uri1 + uri: uri1, } as unknown) as vscode.TextDocument; const mockDocument2 = ({ - uri: uri2 + uri: uri2, } as unknown) as vscode.TextDocument; const range1 = new vscode.Range( new vscode.Position(1, 2), - new vscode.Position(3, 4) + new vscode.Position(3, 4), ); const range2 = new vscode.Range( new vscode.Position(5, 6), - new vscode.Position(7, 8) + new vscode.Position(7, 8), ); const diagnostic1 = new vscode.Diagnostic(range1, 'First diagnostic'); @@ -32,7 +32,7 @@ function suggestion1(): SuggestedFix { return new SuggestedFix( 'Replace me!', new vscode.Location(uri1, range1), - 'With this!' + 'With this!', ); } @@ -44,7 +44,7 @@ describe('SuggestedFixCollection', () => { // Specify the document and range that exactly matches const codeActions = suggestedFixes.provideCodeActions( mockDocument1, - range1 + range1, ); assert.strictEqual(codeActions.length, 1); @@ -66,7 +66,7 @@ describe('SuggestedFixCollection', () => { const codeActions = suggestedFixes.provideCodeActions( mockDocument1, - range2 + range2, ); assert(!codeActions || codeActions.length === 0); @@ -78,7 +78,7 @@ describe('SuggestedFixCollection', () => { const codeActions = suggestedFixes.provideCodeActions( mockDocument2, - range1 + range1, ); assert(!codeActions || codeActions.length === 0); @@ -91,7 +91,7 @@ describe('SuggestedFixCollection', () => { const codeActions = suggestedFixes.provideCodeActions( mockDocument1, - range1 + range1, ); assert(!codeActions || codeActions.length === 0); @@ -106,7 +106,7 @@ describe('SuggestedFixCollection', () => { const codeActions = suggestedFixes.provideCodeActions( mockDocument1, - range1 + range1, ); assert.strictEqual(codeActions.length, 1); diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts index 327d15046f..cee59061f3 100644 --- a/editors/code/src/test/utils/diagnotics/rust.test.ts +++ b/editors/code/src/test/utils/diagnotics/rust.test.ts @@ -6,14 +6,14 @@ import { MappedRustDiagnostic, mapRustDiagnosticToVsCode, RustDiagnostic, - SuggestionApplicability + SuggestionApplicability, } from '../../../utils/diagnostics/rust'; function loadDiagnosticFixture(name: string): RustDiagnostic { const jsonText = fs .readFileSync( // We're actually in our JavaScript output directory, climb out - `${__dirname}/../../../../src/test/fixtures/rust-diagnostics/${name}.json` + `${__dirname}/../../../../src/test/fixtures/rust-diagnostics/${name}.json`, ) .toString(); @@ -33,12 +33,12 @@ function mapFixtureToVsCode(name: string): MappedRustDiagnostic { describe('mapRustDiagnosticToVsCode', () => { it('should map an incompatible type for trait error', () => { const { diagnostic, suggestedFixes } = mapFixtureToVsCode( - 'error/E0053' + 'error/E0053', ); assert.strictEqual( diagnostic.severity, - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert.strictEqual(diagnostic.source, 'rustc'); assert.strictEqual( @@ -46,8 +46,8 @@ describe('mapRustDiagnosticToVsCode', () => { [ `method \`next\` has an incompatible type for trait`, `expected type \`fn(&mut ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&ty::Ref>\``, - ` found type \`fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>\`` - ].join('\n') + ` found type \`fn(&ty::list_iter::ListIterator<'list, M>) -> std::option::Option<&'list ty::Ref>\``, + ].join('\n'), ); assert.strictEqual(diagnostic.code, 'E0053'); assert.deepStrictEqual(diagnostic.tags, []); @@ -61,24 +61,24 @@ describe('mapRustDiagnosticToVsCode', () => { it('should map an unused variable warning', () => { const { diagnostic, suggestedFixes } = mapFixtureToVsCode( - 'warning/unused_variables' + 'warning/unused_variables', ); assert.strictEqual( diagnostic.severity, - vscode.DiagnosticSeverity.Warning + vscode.DiagnosticSeverity.Warning, ); assert.strictEqual( diagnostic.message, [ 'unused variable: `foo`', - '#[warn(unused_variables)] on by default' - ].join('\n') + '#[warn(unused_variables)] on by default', + ].join('\n'), ); assert.strictEqual(diagnostic.code, 'unused_variables'); assert.strictEqual(diagnostic.source, 'rustc'); assert.deepStrictEqual(diagnostic.tags, [ - vscode.DiagnosticTag.Unnecessary + vscode.DiagnosticTag.Unnecessary, ]); // No related information @@ -89,29 +89,29 @@ describe('mapRustDiagnosticToVsCode', () => { const [suggestedFix] = suggestedFixes; assert.strictEqual( suggestedFix.title, - 'consider prefixing with an underscore: `_foo`' + 'consider prefixing with an underscore: `_foo`', ); assert.strictEqual( suggestedFix.applicability, - SuggestionApplicability.MachineApplicable + SuggestionApplicability.MachineApplicable, ); }); it('should map a wrong number of parameters error', () => { const { diagnostic, suggestedFixes } = mapFixtureToVsCode( - 'error/E0061' + 'error/E0061', ); assert.strictEqual( diagnostic.severity, - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert.strictEqual( diagnostic.message, [ 'this function takes 2 parameters but 3 parameters were supplied', - 'expected 2 parameters' - ].join('\n') + 'expected 2 parameters', + ].join('\n'), ); assert.strictEqual(diagnostic.code, 'E0061'); assert.strictEqual(diagnostic.source, 'rustc'); @@ -132,12 +132,12 @@ describe('mapRustDiagnosticToVsCode', () => { it('should map a Clippy copy pass by ref warning', () => { const { diagnostic, suggestedFixes } = mapFixtureToVsCode( - 'clippy/trivially_copy_pass_by_ref' + 'clippy/trivially_copy_pass_by_ref', ); assert.strictEqual( diagnostic.severity, - vscode.DiagnosticSeverity.Warning + vscode.DiagnosticSeverity.Warning, ); assert.strictEqual(diagnostic.source, 'clippy'); assert.strictEqual( @@ -145,8 +145,8 @@ describe('mapRustDiagnosticToVsCode', () => { [ 'this argument is passed by reference, but would be more efficient if passed by value', '#[warn(clippy::trivially_copy_pass_by_ref)] implied by #[warn(clippy::all)]', - 'for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref' - ].join('\n') + 'for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref', + ].join('\n'), ); assert.strictEqual(diagnostic.code, 'trivially_copy_pass_by_ref'); assert.deepStrictEqual(diagnostic.tags, []); @@ -165,27 +165,27 @@ describe('mapRustDiagnosticToVsCode', () => { const [suggestedFix] = suggestedFixes; assert.strictEqual( suggestedFix.title, - 'consider passing by value instead: `self`' + 'consider passing by value instead: `self`', ); // Clippy does not mark this with any applicability assert.strictEqual( suggestedFix.applicability, - SuggestionApplicability.Unspecified + SuggestionApplicability.Unspecified, ); }); it('should map a mismatched type error', () => { const { diagnostic, suggestedFixes } = mapFixtureToVsCode( - 'error/E0308' + 'error/E0308', ); assert.strictEqual( diagnostic.severity, - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert.strictEqual( diagnostic.message, - ['mismatched types', 'expected usize, found u32'].join('\n') + ['mismatched types', 'expected usize, found u32'].join('\n'), ); assert.strictEqual(diagnostic.code, 'E0308'); assert.strictEqual(diagnostic.source, 'rustc'); diff --git a/editors/code/src/test/utils/diagnotics/vscode.test.ts b/editors/code/src/test/utils/diagnotics/vscode.test.ts index 542dec1f54..4944dd0328 100644 --- a/editors/code/src/test/utils/diagnotics/vscode.test.ts +++ b/editors/code/src/test/utils/diagnotics/vscode.test.ts @@ -5,12 +5,12 @@ import { areDiagnosticsEqual } from '../../../utils/diagnostics/vscode'; const range1 = new vscode.Range( new vscode.Position(1, 2), - new vscode.Position(3, 4) + new vscode.Position(3, 4), ); const range2 = new vscode.Range( new vscode.Position(5, 6), - new vscode.Position(7, 8) + new vscode.Position(7, 8), ); describe('areDiagnosticsEqual', () => { @@ -18,13 +18,13 @@ describe('areDiagnosticsEqual', () => { const diagnostic1 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); const diagnostic2 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert(areDiagnosticsEqual(diagnostic1, diagnostic2)); @@ -34,14 +34,14 @@ describe('areDiagnosticsEqual', () => { const diagnostic1 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); diagnostic1.source = 'rustc'; const diagnostic2 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); diagnostic2.source = 'clippy'; @@ -52,13 +52,13 @@ describe('areDiagnosticsEqual', () => { const diagnostic1 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); const diagnostic2 = new vscode.Diagnostic( range2, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); @@ -68,13 +68,13 @@ describe('areDiagnosticsEqual', () => { const diagnostic1 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); const diagnostic2 = new vscode.Diagnostic( range1, 'Goodbye!, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); @@ -84,13 +84,13 @@ describe('areDiagnosticsEqual', () => { const diagnostic1 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Warning + vscode.DiagnosticSeverity.Warning, ); const diagnostic2 = new vscode.Diagnostic( range1, 'Hello, world!', - vscode.DiagnosticSeverity.Error + vscode.DiagnosticSeverity.Error, ); assert(!areDiagnosticsEqual(diagnostic1, diagnostic2)); diff --git a/editors/code/src/test/utils/index.ts b/editors/code/src/test/utils/index.ts index 16715a286c..9927daaf6a 100644 --- a/editors/code/src/test/utils/index.ts +++ b/editors/code/src/test/utils/index.ts @@ -17,7 +17,7 @@ import * as path from 'path'; export function run(): Promise { // Create the mocha test const mocha = new Mocha({ - ui: 'bdd' + ui: 'bdd', }); mocha.useColors(true); diff --git a/editors/code/src/utils/diagnostics/SuggestedFix.ts b/editors/code/src/utils/diagnostics/SuggestedFix.ts index b1be2a225b..6e660bb61d 100644 --- a/editors/code/src/utils/diagnostics/SuggestedFix.ts +++ b/editors/code/src/utils/diagnostics/SuggestedFix.ts @@ -24,7 +24,7 @@ export default class SuggestedFix { title: string, location: vscode.Location, replacement: string, - applicability: SuggestionApplicability = SuggestionApplicability.Unspecified + applicability: SuggestionApplicability = SuggestionApplicability.Unspecified, ) { this.title = title; this.location = location; @@ -51,7 +51,7 @@ export default class SuggestedFix { public toCodeAction(): vscode.CodeAction { const codeAction = new vscode.CodeAction( this.title, - vscode.CodeActionKind.QuickFix + vscode.CodeActionKind.QuickFix, ); const edit = new vscode.WorkspaceEdit(); diff --git a/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts index 132ce12f89..57c9856cfa 100644 --- a/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts +++ b/editors/code/src/utils/diagnostics/SuggestedFixCollection.ts @@ -38,13 +38,13 @@ export default class SuggestedFixCollection */ public addSuggestedFixForDiagnostic( suggestedFix: SuggestedFix, - diagnostic: vscode.Diagnostic + diagnostic: vscode.Diagnostic, ): void { const fileUriString = suggestedFix.location.uri.toString(); const fileSuggestions = this.suggestedFixes.get(fileUriString) || []; const existingSuggestion = fileSuggestions.find(s => - s.isEqual(suggestedFix) + s.isEqual(suggestedFix), ); if (existingSuggestion) { @@ -65,7 +65,7 @@ export default class SuggestedFixCollection */ public provideCodeActions( document: vscode.TextDocument, - range: vscode.Range + range: vscode.Range, ): vscode.CodeAction[] { const documentUriString = document.uri.toString(); diff --git a/editors/code/src/utils/diagnostics/rust.ts b/editors/code/src/utils/diagnostics/rust.ts index 0550d03724..b6efc0f564 100644 --- a/editors/code/src/utils/diagnostics/rust.ts +++ b/editors/code/src/utils/diagnostics/rust.ts @@ -7,7 +7,7 @@ export enum SuggestionApplicability { MachineApplicable = 'MachineApplicable', HasPlaceholders = 'HasPlaceholders', MaybeIncorrect = 'MaybeIncorrect', - Unspecified = 'Unspecified' + Unspecified = 'Unspecified', } // Reference: @@ -69,7 +69,7 @@ function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { const range = new vscode.Range( new vscode.Position(span.line_start - 1, span.column_start - 1), - new vscode.Position(span.line_end - 1, span.column_end - 1) + new vscode.Position(span.line_end - 1, span.column_end - 1), ); return new vscode.Location(fileUri, range); @@ -81,7 +81,7 @@ function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { * If the span is unlabelled this will return `undefined`. */ function mapSecondarySpanToRelated( - span: RustDiagnosticSpan + span: RustDiagnosticSpan, ): vscode.DiagnosticRelatedInformation | undefined { if (!span.label) { // Nothing to label this with @@ -107,7 +107,7 @@ function isUnusedOrUnnecessary(rd: RustDiagnostic): boolean { 'unused_attributes', 'unused_imports', 'unused_macros', - 'unused_variables' + 'unused_variables', ].includes(rd.code.code); } @@ -157,13 +157,13 @@ function mapRustChildDiagnostic(rd: RustDiagnostic): MappedRustChildDiagnostic { title, location, span.suggested_replacement, - span.suggestion_applicability - ) + span.suggestion_applicability, + ), }; } else { const related = new vscode.DiagnosticRelatedInformation( location, - rd.message + rd.message, ); return { related }; @@ -183,7 +183,7 @@ function mapRustChildDiagnostic(rd: RustDiagnostic): MappedRustChildDiagnostic { * If the diagnostic has no primary span this will return `undefined` */ export function mapRustDiagnosticToVsCode( - rd: RustDiagnostic + rd: RustDiagnostic, ): MappedRustDiagnostic | undefined { const primarySpan = rd.spans.find(s => s.is_primary); if (!primarySpan) { @@ -223,7 +223,7 @@ export function mapRustDiagnosticToVsCode( const suggestedFixes = []; for (const child of rd.children) { const { related, suggestedFix, messageLine } = mapRustChildDiagnostic( - child + child, ); if (related) { @@ -256,6 +256,6 @@ export function mapRustDiagnosticToVsCode( return { location, diagnostic: vd, - suggestedFixes + suggestedFixes, }; } diff --git a/editors/code/src/utils/diagnostics/vscode.ts b/editors/code/src/utils/diagnostics/vscode.ts index d8b85b7200..f4a5450e2b 100644 --- a/editors/code/src/utils/diagnostics/vscode.ts +++ b/editors/code/src/utils/diagnostics/vscode.ts @@ -3,7 +3,7 @@ import * as vscode from 'vscode'; /** Compares two `vscode.Diagnostic`s for equality */ export function areDiagnosticsEqual( left: vscode.Diagnostic, - right: vscode.Diagnostic + right: vscode.Diagnostic, ): boolean { return ( left.source === right.source && diff --git a/editors/code/src/utils/processes.ts b/editors/code/src/utils/processes.ts index da8be9eb17..a1d6b7eafb 100644 --- a/editors/code/src/utils/processes.ts +++ b/editors/code/src/utils/processes.ts @@ -22,7 +22,7 @@ export function terminate(process: ChildProcess, cwd?: string): boolean { // Ignore stderr since this is otherwise piped to parent.stderr // which might be already closed. const options: any = { - stdio: ['pipe', 'pipe', 'ignore'] + stdio: ['pipe', 'pipe', 'ignore'], }; if (cwd) { options.cwd = cwd; @@ -30,7 +30,7 @@ export function terminate(process: ChildProcess, cwd?: string): boolean { cp.execFileSync( 'taskkill', ['/T', '/F', '/PID', process.pid.toString()], - options + options, ); return true; } catch (err) { From 16df4d8fcbf6695d8b033efe2dcaa5167629d9c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?= Date: Mon, 9 Dec 2019 22:35:47 +0200 Subject: [PATCH 118/312] chore: bump deps and use mainline chalk --- Cargo.lock | 111 ++++++++++++++---------------------- crates/ra_hir_ty/Cargo.toml | 6 +- 2 files changed, 47 insertions(+), 70 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d80e585482..caa52fb69d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -53,7 +53,7 @@ name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -112,12 +112,12 @@ dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -128,7 +128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chalk-derive" version = "0.1.0" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -138,28 +138,27 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.9.0" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ - "chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chalk-ir" version = "0.1.0" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-engine 0.9.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chalk-macros" version = "0.1.1" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -167,24 +166,24 @@ dependencies = [ [[package]] name = "chalk-rust-ir" version = "0.1.0" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-engine 0.9.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", ] [[package]] name = "chalk-solve" version = "0.1.0" -source = "git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30#095cd38a4f16337913bba487f2055b9ca0179f30" +source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-engine 0.9.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-rust-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -493,7 +492,7 @@ dependencies = [ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -534,7 +533,7 @@ name = "jemalloc-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "fs_extra 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -616,7 +615,7 @@ dependencies = [ "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -626,7 +625,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -669,7 +668,7 @@ dependencies = [ [[package]] name = "mio-extras" -version = "2.0.5" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -712,7 +711,7 @@ dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -845,14 +844,6 @@ dependencies = [ "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "psm" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "quick-error" version = "1.2.2" @@ -1002,9 +993,9 @@ name = "ra_hir_ty" version = "0.1.0" dependencies = [ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-rust-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", - "chalk-solve 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1069,7 +1060,7 @@ dependencies = [ "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1117,7 +1108,7 @@ dependencies = [ "ra_db 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1510,7 +1501,7 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1557,18 +1548,6 @@ dependencies = [ "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "stacker" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "psm 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "superslice" version = "1.0.0" @@ -1610,7 +1589,7 @@ name = "test_utils" version = "0.1.0" dependencies = [ "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "text_unit 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1798,14 +1777,14 @@ dependencies = [ "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" -"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chalk-derive 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chalk-engine 0.9.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chalk-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chalk-macros 0.1.1 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chalk-rust-ir 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" -"checksum chalk-solve 0.1.0 (git+https://github.com/jackh726/chalk.git?rev=095cd38a4f16337913bba487f2055b9ca0179f30)" = "" +"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" @@ -1865,7 +1844,7 @@ dependencies = [ "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" @@ -1884,7 +1863,6 @@ dependencies = [ "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum proptest 0.9.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf147e022eacf0c8a054ab864914a7602618adba841d800a9a9868a5237a529f" -"checksum psm 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b14fc68b454f875abc8354c2555e1d56596f74833ddc0f77f87f4871ed6a30e0" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum ra_vfs 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bc898f237e4b4498959ae0100c688793a23e77624d44ef710ba70094217f98e0" @@ -1926,13 +1904,12 @@ dependencies = [ "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" -"checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" +"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" -"checksum stacker 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d96fc4f13a0ac088e9a3cd9af1cc8c5cc1ab5deb2145cef661267dfc9c542f8a" "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 429242870f..d277bf2bcd 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml @@ -22,9 +22,9 @@ ra_syntax = { path = "../ra_syntax" } test_utils = { path = "../test_utils" } # https://github.com/rust-lang/chalk/pull/294 -chalk-solve = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" } -chalk-rust-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" } -chalk-ir = { git = "https://github.com/jackh726/chalk.git", rev = "095cd38a4f16337913bba487f2055b9ca0179f30" } +chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } +chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } lalrpop-intern = "0.15.1" From d89996fd5bf9ca8111f6a45ff59a0f43b3b9836a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 10 Dec 2019 13:52:04 +0100 Subject: [PATCH 119/312] Build correct SourceAnalyzer for traits --- crates/ra_hir/src/source_binder.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 44d1850038..d3cc5c423e 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -62,6 +62,10 @@ fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) - let src = node.with_value(it); Some(ImplBlock::from_source(db, src)?.id.resolver(db)) }, + ast::TraitDef(it) => { + let src = node.with_value(it); + Some(Trait::from_source(db, src)?.id.resolver(db)) + }, _ => match node.value.kind() { FN_DEF | CONST_DEF | STATIC_DEF => { let def = def_with_body_from_child_node(db, node)?; @@ -411,20 +415,6 @@ impl SourceAnalyzer { ) } - // pub fn autoderef<'a>( - // &'a self, - // db: &'a impl HirDatabase, - // ty: Ty, - // ) -> impl Iterator + 'a { - // // There should be no inference vars in types passed here - // // FIXME check that? - // let canonical = Canonical { value: ty, num_vars: 0 }; - // let krate = self.resolver.krate(); - // let environment = TraitEnvironment::lower(db, &self.resolver); - // let ty = crate::ty::InEnvironment { value: canonical, environment }; - // crate::ty::autoderef(db, krate, ty).map(|canonical| canonical.value) - // } - /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool { From 20ccabc01de7306f44e0b2a460152f0c97f19d76 Mon Sep 17 00:00:00 2001 From: Gabriel Luo Date: Tue, 10 Dec 2019 22:18:05 -0500 Subject: [PATCH 120/312] Fixed #2250 Tuple in type annotation expands correctly; Expansion will prefer the following delimiter when possible. New regression tests added to verify the consistency between tuple expansion in type annotation and tuple expansion in rvalue. --- crates/ra_ide/src/extend_selection.rs | 78 ++++++++++++++++++++++----- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index 4b7bfc0b11..c096ca6ae4 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs @@ -34,6 +34,7 @@ fn try_extend_selection(root: &SyntaxNode, range: TextRange) -> Option Option { TYPE_BOUND => T![+], _ => T![,], }; - if let Some(delimiter_node) = nearby_delimiter(delimiter, node, Direction::Prev) { - return Some(TextRange::from_to( - delimiter_node.text_range().start(), - node.text_range().end(), - )); - } + if let Some(delimiter_node) = nearby_delimiter(delimiter, node, Direction::Next) { // Include any following whitespace when delimiter is after list item. let final_node = delimiter_node @@ -190,6 +186,12 @@ fn extend_list_item(node: &SyntaxNode) -> Option { return Some(TextRange::from_to(node.text_range().start(), final_node.text_range().end())); } + if let Some(delimiter_node) = nearby_delimiter(delimiter, node, Direction::Prev) { + return Some(TextRange::from_to( + delimiter_node.text_range().start(), + node.text_range().end(), + )); + } None } @@ -250,14 +252,14 @@ mod tests { fn test_extend_selection_list() { do_check(r#"fn foo(<|>x: i32) {}"#, &["x", "x: i32"]); do_check(r#"fn foo(<|>x: i32, y: i32) {}"#, &["x", "x: i32", "x: i32, "]); - do_check(r#"fn foo(<|>x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,"]); + do_check(r#"fn foo(<|>x: i32,y: i32) {}"#, &["x", "x: i32", "x: i32,", "(x: i32,y: i32)"]); do_check(r#"fn foo(x: i32, <|>y: i32) {}"#, &["y", "y: i32", ", y: i32"]); - do_check(r#"fn foo(x: i32, <|>y: i32, ) {}"#, &["y", "y: i32", ", y: i32"]); + do_check(r#"fn foo(x: i32, <|>y: i32, ) {}"#, &["y", "y: i32", "y: i32, "]); do_check(r#"fn foo(x: i32,<|>y: i32) {}"#, &["y", "y: i32", ",y: i32"]); do_check(r#"const FOO: [usize; 2] = [ 22<|> , 33];"#, &["22", "22 , "]); do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|>];"#, &["33", ", 33"]); - do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#, &["33", ", 33"]); + do_check(r#"const FOO: [usize; 2] = [ 22 , 33<|> ,];"#, &["33", "33 ,", "[ 22 , 33 ,]"]); do_check(r#"fn main() { (1, 2<|>) }"#, &["2", ", 2", "(1, 2)"]); @@ -276,7 +278,7 @@ const FOO: [usize; 2] = [ 22 , 33<|>, ]"#, - &["33", ", 33"], + &["33", "33,"], ); } @@ -424,7 +426,7 @@ fn foo() do_check(r#"fn foo() where T: <|>Copy +Display"#, &["Copy", "Copy +"]); do_check(r#"fn foo() where T: <|>Copy+Display"#, &["Copy", "Copy+"]); do_check(r#"fn foo() where T: Copy + <|>Display"#, &["Display", "+ Display"]); - do_check(r#"fn foo() where T: Copy + <|>Display + Sync"#, &["Display", "+ Display"]); + do_check(r#"fn foo() where T: Copy + <|>Display + Sync"#, &["Display", "Display + "]); do_check(r#"fn foo() where T: Copy +<|>Display"#, &["Display", "+Display"]); } @@ -435,7 +437,7 @@ fn foo() do_check(r#"fn fooCopy +Display>() {}"#, &["Copy", "Copy +"]); do_check(r#"fn fooCopy+Display>() {}"#, &["Copy", "Copy+"]); do_check(r#"fn fooDisplay>() {}"#, &["Display", "+ Display"]); - do_check(r#"fn fooDisplay + Sync>() {}"#, &["Display", "+ Display"]); + do_check(r#"fn fooDisplay + Sync>() {}"#, &["Display", "Display + "]); do_check(r#"fn fooDisplay>() {}"#, &["Display", "+Display"]); do_check( r#"fn foo + Display, U: Copy>() {}"#, @@ -449,4 +451,56 @@ fn foo() ], ); } + + #[test] + fn test_extend_selection_on_tuple_in_type() { + do_check( + r#"fn main() { let _: (krate, <|>_crate_def_map, module_id) = (); }"#, + &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], + ); + // white space variations + do_check( + r#"fn main() { let _: (krate,<|>_crate_def_map,module_id) = (); }"#, + &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], + ); + do_check( + r#" +fn main() { let _: ( + krate, + _crate<|>_def_map, + module_id +) = (); }"#, + &[ + "_crate_def_map", + "_crate_def_map,", + "(\n krate,\n _crate_def_map,\n module_id\n)", + ], + ); + } + + #[test] + fn test_extend_selection_on_tuple_in_rvalue() { + do_check( + r#"fn main() { let var = (krate, _crate_def_map<|>, module_id); }"#, + &["_crate_def_map", "_crate_def_map, ", "(krate, _crate_def_map, module_id)"], + ); + // white space variations + do_check( + r#"fn main() { let var = (krate,_crate<|>_def_map,module_id); }"#, + &["_crate_def_map", "_crate_def_map,", "(krate,_crate_def_map,module_id)"], + ); + do_check( + r#" +fn main() { let var = ( + krate, + _crate_def_map<|>, + module_id +); }"#, + &[ + "_crate_def_map", + "_crate_def_map,", + "(\n krate,\n _crate_def_map,\n module_id\n)", + ], + ); + } } From b186c612c4210363929e77409149c1e5d902f647 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Wed, 11 Dec 2019 22:40:26 +0900 Subject: [PATCH 121/312] Use ES2018 for vscode extension Today's latest vscode v1.40 (Node.jsv12.4/V8 v7.6) supports ES2018 features natively. We don't have to transform codes to ES6. --- editors/code/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index 9ad2e967b2..8cb1e90351 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -1,9 +1,9 @@ { "compilerOptions": { "module": "commonjs", - "target": "es6", + "target": "es2018", "outDir": "out", - "lib": ["es6"], + "lib": ["es2018"], "sourceMap": true, "rootDir": "src", "strict": true, From fcccf8ec59420d20edc53f7d787f2412e297f5fe Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 11 Dec 2019 09:11:55 -0500 Subject: [PATCH 122/312] Support LSP 3.15 This merely upgrades our protocol support. It does not add any of the new features. --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 7 ++++++- crates/ra_lsp_server/src/main_loop.rs | 3 ++- .../ra_lsp_server/src/main_loop/handlers.rs | 5 ++++- .../ra_lsp_server/tests/heavy_tests/main.rs | 21 ++++++++++++++++++- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caa52fb69d..3c567376e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.61.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" +"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 41672eaffe..c50cb8031d 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.61.0", features = ["proposed"] } +lsp-types = { version = "0.63.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index eea0965edb..4cb259360b 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -5,7 +5,7 @@ use lsp_types::{ DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, + TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, }; pub fn server_capabilities() -> ServerCapabilities { @@ -21,10 +21,14 @@ pub fn server_capabilities() -> ServerCapabilities { completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: Some(vec![":".to_string(), ".".to_string()]), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), + retrigger_characters: None, + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), + declaration_provider: None, definition_provider: Some(true), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), @@ -44,6 +48,7 @@ pub fn server_capabilities() -> ServerCapabilities { folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), document_link_provider: None, color_provider: None, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 83845f1e00..158cac0be1 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -520,7 +520,8 @@ fn on_notification( if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { subs.remove_sub(FileId(file_id.0)); } - let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; + let params = + req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; let not = notification_new::(params); msg_sender.send(not.into()).unwrap(); return Ok(()); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 4095836344..5b64b27cd2 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -648,6 +648,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -670,6 +671,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -828,9 +830,10 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, + tags: None, }) .collect(); - Ok(req::PublishDiagnosticsParams { uri, diagnostics }) + Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) } pub fn publish_decorations( diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index cfbf16ea5f..dff63a12d4 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -4,7 +4,8 @@ use std::{collections::HashMap, time::Instant}; use lsp_types::{ CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, - Position, Range, TextDocumentItem, TextDocumentPositionParams, + PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, + WorkDoneProgressParams, }; use ra_lsp_server::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, @@ -48,6 +49,8 @@ use std::collections::Spam; Position::new(0, 23), ), context: None, + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }); assert!(format!("{}", res).contains("HashMap")); eprintln!("completion took {:?}", completion_start.elapsed()); @@ -211,8 +214,12 @@ pub use std::collections::HashMap; options: FormattingOptions { tab_size: 4, insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, properties: HashMap::new(), }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -272,7 +279,11 @@ pub use std::collections::HashMap; tab_size: 4, insert_spaces: false, properties: HashMap::new(), + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -325,6 +336,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -356,6 +369,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); @@ -404,6 +419,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -435,6 +452,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); From b21bb44c8dcd43e9e42ef7e3d752dd550e6505ad Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Thu, 12 Dec 2019 00:41:16 +0900 Subject: [PATCH 123/312] Enable noUnusedParameters option for vscode extension --- editors/code/src/commands/analyzer_status.ts | 2 +- editors/code/src/commands/expand_macro.ts | 2 +- editors/code/src/commands/runnables.ts | 2 +- editors/code/tsconfig.json | 3 ++- editors/code/tslint.json | 4 +++- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/editors/code/src/commands/analyzer_status.ts b/editors/code/src/commands/analyzer_status.ts index 9e4ce0eb3c..2777ced247 100644 --- a/editors/code/src/commands/analyzer_status.ts +++ b/editors/code/src/commands/analyzer_status.ts @@ -9,7 +9,7 @@ export class TextDocumentContentProvider public syntaxTree: string = 'Not available'; public provideTextDocumentContent( - uri: vscode.Uri, + _uri: vscode.Uri, ): vscode.ProviderResult { const editor = vscode.window.activeTextEditor; if (editor == null) { diff --git a/editors/code/src/commands/expand_macro.ts b/editors/code/src/commands/expand_macro.ts index 842898020b..17c78280a8 100644 --- a/editors/code/src/commands/expand_macro.ts +++ b/editors/code/src/commands/expand_macro.ts @@ -11,7 +11,7 @@ export class ExpandMacroContentProvider public eventEmitter = new vscode.EventEmitter(); public provideTextDocumentContent( - uri: vscode.Uri, + _uri: vscode.Uri, ): vscode.ProviderResult { async function handle() { const editor = vscode.window.activeTextEditor; diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index 9b1c6643d4..c81d7ce0f0 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts @@ -178,7 +178,7 @@ export async function startCargoWatch( } const label = 'install-cargo-watch'; - const taskFinished = new Promise((resolve, reject) => { + const taskFinished = new Promise((resolve, _reject) => { const disposable = vscode.tasks.onDidEndTask(({ execution }) => { if (execution.task.name === label) { disposable.dispose(); diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index 8cb1e90351..9ddf563475 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -7,7 +7,8 @@ "sourceMap": true, "rootDir": "src", "strict": true, - "noUnusedLocals": true + "noUnusedLocals": true, + "noUnusedParameters": true }, "exclude": ["node_modules", ".vscode-test"] } diff --git a/editors/code/tslint.json b/editors/code/tslint.json index bdeb4895ee..b69c5574d2 100644 --- a/editors/code/tslint.json +++ b/editors/code/tslint.json @@ -4,6 +4,8 @@ "rules": { "quotemark": [true, "single"], "interface-name": false, - "object-literal-sort-keys": false + "object-literal-sort-keys": false, + // Allow `_bar` to sort with tsc's `noUnusedParameters` option + "variable-name": [true, "allow-leading-underscore"] } } From 0e9cabab3fb4c15fb1b88e62a35ccf1ea52ef853 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Thu, 12 Dec 2019 00:49:54 +0900 Subject: [PATCH 124/312] Enable noImplicitReturns option for vscode extension --- editors/code/src/commands/runnables.ts | 14 ++++++++------ .../src/test/utils/diagnotics/SuggestedFix.test.ts | 3 ++- .../diagnotics/SuggestedFixCollection.test.ts | 6 ++++-- .../code/src/test/utils/diagnotics/rust.test.ts | 6 ++++-- editors/code/tsconfig.json | 3 ++- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/editors/code/src/commands/runnables.ts b/editors/code/src/commands/runnables.ts index c81d7ce0f0..cf980e2578 100644 --- a/editors/code/src/commands/runnables.ts +++ b/editors/code/src/commands/runnables.ts @@ -73,7 +73,7 @@ function createTask(spec: Runnable): vscode.Task { } let prevRunnable: RunnableQuickPick | undefined; -export async function handle() { +export async function handle(): Promise { const editor = vscode.window.activeTextEditor; if (editor == null || editor.document.languageId !== 'rust') { return; @@ -105,12 +105,14 @@ export async function handle() { items.push(new RunnableQuickPick(r)); } const item = await vscode.window.showQuickPick(items); - if (item) { - item.detail = 'rerun'; - prevRunnable = item; - const task = createTask(item.runnable); - return await vscode.tasks.executeTask(task); + if (!item) { + return; } + + item.detail = 'rerun'; + prevRunnable = item; + const task = createTask(item.runnable); + return await vscode.tasks.executeTask(task); } export async function handleSingle(runnable: Runnable) { diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts index 96ec8c614d..2b25eb705d 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFix.test.ts @@ -114,7 +114,8 @@ describe('SuggestedFix', () => { const edit = codeAction.edit; if (!edit) { - return assert.fail('Code Action edit unexpectedly missing'); + assert.fail('Code Action edit unexpectedly missing'); + return; } const editEntries = edit.entries(); diff --git a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts index 4c1467b576..ef09013f41 100644 --- a/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts +++ b/editors/code/src/test/utils/diagnotics/SuggestedFixCollection.test.ts @@ -53,7 +53,8 @@ describe('SuggestedFixCollection', () => { const { diagnostics } = codeAction; if (!diagnostics) { - return assert.fail('Diagnostics unexpectedly missing'); + assert.fail('Diagnostics unexpectedly missing'); + return; } assert.strictEqual(diagnostics.length, 1); @@ -114,7 +115,8 @@ describe('SuggestedFixCollection', () => { const { diagnostics } = codeAction; if (!diagnostics) { - return assert.fail('Diagnostics unexpectedly missing'); + assert.fail('Diagnostics unexpectedly missing'); + return; } // We should be associated with both diagnostics diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts index cee59061f3..0222dbbaa0 100644 --- a/editors/code/src/test/utils/diagnotics/rust.test.ts +++ b/editors/code/src/test/utils/diagnotics/rust.test.ts @@ -120,7 +120,8 @@ describe('mapRustDiagnosticToVsCode', () => { // One related information for the original definition const relatedInformation = diagnostic.relatedInformation; if (!relatedInformation) { - return assert.fail('Related information unexpectedly undefined'); + assert.fail('Related information unexpectedly undefined'); + return; } assert.strictEqual(relatedInformation.length, 1); const [related] = relatedInformation; @@ -154,7 +155,8 @@ describe('mapRustDiagnosticToVsCode', () => { // One related information for the lint definition const relatedInformation = diagnostic.relatedInformation; if (!relatedInformation) { - return assert.fail('Related information unexpectedly undefined'); + assert.fail('Related information unexpectedly undefined'); + return; } assert.strictEqual(relatedInformation.length, 1); const [related] = relatedInformation; diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index 9ddf563475..f0fd2354cb 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -8,7 +8,8 @@ "rootDir": "src", "strict": true, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "noImplicitReturns": true }, "exclude": ["node_modules", ".vscode-test"] } From f0f259bda32a3cf04f45cea946b5d12368454342 Mon Sep 17 00:00:00 2001 From: Tetsuharu OHZEKI Date: Thu, 12 Dec 2019 00:51:28 +0900 Subject: [PATCH 125/312] Enable noFallthroughCasesInSwitch option for vscode extension --- editors/code/tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/editors/code/tsconfig.json b/editors/code/tsconfig.json index f0fd2354cb..5e11c37751 100644 --- a/editors/code/tsconfig.json +++ b/editors/code/tsconfig.json @@ -9,7 +9,8 @@ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, - "noImplicitReturns": true + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true }, "exclude": ["node_modules", ".vscode-test"] } From 712700d8e027b108f9c4f8fa9acc2f25e453b6d1 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 11 Dec 2019 09:11:55 -0500 Subject: [PATCH 126/312] Support LSP 3.15 This merely upgrades our protocol support. It does not add any of the new features. --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 7 ++++++- crates/ra_lsp_server/src/main_loop.rs | 3 ++- .../ra_lsp_server/src/main_loop/handlers.rs | 5 ++++- .../ra_lsp_server/tests/heavy_tests/main.rs | 21 ++++++++++++++++++- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caa52fb69d..3c567376e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.61.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" +"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 41672eaffe..c50cb8031d 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.61.0", features = ["proposed"] } +lsp-types = { version = "0.63.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index eea0965edb..4cb259360b 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -5,7 +5,7 @@ use lsp_types::{ DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, + TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, }; pub fn server_capabilities() -> ServerCapabilities { @@ -21,10 +21,14 @@ pub fn server_capabilities() -> ServerCapabilities { completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: Some(vec![":".to_string(), ".".to_string()]), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), + retrigger_characters: None, + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), + declaration_provider: None, definition_provider: Some(true), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), @@ -44,6 +48,7 @@ pub fn server_capabilities() -> ServerCapabilities { folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), document_link_provider: None, color_provider: None, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 83845f1e00..158cac0be1 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -520,7 +520,8 @@ fn on_notification( if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { subs.remove_sub(FileId(file_id.0)); } - let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; + let params = + req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; let not = notification_new::(params); msg_sender.send(not.into()).unwrap(); return Ok(()); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 4095836344..5b64b27cd2 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -648,6 +648,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -670,6 +671,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -828,9 +830,10 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, + tags: None, }) .collect(); - Ok(req::PublishDiagnosticsParams { uri, diagnostics }) + Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) } pub fn publish_decorations( diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index cfbf16ea5f..dff63a12d4 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -4,7 +4,8 @@ use std::{collections::HashMap, time::Instant}; use lsp_types::{ CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, - Position, Range, TextDocumentItem, TextDocumentPositionParams, + PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, + WorkDoneProgressParams, }; use ra_lsp_server::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, @@ -48,6 +49,8 @@ use std::collections::Spam; Position::new(0, 23), ), context: None, + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }); assert!(format!("{}", res).contains("HashMap")); eprintln!("completion took {:?}", completion_start.elapsed()); @@ -211,8 +214,12 @@ pub use std::collections::HashMap; options: FormattingOptions { tab_size: 4, insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, properties: HashMap::new(), }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -272,7 +279,11 @@ pub use std::collections::HashMap; tab_size: 4, insert_spaces: false, properties: HashMap::new(), + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -325,6 +336,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -356,6 +369,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); @@ -404,6 +419,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -435,6 +452,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); From 58768b2a6343451bae8c4efb93ce7b1d598c914d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 11 Dec 2019 17:37:32 +0100 Subject: [PATCH 127/312] Revert "Support LSP 3.15" This reverts commit fcccf8ec59420d20edc53f7d787f2412e297f5fe. This causes rust-analyzer die immediatelly after startup --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 7 +------ crates/ra_lsp_server/src/main_loop.rs | 3 +-- .../ra_lsp_server/src/main_loop/handlers.rs | 5 +---- .../ra_lsp_server/tests/heavy_tests/main.rs | 21 +------------------ 6 files changed, 8 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c567376e4..caa52fb69d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.63.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" +"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index c50cb8031d..41672eaffe 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.63.0", features = ["proposed"] } +lsp-types = { version = "0.61.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 4cb259360b..eea0965edb 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -5,7 +5,7 @@ use lsp_types::{ DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, + TextDocumentSyncOptions, TypeDefinitionProviderCapability, }; pub fn server_capabilities() -> ServerCapabilities { @@ -21,14 +21,10 @@ pub fn server_capabilities() -> ServerCapabilities { completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: Some(vec![":".to_string(), ".".to_string()]), - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), - retrigger_characters: None, - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), - declaration_provider: None, definition_provider: Some(true), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), @@ -48,7 +44,6 @@ pub fn server_capabilities() -> ServerCapabilities { folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), document_link_provider: None, color_provider: None, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 158cac0be1..83845f1e00 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -520,8 +520,7 @@ fn on_notification( if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { subs.remove_sub(FileId(file_id.0)); } - let params = - req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; + let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; let not = notification_new::(params); msg_sender.send(not.into()).unwrap(); return Ok(()); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5b64b27cd2..4095836344 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -648,7 +648,6 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), - is_preferred: None, }; res.push(action.into()); } @@ -671,7 +670,6 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), - is_preferred: None, }; res.push(action.into()); } @@ -830,10 +828,9 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, - tags: None, }) .collect(); - Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) + Ok(req::PublishDiagnosticsParams { uri, diagnostics }) } pub fn publish_decorations( diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index dff63a12d4..cfbf16ea5f 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -4,8 +4,7 @@ use std::{collections::HashMap, time::Instant}; use lsp_types::{ CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, - PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, - WorkDoneProgressParams, + Position, Range, TextDocumentItem, TextDocumentPositionParams, }; use ra_lsp_server::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, @@ -49,8 +48,6 @@ use std::collections::Spam; Position::new(0, 23), ), context: None, - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }); assert!(format!("{}", res).contains("HashMap")); eprintln!("completion took {:?}", completion_start.elapsed()); @@ -214,12 +211,8 @@ pub use std::collections::HashMap; options: FormattingOptions { tab_size: 4, insert_spaces: false, - insert_final_newline: None, - trim_final_newlines: None, - trim_trailing_whitespace: None, properties: HashMap::new(), }, - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -279,11 +272,7 @@ pub use std::collections::HashMap; tab_size: 4, insert_spaces: false, properties: HashMap::new(), - insert_final_newline: None, - trim_final_newlines: None, - trim_trailing_whitespace: None, }, - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -336,8 +325,6 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -369,8 +356,6 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); @@ -419,8 +404,6 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -452,8 +435,6 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); From 1e0bf205eff81f04c0e1e6c208c3489327520c3f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 11 Dec 2019 18:27:34 +0100 Subject: [PATCH 128/312] Revert "Support LSP 3.15" This reverts commit 712700d8e027b108f9c4f8fa9acc2f25e453b6d1. --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 7 +------ crates/ra_lsp_server/src/main_loop.rs | 3 +-- .../ra_lsp_server/src/main_loop/handlers.rs | 5 +---- .../ra_lsp_server/tests/heavy_tests/main.rs | 21 +------------------ 6 files changed, 8 insertions(+), 36 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c567376e4..caa52fb69d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.63.0" +version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" +"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index c50cb8031d..41672eaffe 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.63.0", features = ["proposed"] } +lsp-types = { version = "0.61.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 4cb259360b..eea0965edb 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -5,7 +5,7 @@ use lsp_types::{ DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, + TextDocumentSyncOptions, TypeDefinitionProviderCapability, }; pub fn server_capabilities() -> ServerCapabilities { @@ -21,14 +21,10 @@ pub fn server_capabilities() -> ServerCapabilities { completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: Some(vec![":".to_string(), ".".to_string()]), - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), - retrigger_characters: None, - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), - declaration_provider: None, definition_provider: Some(true), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), @@ -48,7 +44,6 @@ pub fn server_capabilities() -> ServerCapabilities { folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), - work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), document_link_provider: None, color_provider: None, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 158cac0be1..83845f1e00 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -520,8 +520,7 @@ fn on_notification( if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { subs.remove_sub(FileId(file_id.0)); } - let params = - req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; + let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; let not = notification_new::(params); msg_sender.send(not.into()).unwrap(); return Ok(()); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5b64b27cd2..4095836344 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -648,7 +648,6 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), - is_preferred: None, }; res.push(action.into()); } @@ -671,7 +670,6 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), - is_preferred: None, }; res.push(action.into()); } @@ -830,10 +828,9 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, - tags: None, }) .collect(); - Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) + Ok(req::PublishDiagnosticsParams { uri, diagnostics }) } pub fn publish_decorations( diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index dff63a12d4..cfbf16ea5f 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -4,8 +4,7 @@ use std::{collections::HashMap, time::Instant}; use lsp_types::{ CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, - PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, - WorkDoneProgressParams, + Position, Range, TextDocumentItem, TextDocumentPositionParams, }; use ra_lsp_server::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, @@ -49,8 +48,6 @@ use std::collections::Spam; Position::new(0, 23), ), context: None, - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }); assert!(format!("{}", res).contains("HashMap")); eprintln!("completion took {:?}", completion_start.elapsed()); @@ -214,12 +211,8 @@ pub use std::collections::HashMap; options: FormattingOptions { tab_size: 4, insert_spaces: false, - insert_final_newline: None, - trim_final_newlines: None, - trim_trailing_whitespace: None, properties: HashMap::new(), }, - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -279,11 +272,7 @@ pub use std::collections::HashMap; tab_size: 4, insert_spaces: false, properties: HashMap::new(), - insert_final_newline: None, - trim_final_newlines: None, - trim_trailing_whitespace: None, }, - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -336,8 +325,6 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -369,8 +356,6 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); @@ -419,8 +404,6 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -452,8 +435,6 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), - partial_result_params: PartialResultParams::default(), - work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); From b0a4765059c38e7b614d98015f7544ce0abc1bdf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 11 Dec 2019 18:34:01 +0100 Subject: [PATCH 129/312] Revert "Revert "Support LSP 3.15"" This reverts commit 1e0bf205eff81f04c0e1e6c208c3489327520c3f. --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 7 ++++++- crates/ra_lsp_server/src/main_loop.rs | 3 ++- .../ra_lsp_server/src/main_loop/handlers.rs | 5 ++++- .../ra_lsp_server/tests/heavy_tests/main.rs | 21 ++++++++++++++++++- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index caa52fb69d..3c567376e4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.61.0" +version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.61.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa3268fbe8beb2795c2fb327bf44f4f3d24f5fe9ebc18d7e2980afd444d72bcf" +"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 41672eaffe..c50cb8031d 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.61.0", features = ["proposed"] } +lsp-types = { version = "0.63.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index eea0965edb..4cb259360b 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -5,7 +5,7 @@ use lsp_types::{ DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, + TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, }; pub fn server_capabilities() -> ServerCapabilities { @@ -21,10 +21,14 @@ pub fn server_capabilities() -> ServerCapabilities { completion_provider: Some(CompletionOptions { resolve_provider: None, trigger_characters: Some(vec![":".to_string(), ".".to_string()]), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), + retrigger_characters: None, + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), + declaration_provider: None, definition_provider: Some(true), type_definition_provider: Some(TypeDefinitionProviderCapability::Simple(true)), implementation_provider: Some(ImplementationProviderCapability::Simple(true)), @@ -44,6 +48,7 @@ pub fn server_capabilities() -> ServerCapabilities { folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), + work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, })), document_link_provider: None, color_provider: None, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 83845f1e00..158cac0be1 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -520,7 +520,8 @@ fn on_notification( if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) { subs.remove_sub(FileId(file_id.0)); } - let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() }; + let params = + req::PublishDiagnosticsParams { uri, diagnostics: Vec::new(), version: None }; let not = notification_new::(params); msg_sender.send(not.into()).unwrap(); return Ok(()); diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 4095836344..5b64b27cd2 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -648,6 +648,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -670,6 +671,7 @@ pub fn handle_code_action( diagnostics: None, edit: None, command: Some(command), + is_preferred: None, }; res.push(action.into()); } @@ -828,9 +830,10 @@ pub fn publish_diagnostics( source: Some("rust-analyzer".to_string()), message: d.message, related_information: None, + tags: None, }) .collect(); - Ok(req::PublishDiagnosticsParams { uri, diagnostics }) + Ok(req::PublishDiagnosticsParams { uri, diagnostics, version: None }) } pub fn publish_decorations( diff --git a/crates/ra_lsp_server/tests/heavy_tests/main.rs b/crates/ra_lsp_server/tests/heavy_tests/main.rs index cfbf16ea5f..dff63a12d4 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/main.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/main.rs @@ -4,7 +4,8 @@ use std::{collections::HashMap, time::Instant}; use lsp_types::{ CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, - Position, Range, TextDocumentItem, TextDocumentPositionParams, + PartialResultParams, Position, Range, TextDocumentItem, TextDocumentPositionParams, + WorkDoneProgressParams, }; use ra_lsp_server::req::{ CodeActionParams, CodeActionRequest, Completion, CompletionParams, DidOpenTextDocument, @@ -48,6 +49,8 @@ use std::collections::Spam; Position::new(0, 23), ), context: None, + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }); assert!(format!("{}", res).contains("HashMap")); eprintln!("completion took {:?}", completion_start.elapsed()); @@ -211,8 +214,12 @@ pub use std::collections::HashMap; options: FormattingOptions { tab_size: 4, insert_spaces: false, + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, properties: HashMap::new(), }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -272,7 +279,11 @@ pub use std::collections::HashMap; tab_size: 4, insert_spaces: false, properties: HashMap::new(), + insert_final_newline: None, + trim_final_newlines: None, + trim_trailing_whitespace: None, }, + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -325,6 +336,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -356,6 +369,8 @@ fn main() {} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); @@ -404,6 +419,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(0, 4), Position::new(0, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([ { @@ -435,6 +452,8 @@ fn main() {{}} text_document: server.doc_id("src/lib.rs"), range: Range::new(Position::new(2, 4), Position::new(2, 7)), context: empty_context(), + partial_result_params: PartialResultParams::default(), + work_done_progress_params: WorkDoneProgressParams::default(), }, json!([]), ); From 6c6e6978eb5b1df611bde4677e078704fc3cc4ab Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 11 Dec 2019 18:34:22 +0100 Subject: [PATCH 130/312] Update lsp-types more --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c567376e4..13bbbb74c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.63.0" +version = "0.63.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1048,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.63.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1839,7 +1839,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.63.0 (registry+https://github.com/rust-lang/crates.io-index)" = "031d6b53a686f8eef69138f5b834b7eadadb0dd86f4c888504476ee1b17ae8d7" +"checksum lsp-types 0.63.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70090cea3cd5db0aa923575e03874b33da90c4d0fe1eaf63fa51b8925a78ef03" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index c50cb8031d..e29b688fdb 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.63.0", features = ["proposed"] } +lsp-types = { version = "0.63.1", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" From b4c8e5b9e95d28d3c18631e65caac4ff8c1f16d0 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Thu, 12 Dec 2019 07:55:05 -0500 Subject: [PATCH 131/312] Do not trigger signature help on close --- crates/ra_lsp_server/src/caps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index 4cb259360b..e0bb756666 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -24,7 +24,7 @@ pub fn server_capabilities() -> ServerCapabilities { work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), signature_help_provider: Some(SignatureHelpOptions { - trigger_characters: Some(vec!["(".to_string(), ",".to_string(), ")".to_string()]), + trigger_characters: Some(vec!["(".to_string(), ",".to_string()]), retrigger_characters: None, work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None }, }), From b0739d5a26684527129882b7d182d01e635525bc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:11:06 +0100 Subject: [PATCH 132/312] Avoid recompiling serde --- crates/ra_syntax/Cargo.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 1c0b184e1f..b6ebb129d0 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml @@ -18,13 +18,14 @@ rustc-hash = "1.0.1" arrayvec = "0.5.1" once_cell = "1.2.0" +ra_text_edit = { path = "../ra_text_edit" } +ra_parser = { path = "../ra_parser" } + # This crate transitively depends on `smol_str` via `rowan`. # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here # to reduce number of compilations smol_str = { version = "0.1.12", features = ["serde"] } - -ra_text_edit = { path = "../ra_text_edit" } -ra_parser = { path = "../ra_parser" } +serde = { version = "1", features = ["derive"] } [dev-dependencies] test_utils = { path = "../test_utils" } From 7b0644d81e52d00a7a6795b187f356213ff68225 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:09:13 +0100 Subject: [PATCH 133/312] Switch to the new location for impls --- Cargo.lock | 1 + crates/ra_hir/src/code_model.rs | 7 +++-- crates/ra_hir/src/from_source.rs | 6 +++-- crates/ra_hir/src/has_source.rs | 2 +- crates/ra_hir_def/src/attr.rs | 2 +- crates/ra_hir_def/src/child_by_source.rs | 5 ++++ crates/ra_hir_def/src/data.rs | 2 +- crates/ra_hir_def/src/db.rs | 6 ++--- crates/ra_hir_def/src/generics.rs | 2 +- crates/ra_hir_def/src/keys.rs | 6 +++-- crates/ra_hir_def/src/lib.rs | 30 +++++++++++++++------- crates/ra_hir_def/src/nameres/collector.rs | 10 +++++--- crates/ra_hir_def/src/resolver.rs | 3 ++- crates/ra_hir_def/src/src.rs | 11 +++++++- crates/ra_hir_ty/src/method_resolution.rs | 6 ++--- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- 16 files changed, 69 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13bbbb74c2..af874945c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1123,6 +1123,7 @@ dependencies = [ "rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index c013ff99bb..117ca2fe32 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -809,7 +809,10 @@ impl ImplBlock { let resolver = self.id.resolver(db); let environment = TraitEnvironment::lower(db, &resolver); let ty = Ty::from_hir(db, &resolver, &impl_data.target_type); - Type { krate: self.id.module(db).krate, ty: InEnvironment { value: ty, environment } } + Type { + krate: self.id.lookup(db).container.krate, + ty: InEnvironment { value: ty, environment }, + } } pub fn items(&self, db: &impl DefDatabase) -> Vec { @@ -821,7 +824,7 @@ impl ImplBlock { } pub fn module(&self, db: &impl DefDatabase) -> Module { - self.id.module(db).into() + self.id.lookup(db).container.into() } pub fn krate(&self, db: &impl DefDatabase) -> Crate { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 307f3d5bff..b35188a21c 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -107,8 +107,10 @@ impl FromSource for MacroDef { impl FromSource for ImplBlock { type Ast = ast::ImplBlock; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let id = from_source(db, src)?; - Some(ImplBlock { id }) + // XXX: use `.parent()` to avoid finding ourselves + let parent = src.value.syntax().parent()?; + let container = Container::find(db, src.with_value(parent).as_ref())?; + container.child_by_source(db)[keys::IMPL].get(&src).copied().map(ImplBlock::from) } } diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index b09582f93c..a888fe995c 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -114,7 +114,7 @@ impl HasSource for MacroDef { impl HasSource for ImplBlock { type Ast = ast::ImplBlock; fn source(self, db: &impl DefDatabase) -> InFile { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Import { diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 2f8f02d821..12d4e777a7 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -64,7 +64,7 @@ impl Attrs { AttrDefId::MacroDefId(it) => { it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)) } - AttrDefId::ImplId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AttrDefId::ImplId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::StaticId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db), diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index a3574a9dbb..821549bd58 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -98,6 +98,11 @@ impl ChildBySource for ModuleId { } } + for &impl_ in crate_def_map[self.local_id].impls.iter() { + let src = impl_.lookup(db).source(db); + res[keys::IMPL].insert(src, impl_) + } + res } } diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 095d7064a0..42821b9b11 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -167,7 +167,7 @@ pub struct ImplData { impl ImplData { pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc { - let src = id.source(db); + let src = id.lookup(db).source(db); let items = db.ast_id_map(src.file_id); let target_trait = src.value.target_trait().map(TypeRef::from_ast); diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index ef5611ffc0..8907aacca4 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -18,8 +18,8 @@ use crate::{ CrateDefMap, }, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, - ImplId, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, TypeAliasLoc, - UnionId, + ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, + TypeAliasLoc, UnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -41,7 +41,7 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; #[salsa::interned] - fn intern_impl(&self, loc: ItemLoc) -> ImplId; + fn intern_impl(&self, loc: ImplLoc) -> ImplId; } #[salsa::query_group(DefDatabaseStorage)] diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 976cf72d09..5d11009458 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -109,7 +109,7 @@ impl GenericParams { // type-parameter, but rather is a type-alias for impl's target // type, so this is handled by the resolver. GenericDefId::ImplId(it) => { - let src = it.source(db); + let src = it.lookup(db).source(db); generics.fill(&mut sm, &src.value); src.file_id } diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index be702a4f80..d318b2451d 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, StaticId, StructFieldId, TypeAliasId, TypeParamId, + ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, TypeAliasId, TypeParamId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -16,8 +16,10 @@ type Key = crate::dyn_map::Key, V, AstPtrPolicy>; pub const FUNCTION: Key = Key::new(); pub const CONST: Key = Key::new(); pub const STATIC: Key = Key::new(); -pub const ENUM_VARIANT: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); +pub const IMPL: Key = Key::new(); + +pub const ENUM_VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); pub const RECORD_FIELD: Key = Key::new(); pub const TYPE_PARAM: Key = Key::new(); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 569da4f284..5564b166bf 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -289,12 +289,24 @@ impl Lookup for TypeAliasId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplId(salsa::InternId); impl_intern_key!(ImplId); -impl AstItemDef for ImplId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_impl(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ImplLoc { + pub container: ModuleId, + pub ast_id: AstId, +} + +impl Intern for ImplLoc { + type ID = ImplId; + fn intern(self, db: &impl db::DefDatabase) -> ImplId { + db.intern_impl(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_impl(self) +} + +impl Lookup for ImplId { + type Data = ImplLoc; + fn lookup(&self, db: &impl db::DefDatabase) -> ImplLoc { + db.lookup_intern_impl(*self) } } @@ -479,7 +491,7 @@ impl HasModule for FunctionLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self.container { ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.module(db), + ContainerId::ImplId(it) => it.lookup(db).container, ContainerId::TraitId(it) => it.module(db), } } @@ -489,7 +501,7 @@ impl HasModule for TypeAliasLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self.container { ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.module(db), + ContainerId::ImplId(it) => it.lookup(db).container, ContainerId::TraitId(it) => it.module(db), } } @@ -499,7 +511,7 @@ impl HasModule for ConstLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self.container { ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.module(db), + ContainerId::ImplId(it) => it.lookup(db).container, ContainerId::TraitId(it) => it.module(db), } } @@ -532,7 +544,7 @@ impl HasModule for GenericDefId { GenericDefId::AdtId(it) => it.module(db), GenericDefId::TraitId(it) => it.module(db), GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), - GenericDefId::ImplId(it) => it.module(db), + GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::EnumVariantId(it) => it.parent.module(db), GenericDefId::ConstId(it) => it.lookup(db).module(db), } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index a80067979f..b33507a9ae 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -24,7 +24,7 @@ use crate::{ }, path::{Path, PathKind}, per_ns::PerNs, - AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplId, + AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplLoc, Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, TraitId, TypeAliasLoc, UnionId, }; @@ -661,9 +661,11 @@ where krate: self.def_collector.def_map.krate, local_id: self.module_id, }; - let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); - let imp_id = ImplId::from_ast_id(ctx, self.raw_items[imp].ast_id); - self.def_collector.def_map.modules[self.module_id].impls.push(imp_id) + let ast_id = self.raw_items[imp].ast_id; + let impl_id = + ImplLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db); + self.def_collector.def_map.modules[self.module_id].impls.push(impl_id) } } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 9484a61d53..f87b16b447 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -564,7 +564,8 @@ impl HasResolver for TypeAliasId { impl HasResolver for ImplId { fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db) + self.lookup(db) + .container .resolver(db) .push_generic_params_scope(db, self.into()) .push_impl_block_scope(self) diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs index 27caa02cc4..a5c4359a73 100644 --- a/crates/ra_hir_def/src/src.rs +++ b/crates/ra_hir_def/src/src.rs @@ -4,7 +4,7 @@ use hir_expand::InFile; use ra_arena::map::ArenaMap; use ra_syntax::ast; -use crate::{db::DefDatabase, ConstLoc, FunctionLoc, StaticLoc, TypeAliasLoc}; +use crate::{db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, TypeAliasLoc}; pub trait HasSource { type Value; @@ -47,6 +47,15 @@ impl HasSource for StaticLoc { } } +impl HasSource for ImplLoc { + type Value = ast::ImplBlock; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + pub trait HasChildSource { type ChildId; type Value; diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 7220d6e0a7..848e306e9e 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use arrayvec::ArrayVec; use hir_def::{ - lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, - FunctionId, HasModule, ImplId, Lookup, TraitId, + lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, FunctionId, + HasModule, ImplId, Lookup, TraitId, }; use hir_expand::name::Name; use ra_db::CrateId; @@ -134,7 +134,7 @@ impl Ty { LangItemTarget::ImplBlockId(it) => Some(it), _ => None, }) - .map(|it| it.module(db).krate) + .map(|it| it.lookup(db).container.krate) .collect(); Some(res) } diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 1e7ff93d59..ff299f511e 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -673,7 +673,7 @@ fn impl_block_datum( let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; - let impl_type = if impl_id.module(db).krate == krate { + let impl_type = if impl_id.lookup(db).container.krate == krate { chalk_rust_ir::ImplType::Local } else { chalk_rust_ir::ImplType::External From 82e9b245587046d2a1ed432225b19023adbe3245 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:34:03 +0100 Subject: [PATCH 134/312] Move traits to the new loc --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir/src/from_source.rs | 6 +++-- crates/ra_hir/src/has_source.rs | 2 +- crates/ra_hir_def/src/attr.rs | 2 +- crates/ra_hir_def/src/child_by_source.rs | 4 +++ crates/ra_hir_def/src/data.rs | 6 ++--- crates/ra_hir_def/src/db.rs | 6 ++--- crates/ra_hir_def/src/docs.rs | 2 +- crates/ra_hir_def/src/generics.rs | 2 +- crates/ra_hir_def/src/keys.rs | 4 ++- crates/ra_hir_def/src/lib.rs | 30 +++++++++++++++------- crates/ra_hir_def/src/nameres/collector.rs | 9 +++++-- crates/ra_hir_def/src/resolver.rs | 8 +++--- crates/ra_hir_def/src/src.rs | 11 +++++++- crates/ra_hir_expand/src/builtin_macro.rs | 5 +++- crates/ra_hir_ty/src/traits/chalk.rs | 6 ++--- 16 files changed, 70 insertions(+), 35 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 117ca2fe32..78c7792bf3 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -577,7 +577,7 @@ pub struct Trait { impl Trait { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).container } } pub fn name(self, db: &impl DefDatabase) -> Name { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index b35188a21c..0cf4bcae15 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -44,8 +44,10 @@ impl FromSource for Enum { impl FromSource for Trait { type Ast = ast::TraitDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let id = from_source(db, src)?; - Some(Trait { id }) + // XXX: use `.parent()` to avoid finding ourselves + let parent = src.value.syntax().parent()?; + let container = Container::find(db, src.with_value(parent).as_ref())?; + container.child_by_source(db)[keys::TRAIT].get(&src).copied().map(Trait::from) } } impl FromSource for Function { diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index a888fe995c..c4c6d66b75 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -93,7 +93,7 @@ impl HasSource for Static { impl HasSource for Trait { type Ast = ast::TraitDef; fn source(self, db: &impl DefDatabase) -> InFile { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for TypeAlias { diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 12d4e777a7..3347d819c7 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -60,7 +60,7 @@ impl Attrs { AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), }, - AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AttrDefId::TraitId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::MacroDefId(it) => { it.ast_id.map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)) } diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 821549bd58..88c2d3f242 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -94,6 +94,10 @@ impl ChildBySource for ModuleId { let src = ty.lookup(db).source(db); res[keys::TYPE_ALIAS].insert(src, ty) } + ModuleDefId::TraitId(trait_) => { + let src = trait_.lookup(db).source(db); + res[keys::TRAIT].insert(src, trait_) + } _ => (), } } diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 42821b9b11..b2dac183e3 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -12,8 +12,8 @@ use crate::{ db::DefDatabase, src::HasSource, type_ref::{Mutability, TypeRef}, - AssocItemId, AstItemDef, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, ImplId, - Intern, Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, + AssocItemId, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, ImplId, Intern, Lookup, + StaticId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -94,7 +94,7 @@ pub struct TraitData { impl TraitData { pub(crate) fn trait_data_query(db: &impl DefDatabase, tr: TraitId) -> Arc { - let src = tr.source(db); + let src = tr.lookup(db).source(db); let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let auto = src.value.is_auto(); let ast_id_map = db.ast_id_map(src.file_id); diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 8907aacca4..f0c2ae559a 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -18,8 +18,8 @@ use crate::{ CrateDefMap, }, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, - ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TypeAliasId, - TypeAliasLoc, UnionId, + ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TraitLoc, + TypeAliasId, TypeAliasLoc, UnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -37,7 +37,7 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_static(&self, loc: StaticLoc) -> StaticId; #[salsa::interned] - fn intern_trait(&self, loc: ItemLoc) -> TraitId; + fn intern_trait(&self, loc: TraitLoc) -> TraitId; #[salsa::interned] fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId; #[salsa::interned] diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 61727bd260..1921681fbd 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -59,7 +59,7 @@ impl Documentation { let src = it.parent.child_source(db); docs_from_ast(&src.value[it.local_id]) } - AttrDefId::TraitId(it) => docs_from_ast(&it.source(db).value), + AttrDefId::TraitId(it) => docs_from_ast(&it.lookup(db).source(db).value), AttrDefId::MacroDefId(it) => docs_from_ast(&it.ast_id?.to_node(db)), AttrDefId::ConstId(it) => docs_from_ast(&it.lookup(db).source(db).value), AttrDefId::StaticId(it) => docs_from_ast(&it.lookup(db).source(db).value), diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 5d11009458..cbfc3ff049 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -86,7 +86,7 @@ impl GenericParams { src.file_id } GenericDefId::TraitId(it) => { - let src = it.source(db); + let src = it.lookup(db).source(db); // traits get the Self type as an implicit first type parameter let self_param_id = diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index d318b2451d..6ec58f5f9a 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,7 +8,8 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, TypeAliasId, TypeParamId, + ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, TraitId, TypeAliasId, + TypeParamId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -18,6 +19,7 @@ pub const CONST: Key = Key::new(); pub const STATIC: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); +pub const TRAIT: Key = Key::new(); pub const ENUM_VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 5564b166bf..0fcc2cde49 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -253,12 +253,24 @@ impl Lookup for StaticId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TraitId(salsa::InternId); impl_intern_key!(TraitId); -impl AstItemDef for TraitId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_trait(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct TraitLoc { + pub container: ModuleId, + pub ast_id: AstId, +} + +impl Intern for TraitLoc { + type ID = TraitId; + fn intern(self, db: &impl db::DefDatabase) -> TraitId { + db.intern_trait(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_trait(self) +} + +impl Lookup for TraitId { + type Data = TraitLoc; + fn lookup(&self, db: &impl db::DefDatabase) -> TraitLoc { + db.lookup_intern_trait(*self) } } @@ -492,7 +504,7 @@ impl HasModule for FunctionLoc { match self.container { ContainerId::ModuleId(it) => it, ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.module(db), + ContainerId::TraitId(it) => it.lookup(db).container, } } } @@ -502,7 +514,7 @@ impl HasModule for TypeAliasLoc { match self.container { ContainerId::ModuleId(it) => it, ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.module(db), + ContainerId::TraitId(it) => it.lookup(db).container, } } } @@ -512,7 +524,7 @@ impl HasModule for ConstLoc { match self.container { ContainerId::ModuleId(it) => it, ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.module(db), + ContainerId::TraitId(it) => it.lookup(db).container, } } } @@ -542,7 +554,7 @@ impl HasModule for GenericDefId { match self { GenericDefId::FunctionId(it) => it.lookup(db).module(db), GenericDefId::AdtId(it) => it.module(db), - GenericDefId::TraitId(it) => it.module(db), + GenericDefId::TraitId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::EnumVariantId(it) => it.parent.module(db), diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b33507a9ae..a7bdd620b4 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -26,7 +26,7 @@ use crate::{ per_ns::PerNs, AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplLoc, Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, - TraitId, TypeAliasLoc, UnionId, + TraitLoc, TypeAliasLoc, UnionId, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -796,7 +796,12 @@ where PerNs::values(def.into()) } - raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), + raw::DefKind::Trait(ast_id) => { + let def = TraitLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db); + + PerNs::types(def.into()) + } raw::DefKind::TypeAlias(ast_id) => { let def = TypeAliasLoc { container: ContainerId::ModuleId(module), diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index f87b16b447..17b2169d2a 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -17,9 +17,9 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{Path, PathKind}, per_ns::PerNs, - AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, TypeParamId, VariantId, + AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, + HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, + TypeAliasId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -524,7 +524,7 @@ impl HasResolver for ModuleId { impl HasResolver for TraitId { fn resolver(self, db: &impl DefDatabase) -> Resolver { - self.module(db).resolver(db).push_generic_params_scope(db, self.into()) + self.lookup(db).container.resolver(db).push_generic_params_scope(db, self.into()) } } diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs index a5c4359a73..858e4861eb 100644 --- a/crates/ra_hir_def/src/src.rs +++ b/crates/ra_hir_def/src/src.rs @@ -4,7 +4,7 @@ use hir_expand::InFile; use ra_arena::map::ArenaMap; use ra_syntax::ast; -use crate::{db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, TypeAliasLoc}; +use crate::{db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, TraitLoc, TypeAliasLoc}; pub trait HasSource { type Value; @@ -56,6 +56,15 @@ impl HasSource for ImplLoc { } } +impl HasSource for TraitLoc { + type Value = ast::TraitDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + pub trait HasChildSource { type ChildId; type Value; diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index ec5ace757c..be5f3cbe35 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -367,6 +367,9 @@ mod tests { BuiltinFnLikeExpander::FormatArgs, ); - assert_eq!(expanded, r#"std::fmt::Arguments::new_v1(&[] ,&[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"#); + assert_eq!( + expanded, + r#"std::fmt::Arguments::new_v1(&[] ,&[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# + ); } } diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index ff299f511e..fc21872b2b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,9 +9,7 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{ - AssocItemId, AstItemDef, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId, -}; +use hir_def::{AssocItemId, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -593,7 +591,7 @@ pub(crate) fn trait_datum_query( let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, - upstream: trait_.module(db).krate != krate, + upstream: trait_.lookup(db).container.krate != krate, non_enumerable: true, coinductive: false, // only relevant for Chalk testing // FIXME set these flags correctly From 63c192b34a54e826afebc735ca6225b44a876eab Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:48:33 +0100 Subject: [PATCH 135/312] Simplify from_source --- crates/ra_hir/src/from_source.rs | 83 +++++++++++++------------------- 1 file changed, 34 insertions(+), 49 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 0cf4bcae15..091349d49d 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -44,16 +44,16 @@ impl FromSource for Enum { impl FromSource for Trait { type Ast = ast::TraitDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - // XXX: use `.parent()` to avoid finding ourselves - let parent = src.value.syntax().parent()?; - let container = Container::find(db, src.with_value(parent).as_ref())?; - container.child_by_source(db)[keys::TRAIT].get(&src).copied().map(Trait::from) + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TRAIT] + .get(&src) + .copied() + .map(Trait::from) } } impl FromSource for Function { type Ast = ast::FnDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::FUNCTION] + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::FUNCTION] .get(&src) .copied() .map(Function::from) @@ -63,7 +63,7 @@ impl FromSource for Function { impl FromSource for Const { type Ast = ast::ConstDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::CONST] + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::CONST] .get(&src) .copied() .map(Const::from) @@ -72,7 +72,7 @@ impl FromSource for Const { impl FromSource for Static { type Ast = ast::StaticDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db)[keys::STATIC] + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STATIC] .get(&src) .copied() .map(Static::from) @@ -82,8 +82,7 @@ impl FromSource for Static { impl FromSource for TypeAlias { type Ast = ast::TypeAliasDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - Container::find(db, src.as_ref().map(|it| it.syntax()))?.child_by_source(db) - [keys::TYPE_ALIAS] + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TYPE_ALIAS] .get(&src) .copied() .map(TypeAlias::from) @@ -109,10 +108,10 @@ impl FromSource for MacroDef { impl FromSource for ImplBlock { type Ast = ast::ImplBlock; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - // XXX: use `.parent()` to avoid finding ourselves - let parent = src.value.syntax().parent()?; - let container = Container::find(db, src.with_value(parent).as_ref())?; - container.child_by_source(db)[keys::IMPL].get(&src).copied().map(ImplBlock::from) + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::IMPL] + .get(&src) + .copied() + .map(ImplBlock::from) } } @@ -262,44 +261,30 @@ where Some(DEF::from_ast_id(ctx, item_id)) } -enum Container { - Trait(Trait), - ImplBlock(ImplBlock), - Module(Module), +fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { + _analyze_container(db, src).unwrap_or_default() } -impl Container { - fn find(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { - // FIXME: this doesn't try to handle nested declarations - for container in src.value.ancestors() { - let res = match_ast! { - match container { - ast::TraitDef(it) => { - let c = Trait::from_source(db, src.with_value(it))?; - Container::Trait(c) - }, - ast::ImplBlock(it) => { - let c = ImplBlock::from_source(db, src.with_value(it))?; - Container::ImplBlock(c) - }, - _ => { continue }, - } - }; - return Some(res); - } - - let module_source = ModuleSource::from_child_node(db, src); - let c = Module::from_definition(db, src.with_value(module_source))?; - Some(Container::Module(c)) +fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { + // FIXME: this doesn't try to handle nested declarations + for container in src.value.ancestors().skip(1) { + let res = match_ast! { + match container { + ast::TraitDef(it) => { + let c = Trait::from_source(db, src.with_value(it))?; + c.id.child_by_source(db) + }, + ast::ImplBlock(it) => { + let c = ImplBlock::from_source(db, src.with_value(it))?; + c.id.child_by_source(db) + }, + _ => { continue }, + } + }; + return Some(res); } -} -impl ChildBySource for Container { - fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { - match self { - Container::Trait(it) => it.id.child_by_source(db), - Container::ImplBlock(it) => it.id.child_by_source(db), - Container::Module(it) => it.id.child_by_source(db), - } - } + let module_source = ModuleSource::from_child_node(db, src); + let c = Module::from_definition(db, src.with_value(module_source))?; + Some(c.id.child_by_source(db)) } From f135a8ea55c0a46c67713fb3b79b5f62ada430c1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 14:58:04 +0100 Subject: [PATCH 136/312] Move structs to new loc --- crates/ra_hir/src/code_model.rs | 4 ++-- crates/ra_hir/src/from_source.rs | 6 ++++-- crates/ra_hir/src/has_source.rs | 2 +- crates/ra_hir_def/src/adt.rs | 9 ++++---- crates/ra_hir_def/src/attr.rs | 2 +- crates/ra_hir_def/src/child_by_source.rs | 12 +++++++++-- crates/ra_hir_def/src/db.rs | 6 +++--- crates/ra_hir_def/src/docs.rs | 2 +- crates/ra_hir_def/src/generics.rs | 2 +- crates/ra_hir_def/src/keys.rs | 5 +++-- crates/ra_hir_def/src/lib.rs | 24 ++++++++++++++++------ crates/ra_hir_def/src/nameres/collector.rs | 7 ++++--- crates/ra_hir_def/src/src.rs | 13 +++++++++++- crates/ra_hir_ty/src/lower.rs | 2 +- 14 files changed, 66 insertions(+), 30 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 78c7792bf3..8588aa5a3a 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -269,7 +269,7 @@ pub struct Struct { impl Struct { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).container } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -290,7 +290,7 @@ impl Struct { } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.module(db).krate, self.id) + Type::from_def(db, self.id.lookup(db).container.krate, self.id) } fn variant_data(self, db: &impl DefDatabase) -> Arc { diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 091349d49d..978326c74c 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -23,8 +23,10 @@ pub trait FromSource: Sized { impl FromSource for Struct { type Ast = ast::StructDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let id = from_source(db, src)?; - Some(Struct { id }) + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STRUCT] + .get(&src) + .copied() + .map(Struct::from) } } impl FromSource for Union { diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index c4c6d66b75..8f35a3fbb4 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -51,7 +51,7 @@ impl HasSource for StructField { impl HasSource for Struct { type Ast = ast::StructDef; fn source(self, db: &impl DefDatabase) -> InFile { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Union { diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index db3e63ef82..ef2b20f1ec 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -11,8 +11,9 @@ use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ - db::DefDatabase, src::HasChildSource, trace::Trace, type_ref::TypeRef, AstItemDef, EnumId, - LocalEnumVariantId, LocalStructFieldId, StructId, UnionId, VariantId, + db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, + AstItemDef, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, + VariantId, }; /// Note that we use `StructData` for unions as well! @@ -50,7 +51,7 @@ pub struct StructFieldData { impl StructData { pub(crate) fn struct_data_query(db: &impl DefDatabase, id: StructId) -> Arc { - let src = id.source(db); + let src = id.lookup(db).source(db); let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let variant_data = VariantData::new(src.value.kind()); let variant_data = Arc::new(variant_data); @@ -153,7 +154,7 @@ impl HasChildSource for VariantId { let src = it.parent.child_source(db); src.map(|map| map[it.local_id].kind()) } - VariantId::StructId(it) => it.source(db).map(|it| it.kind()), + VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()), VariantId::UnionId(it) => it.source(db).map(|it| { it.record_field_def_list() .map(ast::StructKind::Record) diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 3347d819c7..d2aa5ce8f1 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -56,7 +56,7 @@ impl Attrs { Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) } AttrDefId::AdtId(it) => match it { - AdtId::StructId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AdtId::StructId(it) => attrs_from_loc(it.lookup(db), db), AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), }, diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 88c2d3f242..eba361578b 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -11,8 +11,8 @@ use crate::{ dyn_map::DynMap, keys, src::{HasChildSource, HasSource}, - AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, StructFieldId, - TraitId, VariantId, + AdtId, AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, + StructFieldId, TraitId, VariantId, }; pub trait ChildBySource { @@ -98,6 +98,14 @@ impl ChildBySource for ModuleId { let src = trait_.lookup(db).source(db); res[keys::TRAIT].insert(src, trait_) } + ModuleDefId::AdtId(adt) => match adt { + AdtId::StructId(strukt) => { + let src = strukt.lookup(db).source(db); + res[keys::STRUCT].insert(src, strukt) + } + AdtId::UnionId(_) => (), + AdtId::EnumId(_) => (), + }, _ => (), } } diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index f0c2ae559a..e120c7768d 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -18,8 +18,8 @@ use crate::{ CrateDefMap, }, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, - ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, TraitId, TraitLoc, - TypeAliasId, TypeAliasLoc, UnionId, + ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, + TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, }; #[salsa::query_group(InternDatabaseStorage)] @@ -27,7 +27,7 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_function(&self, loc: FunctionLoc) -> FunctionId; #[salsa::interned] - fn intern_struct(&self, loc: ItemLoc) -> StructId; + fn intern_struct(&self, loc: StructLoc) -> StructId; #[salsa::interned] fn intern_union(&self, loc: ItemLoc) -> UnionId; #[salsa::interned] diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 1921681fbd..58143b894a 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -51,7 +51,7 @@ impl Documentation { } } AttrDefId::AdtId(it) => match it { - AdtId::StructId(it) => docs_from_ast(&it.source(db).value), + AdtId::StructId(it) => docs_from_ast(&it.lookup(db).source(db).value), AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), AdtId::UnionId(it) => docs_from_ast(&it.source(db).value), }, diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index cbfc3ff049..f1ce8d59a2 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -71,7 +71,7 @@ impl GenericParams { src.file_id } GenericDefId::AdtId(AdtId::StructId(it)) => { - let src = it.source(db); + let src = it.lookup(db).source(db); generics.fill(&mut sm, &src.value); src.file_id } diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index 6ec58f5f9a..758cf80970 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,8 +8,8 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, TraitId, TypeAliasId, - TypeParamId, + ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId, + TypeAliasId, TypeParamId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -20,6 +20,7 @@ pub const STATIC: Key = Key::new(); pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); pub const TRAIT: Key = Key::new(); +pub const STRUCT: Key = Key::new(); pub const ENUM_VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 0fcc2cde49..1a599706a7 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -149,12 +149,24 @@ impl Lookup for FunctionId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructId(salsa::InternId); impl_intern_key!(StructId); -impl AstItemDef for StructId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_struct(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct StructLoc { + pub container: ModuleId, + pub ast_id: AstId, +} + +impl Intern for StructLoc { + type ID = StructId; + fn intern(self, db: &impl db::DefDatabase) -> StructId { + db.intern_struct(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_struct(self) +} + +impl Lookup for StructId { + type Data = StructLoc; + fn lookup(&self, db: &impl db::DefDatabase) -> StructLoc { + db.lookup_intern_struct(*self) } } @@ -532,7 +544,7 @@ impl HasModule for ConstLoc { impl HasModule for AdtId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self { - AdtId::StructId(it) => it.module(db), + AdtId::StructId(it) => it.lookup(db).container, AdtId::UnionId(it) => it.module(db), AdtId::EnumId(it) => it.module(db), } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index a7bdd620b4..602ec0911c 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -25,7 +25,7 @@ use crate::{ path::{Path, PathKind}, per_ns::PerNs, AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplLoc, - Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructId, + Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionId, }; @@ -773,8 +773,9 @@ where PerNs::values(def.into()) } raw::DefKind::Struct(ast_id) => { - let id = StructId::from_ast_id(ctx, ast_id).into(); - PerNs::both(id, id) + let def = StructLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db); + PerNs::both(def.into(), def.into()) } raw::DefKind::Union(ast_id) => { let id = UnionId::from_ast_id(ctx, ast_id).into(); diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs index 858e4861eb..7e212adb15 100644 --- a/crates/ra_hir_def/src/src.rs +++ b/crates/ra_hir_def/src/src.rs @@ -4,7 +4,9 @@ use hir_expand::InFile; use ra_arena::map::ArenaMap; use ra_syntax::ast; -use crate::{db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, TraitLoc, TypeAliasLoc}; +use crate::{ + db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, +}; pub trait HasSource { type Value; @@ -65,6 +67,15 @@ impl HasSource for TraitLoc { } } +impl HasSource for StructLoc { + type Value = ast::StructDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + pub trait HasChildSource { type ChildId; type Value; diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index eab91229e3..6af5bf50aa 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -699,7 +699,7 @@ impl CallableDef { pub fn krate(self, db: &impl HirDatabase) -> CrateId { match self { CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, - CallableDef::StructId(s) => s.module(db).krate, + CallableDef::StructId(s) => s.lookup(db).container.krate, CallableDef::EnumVariantId(e) => e.parent.module(db).krate, } } From 56710f119b7114efac237ac36ea21730b8bd5311 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 15:11:57 +0100 Subject: [PATCH 137/312] Move enum&union to new loc --- crates/ra_hir/src/code_model.rs | 10 ++--- crates/ra_hir/src/from_source.rs | 29 +++++-------- crates/ra_hir/src/has_source.rs | 6 +-- crates/ra_hir_def/src/adt.rs | 13 +++--- crates/ra_hir_def/src/attr.rs | 7 ++- crates/ra_hir_def/src/child_by_source.rs | 10 ++++- crates/ra_hir_def/src/db.rs | 12 +++--- crates/ra_hir_def/src/docs.rs | 6 +-- crates/ra_hir_def/src/generics.rs | 6 +-- crates/ra_hir_def/src/keys.rs | 4 +- crates/ra_hir_def/src/lib.rs | 50 ++++++++++++++++------ crates/ra_hir_def/src/nameres/collector.rs | 19 ++++---- crates/ra_hir_def/src/src.rs | 21 ++++++++- crates/ra_hir_ty/src/lower.rs | 9 ++-- 14 files changed, 123 insertions(+), 79 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 8588aa5a3a..c705d16302 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,7 +11,7 @@ use hir_def::{ per_ns::PerNs, resolver::HasResolver, type_ref::{Mutability, TypeRef}, - AdtId, AstItemDef, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, + AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, }; @@ -309,11 +309,11 @@ impl Union { } pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).container } } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.module(db).krate, self.id) + Type::from_def(db, self.id.lookup(db).container.krate, self.id) } pub fn fields(self, db: &impl HirDatabase) -> Vec { @@ -337,7 +337,7 @@ pub struct Enum { impl Enum { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.module(db) } + Module { id: self.id.lookup(db).container } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -357,7 +357,7 @@ impl Enum { } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.module(db).krate, self.id) + Type::from_def(db, self.id.lookup(db).container.krate, self.id) } } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 978326c74c..f7411c5cf1 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir_def::{ - child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, AstItemDef, - EnumVariantId, GenericDefId, LocationCtx, ModuleId, VariantId, + child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, EnumVariantId, + GenericDefId, ModuleId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -32,15 +32,19 @@ impl FromSource for Struct { impl FromSource for Union { type Ast = ast::UnionDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let id = from_source(db, src)?; - Some(Union { id }) + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::UNION] + .get(&src) + .copied() + .map(Union::from) } } impl FromSource for Enum { type Ast = ast::EnumDef; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - let id = from_source(db, src)?; - Some(Enum { id }) + analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::ENUM] + .get(&src) + .copied() + .map(Enum::from) } } impl FromSource for Trait { @@ -250,19 +254,6 @@ impl Module { } } -fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option -where - N: AstNode, - DEF: AstItemDef, -{ - let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); - let module = Module::from_definition(db, InFile::new(src.file_id, module_src))?; - let ctx = LocationCtx::new(db, module.id, src.file_id); - let items = db.ast_id_map(src.file_id); - let item_id = items.ast_id(&src.value); - Some(DEF::from_ast_id(ctx, item_id)) -} - fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { _analyze_container(db, src).unwrap_or_default() } diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 8f35a3fbb4..72afecf26c 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -4,7 +4,7 @@ use either::Either; use hir_def::{ nameres::ModuleSource, src::{HasChildSource, HasSource as _}, - AstItemDef, Lookup, VariantId, + Lookup, VariantId, }; use ra_syntax::ast; @@ -57,13 +57,13 @@ impl HasSource for Struct { impl HasSource for Union { type Ast = ast::UnionDef; fn source(self, db: &impl DefDatabase) -> InFile { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for Enum { type Ast = ast::EnumDef; fn source(self, db: &impl DefDatabase) -> InFile { - self.id.source(db) + self.id.lookup(db).source(db) } } impl HasSource for EnumVariant { diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index ef2b20f1ec..ec3d57d1a9 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -11,9 +11,8 @@ use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ - db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, - AstItemDef, EnumId, LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, - VariantId, + db::DefDatabase, src::HasChildSource, src::HasSource, trace::Trace, type_ref::TypeRef, EnumId, + LocalEnumVariantId, LocalStructFieldId, Lookup, StructId, UnionId, VariantId, }; /// Note that we use `StructData` for unions as well! @@ -58,7 +57,7 @@ impl StructData { Arc::new(StructData { name, variant_data }) } pub(crate) fn union_data_query(db: &impl DefDatabase, id: UnionId) -> Arc { - let src = id.source(db); + let src = id.lookup(db).source(db); let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let variant_data = VariantData::new( src.value @@ -73,7 +72,7 @@ impl StructData { impl EnumData { pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc { - let src = e.source(db); + let src = e.lookup(db).source(db); let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let mut trace = Trace::new_for_arena(); lower_enum(&mut trace, &src.value); @@ -90,7 +89,7 @@ impl HasChildSource for EnumId { type ChildId = LocalEnumVariantId; type Value = ast::EnumVariant; fn child_source(&self, db: &impl DefDatabase) -> InFile> { - let src = self.source(db); + let src = self.lookup(db).source(db); let mut trace = Trace::new_for_map(); lower_enum(&mut trace, &src.value); src.with_value(trace.into_map()) @@ -155,7 +154,7 @@ impl HasChildSource for VariantId { src.map(|map| map[it.local_id].kind()) } VariantId::StructId(it) => it.lookup(db).source(db).map(|it| it.kind()), - VariantId::UnionId(it) => it.source(db).map(|it| { + VariantId::UnionId(it) => it.lookup(db).source(db).map(|it| { it.record_field_def_list() .map(ast::StructKind::Record) .unwrap_or(ast::StructKind::Unit) diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index d2aa5ce8f1..5bf82e191c 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -12,8 +12,7 @@ use ra_syntax::{ use tt::Subtree; use crate::{ - db::DefDatabase, path::Path, src::HasChildSource, src::HasSource, AdtId, AstItemDef, AttrDefId, - Lookup, + db::DefDatabase, path::Path, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -57,8 +56,8 @@ impl Attrs { } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_loc(it.lookup(db), db), - AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), - AdtId::UnionId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AdtId::EnumId(it) => attrs_from_loc(it.lookup(db), db), + AdtId::UnionId(it) => attrs_from_loc(it.lookup(db), db), }, AttrDefId::TraitId(it) => attrs_from_loc(it.lookup(db), db), AttrDefId::MacroDefId(it) => { diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index eba361578b..3c9379b151 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -103,8 +103,14 @@ impl ChildBySource for ModuleId { let src = strukt.lookup(db).source(db); res[keys::STRUCT].insert(src, strukt) } - AdtId::UnionId(_) => (), - AdtId::EnumId(_) => (), + AdtId::UnionId(union_) => { + let src = union_.lookup(db).source(db); + res[keys::UNION].insert(src, union_) + } + AdtId::EnumId(enum_) => { + let src = enum_.lookup(db).source(db); + res[keys::ENUM].insert(src, enum_) + } }, _ => (), } diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index e120c7768d..98bff6cb78 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use hir_expand::{db::AstDatabase, HirFileId}; use ra_db::{salsa, CrateId, SourceDatabase}; -use ra_syntax::{ast, SmolStr}; +use ra_syntax::SmolStr; use crate::{ adt::{EnumData, StructData}, @@ -17,9 +17,9 @@ use crate::{ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, FunctionId, FunctionLoc, GenericDefId, - ImplId, ImplLoc, ItemLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, - TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, + AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, + GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, + TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, }; #[salsa::query_group(InternDatabaseStorage)] @@ -29,9 +29,9 @@ pub trait InternDatabase: SourceDatabase { #[salsa::interned] fn intern_struct(&self, loc: StructLoc) -> StructId; #[salsa::interned] - fn intern_union(&self, loc: ItemLoc) -> UnionId; + fn intern_union(&self, loc: UnionLoc) -> UnionId; #[salsa::interned] - fn intern_enum(&self, loc: ItemLoc) -> EnumId; + fn intern_enum(&self, loc: EnumLoc) -> EnumId; #[salsa::interned] fn intern_const(&self, loc: ConstLoc) -> ConstId; #[salsa::interned] diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs index 58143b894a..b29f142e33 100644 --- a/crates/ra_hir_def/src/docs.rs +++ b/crates/ra_hir_def/src/docs.rs @@ -11,7 +11,7 @@ use ra_syntax::ast; use crate::{ db::DefDatabase, src::{HasChildSource, HasSource}, - AdtId, AstItemDef, AttrDefId, Lookup, + AdtId, AttrDefId, Lookup, }; /// Holds documentation @@ -52,8 +52,8 @@ impl Documentation { } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => docs_from_ast(&it.lookup(db).source(db).value), - AdtId::EnumId(it) => docs_from_ast(&it.source(db).value), - AdtId::UnionId(it) => docs_from_ast(&it.source(db).value), + AdtId::EnumId(it) => docs_from_ast(&it.lookup(db).source(db).value), + AdtId::UnionId(it) => docs_from_ast(&it.lookup(db).source(db).value), }, AttrDefId::EnumVariantId(it) => { let src = it.parent.child_source(db); diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index f1ce8d59a2..e502dd7983 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -21,7 +21,7 @@ use crate::{ src::HasChildSource, src::HasSource, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, + AdtId, GenericDefId, LocalTypeParamId, Lookup, TypeParamId, }; /// Data about a generic parameter (to a function, struct, impl, ...). @@ -76,12 +76,12 @@ impl GenericParams { src.file_id } GenericDefId::AdtId(AdtId::UnionId(it)) => { - let src = it.source(db); + let src = it.lookup(db).source(db); generics.fill(&mut sm, &src.value); src.file_id } GenericDefId::AdtId(AdtId::EnumId(it)) => { - let src = it.source(db); + let src = it.lookup(db).source(db); generics.fill(&mut sm, &src.value); src.file_id } diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index 758cf80970..ada145379c 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -9,7 +9,7 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId, - TypeAliasId, TypeParamId, + TypeAliasId, TypeParamId, EnumId, UnionId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; @@ -21,6 +21,8 @@ pub const TYPE_ALIAS: Key = Key::new(); pub const IMPL: Key = Key::new(); pub const TRAIT: Key = Key::new(); pub const STRUCT: Key = Key::new(); +pub const UNION: Key = Key::new(); +pub const ENUM: Key = Key::new(); pub const ENUM_VARIANT: Key = Key::new(); pub const TUPLE_FIELD: Key = Key::new(); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 1a599706a7..c9e4e6a0f5 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -173,24 +173,48 @@ impl Lookup for StructId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UnionId(salsa::InternId); impl_intern_key!(UnionId); -impl AstItemDef for UnionId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_union(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct UnionLoc { + pub container: ModuleId, + pub ast_id: AstId, +} + +impl Intern for UnionLoc { + type ID = UnionId; + fn intern(self, db: &impl db::DefDatabase) -> UnionId { + db.intern_union(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_union(self) +} + +impl Lookup for UnionId { + type Data = UnionLoc; + fn lookup(&self, db: &impl db::DefDatabase) -> UnionLoc { + db.lookup_intern_union(*self) } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumId(salsa::InternId); impl_intern_key!(EnumId); -impl AstItemDef for EnumId { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self { - db.intern_enum(loc) + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct EnumLoc { + pub container: ModuleId, + pub ast_id: AstId, +} + +impl Intern for EnumLoc { + type ID = EnumId; + fn intern(self, db: &impl db::DefDatabase) -> EnumId { + db.intern_enum(self) } - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc { - db.lookup_intern_enum(self) +} + +impl Lookup for EnumId { + type Data = EnumLoc; + fn lookup(&self, db: &impl db::DefDatabase) -> EnumLoc { + db.lookup_intern_enum(*self) } } @@ -545,8 +569,8 @@ impl HasModule for AdtId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match self { AdtId::StructId(it) => it.lookup(db).container, - AdtId::UnionId(it) => it.module(db), - AdtId::EnumId(it) => it.module(db), + AdtId::UnionId(it) => it.lookup(db).container, + AdtId::EnumId(it) => it.lookup(db).container, } } } @@ -569,7 +593,7 @@ impl HasModule for GenericDefId { GenericDefId::TraitId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => it.parent.module(db), + GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, GenericDefId::ConstId(it) => it.lookup(db).module(db), } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 602ec0911c..04aadead19 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -24,9 +24,9 @@ use crate::{ }, path::{Path, PathKind}, per_ns::PerNs, - AdtId, AstId, AstItemDef, ConstLoc, ContainerId, EnumId, EnumVariantId, FunctionLoc, ImplLoc, - Intern, LocalImportId, LocalModuleId, LocationCtx, ModuleDefId, ModuleId, StaticLoc, StructLoc, - TraitLoc, TypeAliasLoc, UnionId, + AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, + LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, + TypeAliasLoc, UnionLoc, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -753,8 +753,6 @@ where fn define_def(&mut self, def: &raw::DefData, attrs: &Attrs) { let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: self.module_id }; - let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id); - // FIXME: check attrs to see if this is an attribute macro invocation; // in which case we don't add the invocation, just a single attribute // macro invocation @@ -778,10 +776,15 @@ where PerNs::both(def.into(), def.into()) } raw::DefKind::Union(ast_id) => { - let id = UnionId::from_ast_id(ctx, ast_id).into(); - PerNs::both(id, id) + let def = UnionLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db); + PerNs::both(def.into(), def.into()) + } + raw::DefKind::Enum(ast_id) => { + let def = EnumLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db); + PerNs::types(def.into()) } - raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), raw::DefKind::Const(ast_id) => { let def = ConstLoc { container: ContainerId::ModuleId(module), diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs index 7e212adb15..20200d1db4 100644 --- a/crates/ra_hir_def/src/src.rs +++ b/crates/ra_hir_def/src/src.rs @@ -5,7 +5,8 @@ use ra_arena::map::ArenaMap; use ra_syntax::ast; use crate::{ - db::DefDatabase, ConstLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, + db::DefDatabase, ConstLoc, EnumLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc, + TypeAliasLoc, UnionLoc, }; pub trait HasSource { @@ -76,6 +77,24 @@ impl HasSource for StructLoc { } } +impl HasSource for UnionLoc { + type Value = ast::UnionDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + +impl HasSource for EnumLoc { + type Value = ast::EnumDef; + + fn source(&self, db: &impl DefDatabase) -> InFile { + let node = self.ast_id.to_node(db); + InFile::new(self.ast_id.file_id, node) + } +} + pub trait HasChildSource { type ChildId; type Value; diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 6af5bf50aa..5f795bc022 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -14,7 +14,7 @@ use hir_def::{ path::{GenericArg, Path, PathKind, PathSegment}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, - AdtId, AstItemDef, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, + AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalStructFieldId, Lookup, StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use ra_arena::map::ArenaMap; @@ -698,10 +698,11 @@ impl_froms!(CallableDef: FunctionId, StructId, EnumVariantId); impl CallableDef { pub fn krate(self, db: &impl HirDatabase) -> CrateId { match self { - CallableDef::FunctionId(f) => f.lookup(db).module(db).krate, - CallableDef::StructId(s) => s.lookup(db).container.krate, - CallableDef::EnumVariantId(e) => e.parent.module(db).krate, + CallableDef::FunctionId(f) => f.lookup(db).module(db), + CallableDef::StructId(s) => s.lookup(db).container, + CallableDef::EnumVariantId(e) => e.parent.lookup(db).container, } + .krate } } From 7a255a2f9381ba5886cacc48c1dd0420a739a55c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 15:13:05 +0100 Subject: [PATCH 138/312] Remove old location infra --- crates/ra_hir_def/src/keys.rs | 4 +-- crates/ra_hir_def/src/lib.rs | 65 +++-------------------------------- 2 files changed, 6 insertions(+), 63 deletions(-) diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index ada145379c..4611c6e386 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -8,8 +8,8 @@ use rustc_hash::FxHashMap; use crate::{ dyn_map::{DynMap, Policy}, - ConstId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId, - TypeAliasId, TypeParamId, EnumId, UnionId, + ConstId, EnumId, EnumVariantId, FunctionId, ImplId, StaticId, StructFieldId, StructId, TraitId, + TypeAliasId, TypeParamId, UnionId, }; type Key = crate::dyn_map::Key, V, AstPtrPolicy>; diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index c9e4e6a0f5..f085bbe872 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -40,14 +40,14 @@ mod test_db; #[cfg(test)] mod marks; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; -use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, InFile, MacroDefId}; +use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId}; use ra_arena::{impl_arena_id, RawId}; use ra_db::{impl_intern_key, salsa, CrateId}; -use ra_syntax::{ast, AstNode}; +use ra_syntax::ast; -use crate::{builtin_type::BuiltinType, db::InternDatabase}; +use crate::builtin_type::BuiltinType; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct LocalImportId(RawId); @@ -65,63 +65,6 @@ pub struct ModuleId { pub struct LocalModuleId(RawId); impl_arena_id!(LocalModuleId); -#[derive(Debug)] -pub struct ItemLoc { - pub(crate) module: ModuleId, - ast_id: AstId, -} - -impl PartialEq for ItemLoc { - fn eq(&self, other: &Self) -> bool { - self.module == other.module && self.ast_id == other.ast_id - } -} -impl Eq for ItemLoc {} -impl Hash for ItemLoc { - fn hash(&self, hasher: &mut H) { - self.module.hash(hasher); - self.ast_id.hash(hasher); - } -} - -impl Clone for ItemLoc { - fn clone(&self) -> ItemLoc { - ItemLoc { module: self.module, ast_id: self.ast_id } - } -} - -#[derive(Clone, Copy)] -pub struct LocationCtx { - db: DB, - module: ModuleId, - file_id: HirFileId, -} - -impl<'a, DB> LocationCtx<&'a DB> { - pub fn new(db: &'a DB, module: ModuleId, file_id: HirFileId) -> LocationCtx<&'a DB> { - LocationCtx { db, module, file_id } - } -} - -pub trait AstItemDef: salsa::InternKey + Clone { - fn intern(db: &impl InternDatabase, loc: ItemLoc) -> Self; - fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc; - - fn from_ast_id(ctx: LocationCtx<&impl InternDatabase>, ast_id: FileAstId) -> Self { - let loc = ItemLoc { module: ctx.module, ast_id: AstId::new(ctx.file_id, ast_id) }; - Self::intern(ctx.db, loc) - } - fn source(self, db: &(impl AstDatabase + InternDatabase)) -> InFile { - let loc = self.lookup_intern(db); - let value = loc.ast_id.to_node(db); - InFile { file_id: loc.ast_id.file_id, value } - } - fn module(self, db: &impl InternDatabase) -> ModuleId { - let loc = self.lookup_intern(db); - loc.module - } -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(salsa::InternId); impl_intern_key!(FunctionId); From 8e65b773874909985b6ffc9247ea9dfbaac6a02b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 15:50:16 +0100 Subject: [PATCH 139/312] Dedupe from_source impls --- crates/ra_hir/src/from_source.rs | 111 ++++++++++--------------------- crates/ra_hir_def/src/keys.rs | 2 +- 2 files changed, 35 insertions(+), 78 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index f7411c5cf1..7abb4bd75a 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,7 +1,8 @@ //! FIXME: write short doc here use hir_def::{ - child_by_source::ChildBySource, dyn_map::DynMap, keys, nameres::ModuleSource, EnumVariantId, - GenericDefId, ModuleId, VariantId, + child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, + ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, + TraitId, TypeAliasId, UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -20,80 +21,46 @@ pub trait FromSource: Sized { fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option; } -impl FromSource for Struct { - type Ast = ast::StructDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STRUCT] - .get(&src) - .copied() - .map(Struct::from) - } +pub trait FromSourceByContainer: Sized { + type Ast: AstNode + 'static; + type Id: Copy + 'static; + const KEY: Key; } -impl FromSource for Union { - type Ast = ast::UnionDef; + +impl FromSource for T +where + T: From<::Id>, +{ + type Ast = ::Ast; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::UNION] + analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] .get(&src) .copied() - .map(Union::from) - } -} -impl FromSource for Enum { - type Ast = ast::EnumDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::ENUM] - .get(&src) - .copied() - .map(Enum::from) - } -} -impl FromSource for Trait { - type Ast = ast::TraitDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TRAIT] - .get(&src) - .copied() - .map(Trait::from) - } -} -impl FromSource for Function { - type Ast = ast::FnDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::FUNCTION] - .get(&src) - .copied() - .map(Function::from) + .map(Self::from) } } -impl FromSource for Const { - type Ast = ast::ConstDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::CONST] - .get(&src) - .copied() - .map(Const::from) - } -} -impl FromSource for Static { - type Ast = ast::StaticDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::STATIC] - .get(&src) - .copied() - .map(Static::from) - } +macro_rules! from_source_by_container_impls { + ($(($hir:ident, $id:ident, $ast:path, $key:path)),* ,) => {$( + impl FromSourceByContainer for $hir { + type Ast = $ast; + type Id = $id; + const KEY: Key = $key; + } + )*} } -impl FromSource for TypeAlias { - type Ast = ast::TypeAliasDef; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::TYPE_ALIAS] - .get(&src) - .copied() - .map(TypeAlias::from) - } -} +from_source_by_container_impls![ + (Struct, StructId, ast::StructDef, keys::STRUCT), + (Union, UnionId, ast::UnionDef, keys::UNION), + (Enum, EnumId, ast::EnumDef, keys::ENUM), + (Trait, TraitId, ast::TraitDef, keys::TRAIT), + (Function, FunctionId, ast::FnDef, keys::FUNCTION), + (Static, StaticId, ast::StaticDef, keys::STATIC), + (Const, ConstId, ast::ConstDef, keys::CONST), + (TypeAlias, TypeAliasId, ast::TypeAliasDef, keys::TYPE_ALIAS), + (ImplBlock, ImplId, ast::ImplBlock, keys::IMPL), +]; impl FromSource for MacroDef { type Ast = ast::MacroCall; @@ -111,16 +78,6 @@ impl FromSource for MacroDef { } } -impl FromSource for ImplBlock { - type Ast = ast::ImplBlock; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { - analyze_container(db, src.as_ref().map(|it| it.syntax()))[keys::IMPL] - .get(&src) - .copied() - .map(ImplBlock::from) - } -} - impl FromSource for EnumVariant { type Ast = ast::EnumVariant; fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { diff --git a/crates/ra_hir_def/src/keys.rs b/crates/ra_hir_def/src/keys.rs index 4611c6e386..d844f7a627 100644 --- a/crates/ra_hir_def/src/keys.rs +++ b/crates/ra_hir_def/src/keys.rs @@ -12,7 +12,7 @@ use crate::{ TypeAliasId, TypeParamId, UnionId, }; -type Key = crate::dyn_map::Key, V, AstPtrPolicy>; +pub type Key = crate::dyn_map::Key, V, AstPtrPolicy>; pub const FUNCTION: Key = Key::new(); pub const CONST: Key = Key::new(); From 125559c14b0e85bb69e9b2759d7ecd33a73ea443 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 17:15:57 +0100 Subject: [PATCH 140/312] Move use tree lowering to a separate module --- crates/ra_hir_def/src/path.rs | 107 +--------------------- crates/ra_hir_def/src/path/lower_use.rs | 115 ++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 104 deletions(-) create mode 100644 crates/ra_hir_def/src/path/lower_use.rs diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index e547b2f03c..ddb53ee7cc 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -1,4 +1,5 @@ //! A desugared representation of paths like `crate::foo` or `::bar`. +mod lower_use; use std::{iter, sync::Arc}; @@ -9,7 +10,7 @@ use hir_expand::{ }; use ra_db::CrateId; use ra_syntax::{ - ast::{self, NameOwner, TypeAscriptionOwner}, + ast::{self, TypeAscriptionOwner}, AstNode, }; @@ -72,7 +73,7 @@ impl Path { mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), ) { if let Some(tree) = item_src.value.use_tree() { - expand_use_tree(None, tree, hygiene, &mut cb); + lower_use::lower_use_tree(None, tree, hygiene, &mut cb); } } @@ -296,108 +297,6 @@ impl From for Path { } } -fn expand_use_tree( - prefix: Option, - tree: ast::UseTree, - hygiene: &Hygiene, - cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option), -) { - if let Some(use_tree_list) = tree.use_tree_list() { - let prefix = match tree.path() { - // E.g. use something::{{{inner}}}; - None => prefix, - // E.g. `use something::{inner}` (prefix is `None`, path is `something`) - // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) - Some(path) => match convert_path(prefix, path, hygiene) { - Some(it) => Some(it), - None => return, // FIXME: report errors somewhere - }, - }; - for child_tree in use_tree_list.use_trees() { - expand_use_tree(prefix.clone(), child_tree, hygiene, cb); - } - } else { - let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); - if let Some(ast_path) = tree.path() { - // Handle self in a path. - // E.g. `use something::{self, <...>}` - if ast_path.qualifier().is_none() { - if let Some(segment) = ast_path.segment() { - if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { - if let Some(prefix) = prefix { - cb(prefix, &tree, false, alias); - return; - } - } - } - } - if let Some(path) = convert_path(prefix, ast_path, hygiene) { - let is_glob = tree.has_star(); - cb(path, &tree, is_glob, alias) - } - // FIXME: report errors somewhere - // We get here if we do - } - } -} - -fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Option { - let prefix = if let Some(qual) = path.qualifier() { - Some(convert_path(prefix, qual, hygiene)?) - } else { - prefix - }; - - let segment = path.segment()?; - let res = match segment.kind()? { - ast::PathSegmentKind::Name(name_ref) => { - match hygiene.name_ref_to_name(name_ref) { - Either::Left(name) => { - // no type args in use - let mut res = prefix.unwrap_or_else(|| Path { - kind: PathKind::Plain, - segments: Vec::with_capacity(1), - }); - res.segments.push(PathSegment { - name, - args_and_bindings: None, // no type args in use - }); - res - } - Either::Right(crate_id) => { - return Some(Path::from_simple_segments( - PathKind::DollarCrate(crate_id), - iter::empty(), - )) - } - } - } - ast::PathSegmentKind::CrateKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Crate, iter::empty()) - } - ast::PathSegmentKind::SelfKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Self_, iter::empty()) - } - ast::PathSegmentKind::SuperKw => { - if prefix.is_some() { - return None; - } - Path::from_simple_segments(PathKind::Super, iter::empty()) - } - ast::PathSegmentKind::Type { .. } => { - // not allowed in imports - return None; - } - }; - Some(res) -} - pub mod known { use hir_expand::name; diff --git a/crates/ra_hir_def/src/path/lower_use.rs b/crates/ra_hir_def/src/path/lower_use.rs new file mode 100644 index 0000000000..e2e1f716dc --- /dev/null +++ b/crates/ra_hir_def/src/path/lower_use.rs @@ -0,0 +1,115 @@ +//! Lowers a single complex use like `use foo::{bar, baz};` into a list of paths like +//! `foo::bar`, `foo::baz`; + +use std::iter; + +use either::Either; +use hir_expand::{ + hygiene::Hygiene, + name::{AsName, Name}, +}; +use ra_syntax::ast::{self, NameOwner}; + +use crate::path::{Path, PathKind, PathSegment}; + +pub(crate) fn lower_use_tree( + prefix: Option, + tree: ast::UseTree, + hygiene: &Hygiene, + cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option), +) { + if let Some(use_tree_list) = tree.use_tree_list() { + let prefix = match tree.path() { + // E.g. use something::{{{inner}}}; + None => prefix, + // E.g. `use something::{inner}` (prefix is `None`, path is `something`) + // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`) + Some(path) => match convert_path(prefix, path, hygiene) { + Some(it) => Some(it), + None => return, // FIXME: report errors somewhere + }, + }; + for child_tree in use_tree_list.use_trees() { + lower_use_tree(prefix.clone(), child_tree, hygiene, cb); + } + } else { + let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); + if let Some(ast_path) = tree.path() { + // Handle self in a path. + // E.g. `use something::{self, <...>}` + if ast_path.qualifier().is_none() { + if let Some(segment) = ast_path.segment() { + if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { + if let Some(prefix) = prefix { + cb(prefix, &tree, false, alias); + return; + } + } + } + } + if let Some(path) = convert_path(prefix, ast_path, hygiene) { + let is_glob = tree.has_star(); + cb(path, &tree, is_glob, alias) + } + // FIXME: report errors somewhere + // We get here if we do + } + } +} + +fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Option { + let prefix = if let Some(qual) = path.qualifier() { + Some(convert_path(prefix, qual, hygiene)?) + } else { + prefix + }; + + let segment = path.segment()?; + let res = match segment.kind()? { + ast::PathSegmentKind::Name(name_ref) => { + match hygiene.name_ref_to_name(name_ref) { + Either::Left(name) => { + // no type args in use + let mut res = prefix.unwrap_or_else(|| Path { + kind: PathKind::Plain, + segments: Vec::with_capacity(1), + }); + res.segments.push(PathSegment { + name, + args_and_bindings: None, // no type args in use + }); + res + } + Either::Right(crate_id) => { + return Some(Path::from_simple_segments( + PathKind::DollarCrate(crate_id), + iter::empty(), + )) + } + } + } + ast::PathSegmentKind::CrateKw => { + if prefix.is_some() { + return None; + } + Path::from_simple_segments(PathKind::Crate, iter::empty()) + } + ast::PathSegmentKind::SelfKw => { + if prefix.is_some() { + return None; + } + Path::from_simple_segments(PathKind::Self_, iter::empty()) + } + ast::PathSegmentKind::SuperKw => { + if prefix.is_some() { + return None; + } + Path::from_simple_segments(PathKind::Super, iter::empty()) + } + ast::PathSegmentKind::Type { .. } => { + // not allowed in imports + return None; + } + }; + Some(res) +} From 332f2205b092744265914a4064b61161ba368df3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 12 Dec 2019 17:17:57 +0100 Subject: [PATCH 141/312] Correct obsolete comment --- crates/ra_hir_def/src/path.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ddb53ee7cc..ec9d13e827 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -29,8 +29,7 @@ pub struct PathSegment { } /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This -/// can (in the future) also include bindings of associated types, like in -/// `Iterator`. +/// also includes bindings of associated types, like in `Iterator`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GenericArgs { pub args: Vec, From 47f2b5d0d9f8206f02924b305cde60404813e8b5 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 13 Dec 2019 02:39:14 +0800 Subject: [PATCH 142/312] Map first and last node in original_range --- crates/ra_ide/src/expand.rs | 49 +++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 216d5cfec7..661628ae46 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -3,7 +3,7 @@ use std::iter::successors; use hir::InFile; use ra_db::FileId; -use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken}; +use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; use crate::{db::RootDatabase, FileRange}; @@ -17,26 +17,45 @@ pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Fi } Some(it) => it, }; - // FIXME: the following completely wrong. - // - // *First*, we should try to map first and last tokens of node, and, if that - // fails, return the range of the overall macro expansions. - // - // *Second*, we should handle recurside macro expansions + // FIXME: We should handle recurside macro expansions - let token = node - .value - .descendants_with_tokens() - .filter_map(|it| it.into_token()) - .find_map(|it| expansion.map_token_up(node.with_value(&it))); + let range = node.value.descendants_with_tokens().find_map(|it| { + match it.as_token() { + // FIXME: Remove this branch after all `tt::TokenTree`s have a proper `TokenId`, + // and return the range of the overall macro expansions if mapping first and last tokens fails. + Some(token) => { + let token = expansion.map_token_up(node.with_value(&token))?; + Some(token.with_value(token.value.text_range())) + } + None => { + // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens + let n = it.into_node()?; + let first = expansion.map_token_up(node.with_value(&n.first_token()?))?; + let last = expansion.map_token_up(node.with_value(&n.last_token()?))?; - match token { - Some(it) => { - FileRange { file_id: it.file_id.original_file(db), range: it.value.text_range() } + // FIXME: Is is possible ? + if first.file_id != last.file_id { + return None; + } + + // FIXME: Add union method in TextRange + let range = union_range(first.value.text_range(), last.value.text_range()); + Some(first.with_value(range)) + } } + }); + + return match range { + Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.value }, None => { FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } } + }; + + fn union_range(a: TextRange, b: TextRange) -> TextRange { + let start = a.start().min(b.start()); + let end = a.end().max(b.end()); + TextRange::from_to(start, end) } } From af4eb266457eb784010da28d80535f9fd38d4d1e Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 13 Dec 2019 18:16:34 +0800 Subject: [PATCH 143/312] Support setting cargo features --- crates/ra_batch/src/lib.rs | 2 +- crates/ra_lsp_server/src/config.rs | 5 ++ crates/ra_lsp_server/src/main_loop.rs | 1 + .../ra_project_model/src/cargo_workspace.rs | 31 +++++++- crates/ra_project_model/src/lib.rs | 14 ++-- editors/code/package.json | 15 ++++ editors/code/src/config.ts | 70 +++++++++++++++---- editors/code/src/server.ts | 1 + 8 files changed, 118 insertions(+), 21 deletions(-) diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs index 2c9645c00a..7744ba85a2 100644 --- a/crates/ra_batch/src/lib.rs +++ b/crates/ra_batch/src/lib.rs @@ -22,7 +22,7 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId { pub fn load_cargo(root: &Path) -> Result<(AnalysisHost, FxHashMap)> { let root = std::env::current_dir()?.join(root); - let ws = ProjectWorkspace::discover(root.as_ref())?; + let ws = ProjectWorkspace::discover(root.as_ref(), &Default::default())?; let project_roots = ws.to_roots(); let (sender, receiver) = unbounded(); let sender = Box::new(move |t| sender.send(t).unwrap()); diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 8045f3d60d..67942aa414 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs @@ -9,6 +9,7 @@ use rustc_hash::FxHashMap; +use ra_project_model::CargoFeatures; use serde::{Deserialize, Deserializer}; /// Client provided initialization options @@ -37,6 +38,9 @@ pub struct ServerConfig { /// Fine grained feature flags to disable specific features. pub feature_flags: FxHashMap, + + /// Cargo feature configurations. + pub cargo_features: CargoFeatures, } impl Default for ServerConfig { @@ -49,6 +53,7 @@ impl Default for ServerConfig { max_inlay_hint_length: None, with_sysroot: true, feature_flags: FxHashMap::default(), + cargo_features: Default::default(), } } } diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 158cac0be1..965e7c53c1 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -67,6 +67,7 @@ pub fn main_loop( let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot( ws_root.as_path(), config.with_sysroot, + &config.cargo_features, ); match workspace { Ok(workspace) => loaded_workspaces.push(workspace), diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 351997dcdb..4a0437da32 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -6,6 +6,7 @@ use cargo_metadata::{CargoOpt, MetadataCommand}; use ra_arena::{impl_arena_id, Arena, RawId}; use ra_db::Edition; use rustc_hash::FxHashMap; +use serde::Deserialize; use crate::Result; @@ -23,6 +24,20 @@ pub struct CargoWorkspace { pub(crate) workspace_root: PathBuf, } +#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)] +#[serde(rename_all = "camelCase", default)] +pub struct CargoFeatures { + /// Do not activate the `default` feature. + pub no_default_features: bool, + + /// Activate all available features + pub all_features: bool, + + /// List of features to activate. + /// This will be ignored if `cargo_all_features` is true. + pub features: Vec, +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Package(RawId); impl_arena_id!(Package); @@ -132,9 +147,21 @@ impl Target { } impl CargoWorkspace { - pub fn from_cargo_metadata(cargo_toml: &Path) -> Result { + pub fn from_cargo_metadata( + cargo_toml: &Path, + cargo_features: &CargoFeatures, + ) -> Result { let mut meta = MetadataCommand::new(); - meta.manifest_path(cargo_toml).features(CargoOpt::AllFeatures); + meta.manifest_path(cargo_toml); + if cargo_features.all_features { + meta.features(CargoOpt::AllFeatures); + } else if cargo_features.no_default_features { + // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` + // https://github.com/oli-obk/cargo_metadata/issues/79 + meta.features(CargoOpt::NoDefaultFeatures); + } else { + meta.features(CargoOpt::SomeFeatures(cargo_features.features.clone())); + } if let Some(parent) = cargo_toml.parent() { meta.current_dir(parent); } diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 55ff4d6efc..d71b7031a8 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs @@ -18,7 +18,7 @@ use rustc_hash::FxHashMap; use serde_json::from_reader; pub use crate::{ - cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, + cargo_workspace::{CargoFeatures, CargoWorkspace, Package, Target, TargetKind}, json_project::JsonProject, sysroot::Sysroot, }; @@ -60,11 +60,15 @@ impl PackageRoot { } impl ProjectWorkspace { - pub fn discover(path: &Path) -> Result { - ProjectWorkspace::discover_with_sysroot(path, true) + pub fn discover(path: &Path, cargo_features: &CargoFeatures) -> Result { + ProjectWorkspace::discover_with_sysroot(path, true, cargo_features) } - pub fn discover_with_sysroot(path: &Path, with_sysroot: bool) -> Result { + pub fn discover_with_sysroot( + path: &Path, + with_sysroot: bool, + cargo_features: &CargoFeatures, + ) -> Result { match find_rust_project_json(path) { Some(json_path) => { let file = File::open(json_path)?; @@ -73,7 +77,7 @@ impl ProjectWorkspace { } None => { let cargo_toml = find_cargo_toml(path)?; - let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; + let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?; let sysroot = if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() }; Ok(ProjectWorkspace::Cargo { cargo, sysroot }) diff --git a/editors/code/package.json b/editors/code/package.json index 7bc08ec31f..8ed95fda7e 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -278,6 +278,21 @@ "type": "number", "default": 20, "description": "Maximum length for inlay hints" + }, + "rust-analyzer.cargoFeatures.noDefaultFeatures": { + "type": "boolean", + "default": false, + "description": "Do not activate the `default` feature" + }, + "rust-analyzer.cargoFeatures.allFeatures": { + "type": "boolean", + "default": false, + "description": "Activate all available features" + }, + "rust-analyzer.cargoFeatures.features": { + "type": "array", + "default": [], + "description": "List of features to activate" } } }, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 2d3b6a54ea..6d709f7a85 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -15,6 +15,12 @@ export interface CargoWatchOptions { ignore: string[]; } +export interface CargoFeatures { + noDefaultFeatures: boolean; + allFeatures: boolean; + features: string[]; +} + export class Config { public highlightingOn = true; public rainbowHighlightingOn = false; @@ -35,8 +41,14 @@ export class Config { command: '', ignore: [], }; + public cargoFeatures: CargoFeatures = { + noDefaultFeatures: false, + allFeatures: false, + features: [], + }; private prevEnhancedTyping: null | boolean = null; + private prevCargoFeatures: null | CargoFeatures = null; constructor() { vscode.workspace.onDidChangeConfiguration(_ => @@ -47,6 +59,8 @@ export class Config { public userConfigChanged() { const config = vscode.workspace.getConfiguration('rust-analyzer'); + let requireReloadMessage = null; + if (config.has('highlightingOn')) { this.highlightingOn = config.get('highlightingOn') as boolean; } @@ -74,19 +88,7 @@ export class Config { } if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { - const reloadAction = 'Reload now'; - vscode.window - .showInformationMessage( - 'Changing enhanced typing setting requires a reload', - reloadAction, - ) - .then(selectedAction => { - if (selectedAction === reloadAction) { - vscode.commands.executeCommand( - 'workbench.action.reloadWindow', - ); - } - }); + requireReloadMessage = 'Changing enhanced typing setting requires a reload'; this.prevEnhancedTyping = this.enableEnhancedTyping; } @@ -153,5 +155,47 @@ export class Config { if (config.has('withSysroot')) { this.withSysroot = config.get('withSysroot') || false; } + + if (config.has('cargoFeatures.noDefaultFeatures')) { + this.cargoFeatures.noDefaultFeatures = config.get( + 'cargoFeatures.noDefaultFeatures', + false, + ); + } + if (config.has('cargoFeatures.allFeatures')) { + this.cargoFeatures.allFeatures = config.get( + 'cargoFeatures.allFeatures', + false, + ); + } + if (config.has('cargoFeatures.features')) { + this.cargoFeatures.features = config.get( + 'cargoFeatures.features', + [], + ); + } + + if (this.prevCargoFeatures !== null && ( + this.cargoFeatures.allFeatures !== this.prevCargoFeatures.allFeatures || + this.cargoFeatures.noDefaultFeatures !== this.prevCargoFeatures.noDefaultFeatures || + this.cargoFeatures.features.length !== this.prevCargoFeatures.features.length || + this.cargoFeatures.features.some((v, i) => v !== this.prevCargoFeatures!.features[i]) + )) { + requireReloadMessage = 'Changing cargo features requires a reload'; + } + this.prevCargoFeatures = { ...this.cargoFeatures }; + + if (requireReloadMessage !== null) { + const reloadAction = 'Reload now'; + vscode.window + .showInformationMessage(requireReloadMessage, reloadAction) + .then(selectedAction => { + if (selectedAction === reloadAction) { + vscode.commands.executeCommand( + 'workbench.action.reloadWindow', + ); + } + }); + } } } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 2fe45f1ed6..5ace1d0fae 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -59,6 +59,7 @@ export class Server { useClientWatching: Server.config.useClientWatching, featureFlags: Server.config.featureFlags, withSysroot: Server.config.withSysroot, + cargoFeatures: Server.config.cargoFeatures, }, traceOutputChannel, }; From 95dc2de8e979264e1c76ce5594e8a63547a7956e Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Fri, 13 Dec 2019 12:44:07 +0100 Subject: [PATCH 144/312] Add helper for resolving associated type of trait in infer --- crates/ra_hir_ty/src/infer.rs | 18 ++++++++++ crates/ra_hir_ty/src/infer/expr.rs | 54 ++++-------------------------- 2 files changed, 25 insertions(+), 47 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index d16f1eb46d..62d5c8803c 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -338,6 +338,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.table.resolve_ty_shallow(ty) } + fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option) -> Ty { + match assoc_ty { + Some(res_assoc_ty) => { + let ty = self.table.new_type_var(); + let projection = ProjectionPredicate { + ty: ty.clone(), + projection_ty: ProjectionTy { + associated_ty: res_assoc_ty, + parameters: Substs::single(inner_ty), + }, + }; + self.obligations.push(Obligation::Projection(projection)); + self.resolve_ty_as_possible(ty) + } + None => Ty::Unknown, + } + } + /// Recurses through the given type, normalizing associated types mentioned /// in it by replacing them by type variables and registering obligations to /// resolve later. This should be done once for every type we get from some diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 2c296987c8..6110f5abd3 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -19,8 +19,8 @@ use crate::{ method_resolution, op, traits::InEnvironment, utils::{generics, variant_data, Generics}, - CallableDef, InferTy, IntTy, Mutability, Obligation, ProjectionPredicate, ProjectionTy, Substs, - TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, + ApplicationTy, CallableDef, InferTy, IntTy, Mutability, Obligation, Substs, TraitRef, Ty, + TypeCtor, TypeWalk, Uncertain, }; use super::{BindingMode, Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch}; @@ -95,21 +95,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::For { iterable, body, pat } => { let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); - let pat_ty = match self.resolve_into_iter_item() { - Some(into_iter_item_alias) => { - let pat_ty = self.table.new_type_var(); - let projection = ProjectionPredicate { - ty: pat_ty.clone(), - projection_ty: ProjectionTy { - associated_ty: into_iter_item_alias, - parameters: Substs::single(iterable_ty), - }, - }; - self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(pat_ty) - } - None => Ty::Unknown, - }; + let pat_ty = + self.resolve_associated_type(iterable_ty, self.resolve_into_iter_item()); self.infer_pat(*pat, &pat_ty, BindingMode::default()); self.infer_expr(*body, &Expectation::has_type(Ty::unit())); @@ -284,40 +271,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } Expr::Await { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); - let ty = match self.resolve_future_future_output() { - Some(future_future_output_alias) => { - let ty = self.table.new_type_var(); - let projection = ProjectionPredicate { - ty: ty.clone(), - projection_ty: ProjectionTy { - associated_ty: future_future_output_alias, - parameters: Substs::single(inner_ty), - }, - }; - self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(ty) - } - None => Ty::Unknown, - }; + let ty = + self.resolve_associated_type(inner_ty, self.resolve_future_future_output()); ty } Expr::Try { expr } => { let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); - let ty = match self.resolve_ops_try_ok() { - Some(ops_try_ok_alias) => { - let ty = self.table.new_type_var(); - let projection = ProjectionPredicate { - ty: ty.clone(), - projection_ty: ProjectionTy { - associated_ty: ops_try_ok_alias, - parameters: Substs::single(inner_ty), - }, - }; - self.obligations.push(Obligation::Projection(projection)); - self.resolve_ty_as_possible(ty) - } - None => Ty::Unknown, - }; + let ty = self.resolve_associated_type(inner_ty, self.resolve_ops_try_ok()); ty } Expr::Cast { expr, type_ref } => { From 77052090515c1bb2a00236b3a57cdd778e581c8c Mon Sep 17 00:00:00 2001 From: Emil Lauridsen Date: Fri, 13 Dec 2019 12:44:42 +0100 Subject: [PATCH 145/312] Correctly infer - and ! using std::ops::{Neg,Not} --- crates/ra_hir_def/src/path.rs | 8 ++++ crates/ra_hir_expand/src/name.rs | 2 + crates/ra_hir_ty/src/infer.rs | 16 ++++++- crates/ra_hir_ty/src/infer/expr.rs | 47 +++++++++++--------- crates/ra_hir_ty/src/tests/traits.rs | 64 ++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 23 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index ec9d13e827..50f0cad94f 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -342,6 +342,14 @@ pub mod known { ) } + pub fn std_ops_neg() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NEG_TYPE]) + } + + pub fn std_ops_not() -> Path { + Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NOT_TYPE]) + } + pub fn std_result_result() -> Path { Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) } diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 4f2f702c01..9e68dd98d7 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -152,6 +152,8 @@ pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive") pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive"); pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo"); pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range"); +pub const NEG_TYPE: Name = Name::new_inline_ascii(b"Neg"); +pub const NOT_TYPE: Name = Name::new_inline_ascii(b"Not"); // Builtin Macros pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file"); diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 62d5c8803c..a1201b3e47 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -36,8 +36,8 @@ use ra_prof::profile; use super::{ primitive::{FloatTy, IntTy}, traits::{Guidance, Obligation, ProjectionPredicate, Solution}, - ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk, - Uncertain, + ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, + TypeWalk, Uncertain, }; use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; @@ -433,6 +433,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE) } + fn resolve_ops_neg_output(&self) -> Option { + let path = known::std_ops_neg(); + let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) + } + + fn resolve_ops_not_output(&self) -> Option { + let path = known::std_ops_not(); + let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) + } + fn resolve_future_future_output(&self) -> Option { let path = known::std_future_future(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 6110f5abd3..f8c00a7b4a 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -332,31 +332,36 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { }, UnaryOp::Neg => { match &inner_ty { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Int(Uncertain::Unknown) - | TypeCtor::Int(Uncertain::Known(IntTy { - signedness: Signedness::Signed, - .. - })) - | TypeCtor::Float(..) => inner_ty, - _ => Ty::Unknown, - }, - Ty::Infer(InferTy::IntVar(..)) | Ty::Infer(InferTy::FloatVar(..)) => { - inner_ty - } - // FIXME: resolve ops::Neg trait - _ => Ty::Unknown, + // Fast path for builtins + Ty::Apply(ApplicationTy { + ctor: + TypeCtor::Int(Uncertain::Known(IntTy { + signedness: Signedness::Signed, + .. + })), + .. + }) + | Ty::Apply(ApplicationTy { + ctor: TypeCtor::Int(Uncertain::Unknown), + .. + }) + | Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(_), .. }) + | Ty::Infer(InferTy::IntVar(..)) + | Ty::Infer(InferTy::FloatVar(..)) => inner_ty, + // Otherwise we resolve via the std::ops::Neg trait + _ => self + .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()), } } UnaryOp::Not => { match &inner_ty { - Ty::Apply(a_ty) => match a_ty.ctor { - TypeCtor::Bool | TypeCtor::Int(_) => inner_ty, - _ => Ty::Unknown, - }, - Ty::Infer(InferTy::IntVar(..)) => inner_ty, - // FIXME: resolve ops::Not trait for inner_ty - _ => Ty::Unknown, + // Fast path for builtins + Ty::Apply(ApplicationTy { ctor: TypeCtor::Bool, .. }) + | Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(_), .. }) + | Ty::Infer(InferTy::IntVar(..)) => inner_ty, + // Otherwise we resolve via the std::ops::Not trait + _ => self + .resolve_associated_type(inner_ty, self.resolve_ops_not_output()), } } } diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 93c5f9a15a..6139adb72e 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -115,6 +115,70 @@ mod collections { assert_eq!("&str", type_at_pos(&db, pos)); } +#[test] +fn infer_ops_neg() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +struct Bar; +struct Foo; + +impl std::ops::Neg for Bar { + type Output = Foo; +} + +fn test() { + let a = Bar; + let b = -a; + b<|>; +} + +//- /std.rs crate:std + +#[prelude_import] use ops::*; +mod ops { + pub trait Neg { + type Output; + } +} +"#, + ); + assert_eq!("Foo", type_at_pos(&db, pos)); +} + +#[test] +fn infer_ops_not() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +struct Bar; +struct Foo; + +impl std::ops::Not for Bar { + type Output = Foo; +} + +fn test() { + let a = Bar; + let b = !a; + b<|>; +} + +//- /std.rs crate:std + +#[prelude_import] use ops::*; +mod ops { + pub trait Not { + type Output; + } +} +"#, + ); + assert_eq!("Foo", type_at_pos(&db, pos)); +} + #[test] fn infer_from_bound_1() { assert_snapshot!( From 98f98cbb5404385703a404547aa2477d4a2fd1cb Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 13 Dec 2019 21:53:34 +0800 Subject: [PATCH 146/312] Refactor tt::Delimiter --- crates/ra_hir_expand/src/quote.rs | 7 ++-- crates/ra_mbe/src/lib.rs | 4 +-- crates/ra_mbe/src/mbe_expander/matcher.rs | 6 ++-- crates/ra_mbe/src/mbe_expander/transcriber.rs | 10 +++--- crates/ra_mbe/src/subtree_source.rs | 10 +++--- crates/ra_mbe/src/syntax_bridge.rs | 34 +++++++++---------- crates/ra_mbe/src/tests.rs | 2 +- crates/ra_tt/src/lib.rs | 13 ++++--- 8 files changed, 42 insertions(+), 44 deletions(-) diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 4f698ff134..aa8a5f23fd 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -16,7 +16,7 @@ macro_rules! __quote { { let children = $crate::__quote!($($tt)*); let subtree = tt::Subtree { - delimiter: tt::Delimiter::$delim, + delimiter: Some(tt::Delimiter::$delim), token_trees: $crate::quote::IntoTt::to_tokens(children), }; subtree @@ -124,7 +124,7 @@ pub(crate) trait IntoTt { impl IntoTt for Vec { fn to_subtree(self) -> tt::Subtree { - tt::Subtree { delimiter: tt::Delimiter::None, token_trees: self } + tt::Subtree { delimiter: None, token_trees: self } } fn to_tokens(self) -> Vec { @@ -254,7 +254,8 @@ mod tests { let fields = fields.iter().map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()).flatten(); - let list = tt::Subtree { delimiter: tt::Delimiter::Brace, token_trees: fields.collect() }; + let list = + tt::Subtree { delimiter: Some(tt::Delimiter::Brace), token_trees: fields.collect() }; let quoted = quote! { impl Clone for #struct_name { diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index bbddebe67f..0d2d43bef4 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -159,14 +159,14 @@ impl Rule { .expect_subtree() .map_err(|()| ParseError::Expected("expected subtree".to_string()))? .clone(); - lhs.delimiter = tt::Delimiter::None; + lhs.delimiter = None; src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; let mut rhs = src .expect_subtree() .map_err(|()| ParseError::Expected("expected subtree".to_string()))? .clone(); - rhs.delimiter = tt::Delimiter::None; + rhs.delimiter = None; Ok(crate::Rule { lhs, rhs }) } } diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 33b9d483d2..3f51364780 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs @@ -16,7 +16,7 @@ impl Bindings { fn push_optional(&mut self, name: &SmolStr) { // FIXME: Do we have a better way to represent an empty token ? // Insert an empty subtree for empty token - let tt = tt::Subtree { delimiter: tt::Delimiter::None, token_trees: vec![] }.into(); + let tt = tt::Subtree::default().into(); self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt))); } @@ -65,7 +65,7 @@ macro_rules! bail { } pub(super) fn match_(pattern: &tt::Subtree, src: &tt::Subtree) -> Result { - assert!(pattern.delimiter == tt::Delimiter::None); + assert!(pattern.delimiter == None); let mut res = Bindings::default(); let mut src = TtIter::new(src); @@ -210,7 +210,7 @@ impl<'a> TtIter<'a> { 0 => Err(()), 1 => Ok(res[0].clone()), _ => Ok(tt::TokenTree::Subtree(tt::Subtree { - delimiter: tt::Delimiter::None, + delimiter: None, token_trees: res.into_iter().cloned().collect(), })), } diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs index ed094d5bb4..f7636db11b 100644 --- a/crates/ra_mbe/src/mbe_expander/transcriber.rs +++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs @@ -50,7 +50,7 @@ pub(super) fn transcribe( template: &tt::Subtree, bindings: &Bindings, ) -> Result { - assert!(template.delimiter == tt::Delimiter::None); + assert!(template.delimiter == None); let mut ctx = ExpandCtx { bindings: &bindings, nesting: Vec::new(), var_expanded: false }; expand_subtree(&mut ctx, template) } @@ -106,7 +106,7 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result // ``` // We just treat it a normal tokens let tt = tt::Subtree { - delimiter: tt::Delimiter::None, + delimiter: None, token_trees: vec![ tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone }).into(), tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() }) @@ -147,7 +147,7 @@ fn expand_repeat( ctx.var_expanded = false; while let Ok(mut t) = expand_subtree(ctx, template) { - t.delimiter = tt::Delimiter::None; + t.delimiter = None; // if no var expanded in the child, we count it as a fail if !ctx.var_expanded { break; @@ -212,7 +212,7 @@ fn expand_repeat( // Check if it is a single token subtree without any delimiter // e.g {Delimiter:None> ['>'] /Delimiter:None>} - let tt = tt::Subtree { delimiter: tt::Delimiter::None, token_trees: buf }.into(); + let tt = tt::Subtree { delimiter: None, token_trees: buf }.into(); Ok(Fragment::Tokens(tt)) } @@ -225,7 +225,7 @@ fn push_fragment(buf: &mut Vec, fragment: Fragment) { fn push_subtree(buf: &mut Vec, tt: tt::Subtree) { match tt.delimiter { - tt::Delimiter::None => buf.extend(tt.token_trees), + None => buf.extend(tt.token_trees), _ => buf.push(tt.into()), } } diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 7ef45f6dc4..061e9f20b2 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs @@ -114,12 +114,12 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> { } } -fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken { +fn convert_delim(d: Option, closing: bool) -> TtToken { let (kinds, texts) = match d { - tt::Delimiter::Parenthesis => ([T!['('], T![')']], "()"), - tt::Delimiter::Brace => ([T!['{'], T!['}']], "{}"), - tt::Delimiter::Bracket => ([T!['['], T![']']], "[]"), - tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""), + Some(tt::Delimiter::Parenthesis) => ([T!['('], T![')']], "()"), + Some(tt::Delimiter::Brace) => ([T!['{'], T!['}']], "{}"), + Some(tt::Delimiter::Bracket) => ([T!['['], T![']']], "[]"), + None => ([L_DOLLAR, R_DOLLAR], ""), }; let idx = closing as usize; diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 66c1f0337d..b8e2cfc1d8 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -51,7 +51,7 @@ pub fn token_tree_to_syntax_node( ) -> Result<(Parse, TokenMap), ExpandError> { let tmp; let tokens = match tt { - tt::Subtree { delimiter: tt::Delimiter::None, token_trees } => token_trees.as_slice(), + tt::Subtree { delimiter: None, token_trees } => token_trees.as_slice(), _ => { tmp = [tt.clone().into()]; &tmp[..] @@ -121,7 +121,7 @@ fn convert_doc_comment(token: &ra_syntax::SyntaxToken) -> Option Option { // This tree is empty if tt.first_child_or_token().is_none() { - return Some(tt::Subtree { token_trees: vec![], delimiter: tt::Delimiter::None }); + return Some(tt::Subtree { token_trees: vec![], delimiter: None }); } let first_child = tt.first_child_or_token()?; @@ -173,7 +173,7 @@ impl Convertor { .last() .unwrap(); if first_child.kind().is_trivia() { - return Some(tt::Subtree { token_trees: vec![], delimiter: tt::Delimiter::None }); + return Some(tt::Subtree { token_trees: vec![], delimiter: None }); } let last_child = successors(Some(last_child), |it| { @@ -187,10 +187,10 @@ impl Convertor { .unwrap(); let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { - (T!['('], T![')']) => (tt::Delimiter::Parenthesis, true), - (T!['{'], T!['}']) => (tt::Delimiter::Brace, true), - (T!['['], T![']']) => (tt::Delimiter::Bracket, true), - _ => (tt::Delimiter::None, false), + (T!['('], T![')']) => (Some(tt::Delimiter::Parenthesis), true), + (T!['{'], T!['}']) => (Some(tt::Delimiter::Brace), true), + (T!['['], T![']']) => (Some(tt::Delimiter::Bracket), true), + _ => (None, false), }; let mut token_trees = Vec::new(); @@ -246,9 +246,7 @@ impl Convertor { } NodeOrToken::Node(node) => { let child_subtree = self.go(&node)?; - if child_subtree.delimiter == tt::Delimiter::None - && node.kind() != SyntaxKind::TOKEN_TREE - { + if child_subtree.delimiter.is_none() && node.kind() != SyntaxKind::TOKEN_TREE { token_trees.extend(child_subtree.token_trees); } else { token_trees.push(child_subtree.into()); @@ -299,16 +297,16 @@ impl<'a> TtTreeSink<'a> { } } -fn delim_to_str(d: tt::Delimiter, closing: bool) -> SmolStr { +fn delim_to_str(d: Option, closing: bool) -> SmolStr { let texts = match d { - tt::Delimiter::Parenthesis => "()", - tt::Delimiter::Brace => "{}", - tt::Delimiter::Bracket => "[]", - tt::Delimiter::None => "", + Some(tt::Delimiter::Parenthesis) => "()", + Some(tt::Delimiter::Brace) => "{}", + Some(tt::Delimiter::Bracket) => "[]", + None => return "".into(), }; let idx = closing as usize; - let text = if !texts.is_empty() { &texts[idx..texts.len() - (1 - idx)] } else { "" }; + let text = &texts[idx..texts.len() - (1 - idx)]; text.into() } @@ -497,7 +495,7 @@ mod tests { let token_tree = ast::TokenTree::cast(token_tree).unwrap(); let tt = ast_to_token_tree(&token_tree).unwrap().0; - assert_eq!(tt.delimiter, tt::Delimiter::Brace); + assert_eq!(tt.delimiter, Some(tt::Delimiter::Brace)); } #[test] diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 0109a4d980..148cc26254 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -1463,7 +1463,7 @@ pub(crate) fn assert_expansion( let wrapped = ast::SourceFile::parse(&wrapped); let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; - wrapped.delimiter = tt::Delimiter::None; + wrapped.delimiter = None; wrapped }; let (expanded_tree, expected_tree) = match kind { diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 4c00b8f302..e7bfd5fd29 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -48,9 +48,9 @@ pub enum Leaf { } impl_froms!(Leaf: Literal, Punct, Ident); -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)] pub struct Subtree { - pub delimiter: Delimiter, + pub delimiter: Option, pub token_trees: Vec, } @@ -59,7 +59,6 @@ pub enum Delimiter { Parenthesis, Brace, Bracket, - None, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -97,10 +96,10 @@ impl fmt::Display for TokenTree { impl fmt::Display for Subtree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let (l, r) = match self.delimiter { - Delimiter::Parenthesis => ("(", ")"), - Delimiter::Brace => ("{", "}"), - Delimiter::Bracket => ("[", "]"), - Delimiter::None => ("", ""), + Some(Delimiter::Parenthesis) => ("(", ")"), + Some(Delimiter::Brace) => ("{", "}"), + Some(Delimiter::Bracket) => ("[", "]"), + None => ("", ""), }; f.write_str(l)?; let mut needs_space = false; From f56a2a079069edafd74ef92b7e545f18be88b243 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sat, 14 Dec 2019 00:48:47 +0800 Subject: [PATCH 147/312] Enable `allFeatures` by default and fix lints --- editors/code/package.json | 2 +- editors/code/src/config.ts | 25 ++++++++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 8ed95fda7e..e3bb07be79 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -286,7 +286,7 @@ }, "rust-analyzer.cargoFeatures.allFeatures": { "type": "boolean", - "default": false, + "default": true, "description": "Activate all available features" }, "rust-analyzer.cargoFeatures.features": { diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 6d709f7a85..defdfeb9c4 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -43,7 +43,7 @@ export class Config { }; public cargoFeatures: CargoFeatures = { noDefaultFeatures: false, - allFeatures: false, + allFeatures: true, features: [], }; @@ -88,7 +88,8 @@ export class Config { } if (this.prevEnhancedTyping !== this.enableEnhancedTyping) { - requireReloadMessage = 'Changing enhanced typing setting requires a reload'; + requireReloadMessage = + 'Changing enhanced typing setting requires a reload'; this.prevEnhancedTyping = this.enableEnhancedTyping; } @@ -165,7 +166,7 @@ export class Config { if (config.has('cargoFeatures.allFeatures')) { this.cargoFeatures.allFeatures = config.get( 'cargoFeatures.allFeatures', - false, + true, ); } if (config.has('cargoFeatures.features')) { @@ -175,12 +176,18 @@ export class Config { ); } - if (this.prevCargoFeatures !== null && ( - this.cargoFeatures.allFeatures !== this.prevCargoFeatures.allFeatures || - this.cargoFeatures.noDefaultFeatures !== this.prevCargoFeatures.noDefaultFeatures || - this.cargoFeatures.features.length !== this.prevCargoFeatures.features.length || - this.cargoFeatures.features.some((v, i) => v !== this.prevCargoFeatures!.features[i]) - )) { + if ( + this.prevCargoFeatures !== null && + (this.cargoFeatures.allFeatures !== + this.prevCargoFeatures.allFeatures || + this.cargoFeatures.noDefaultFeatures !== + this.prevCargoFeatures.noDefaultFeatures || + this.cargoFeatures.features.length !== + this.prevCargoFeatures.features.length || + this.cargoFeatures.features.some( + (v, i) => v !== this.prevCargoFeatures!.features[i], + )) + ) { requireReloadMessage = 'Changing cargo features requires a reload'; } this.prevCargoFeatures = { ...this.cargoFeatures }; From 30672c420ee19faa1acc15ecc84ae8d17c309e95 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Fri, 13 Dec 2019 19:00:55 +0200 Subject: [PATCH 148/312] scopes resolution is more granular --- crates/ra_ide/src/syntax_highlighting.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 7ecb1a0272..cd9d8b058f 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -108,14 +108,17 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec highlight_name(db, name_kind), None => name.syntax().parent().map_or("function", |x| match x.kind() { - TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", + STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", + TYPE_PARAM => "type.param", RECORD_FIELD_DEF => "field", _ => "function", }), } } - INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", - LIFETIME => "parameter", + INT_NUMBER | FLOAT_NUMBER => "literal.numeric", + BYTE => "literal.byte", + CHAR => "literal.char", + LIFETIME => "lifetime", T![unsafe] => "keyword.unsafe", k if is_control_keyword(k) => "keyword.control", k if k.is_keyword() => "keyword", @@ -215,17 +218,18 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { Field(_) => "field", AssocItem(hir::AssocItem::Function(_)) => "function", AssocItem(hir::AssocItem::Const(_)) => "constant", - AssocItem(hir::AssocItem::TypeAlias(_)) => "type", + AssocItem(hir::AssocItem::TypeAlias(_)) => "type.alias", Def(hir::ModuleDef::Module(_)) => "module", Def(hir::ModuleDef::Function(_)) => "function", Def(hir::ModuleDef::Adt(_)) => "type", Def(hir::ModuleDef::EnumVariant(_)) => "constant", Def(hir::ModuleDef::Const(_)) => "constant", Def(hir::ModuleDef::Static(_)) => "constant", - Def(hir::ModuleDef::Trait(_)) => "type", - Def(hir::ModuleDef::TypeAlias(_)) => "type", - Def(hir::ModuleDef::BuiltinType(_)) => "type", - SelfType(_) | TypeParam(_) => "type", + Def(hir::ModuleDef::Trait(_)) => "type.trait", + Def(hir::ModuleDef::TypeAlias(_)) => "type.alias", + Def(hir::ModuleDef::BuiltinType(_)) => "type.builtin", + SelfType(_) => "type.self", + TypeParam(_) => "type.param", Local(local) => { if local.is_mut(db) { "variable.mut" From 4df741ecb2d00c3d8cdbc37d734ff5514dd5e7b0 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:20:02 +0100 Subject: [PATCH 149/312] fix goto definition when inbetween tokens fixes both goto_definition and goto_type_definition. before, when running goto between some non-trivia token and an identifier, goto would be attempted for the non-trivia token. but this does not make sense for e.g. L_PAREN or COLONCOLON only for IDENTs. now only IDENTs will be searched for in goto actions. --- crates/ra_ide/src/goto_definition.rs | 16 ++++++++++++++-- crates/ra_ide/src/goto_type_definition.rs | 16 ++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index cfe62037fc..96a73675ff 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -3,7 +3,7 @@ use hir::{db::AstDatabase, InFile}; use ra_syntax::{ ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxNode, + match_ast, AstNode, SyntaxKind, SyntaxNode, }; use crate::{ @@ -20,7 +20,7 @@ pub(crate) fn goto_definition( ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; let original_token = - file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; let token = descend_into_macros(db, position.file_id, original_token.clone()); let nav_targets = match_ast! { @@ -234,6 +234,18 @@ mod tests { ); } + #[test] + fn goto_definition_works_at_start_of_item() { + check_goto( + " + //- /lib.rs + struct Foo; + enum E { X(<|>Foo) } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } + #[test] fn goto_definition_resolves_correct_name() { check_goto( diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 992a088090..cc1b90925d 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::db::AstDatabase; -use ra_syntax::{ast, AstNode}; +use ra_syntax::{ast, AstNode, SyntaxKind}; use crate::{ db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, @@ -13,7 +13,7 @@ pub(crate) fn goto_type_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + let token = file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; let token = descend_into_macros(db, position.file_id, token); let node = token.value.ancestors().find_map(|token| { @@ -102,4 +102,16 @@ mod tests { "Foo STRUCT_DEF FileId(1) [52; 65) [59; 62)", ); } + + #[test] + fn goto_type_definition_works_param() { + check_goto( + " + //- /lib.rs + struct Foo; + fn foo(<|>f: Foo) {} + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } } From f54fef85aa88db44b1d3f6436551595dcb98ab83 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:54:02 +0100 Subject: [PATCH 150/312] use find() instead of filter().next() --- crates/ra_ide/src/hover.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index d372ca758e..24f7eeed33 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -156,7 +156,7 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; + let token = file.token_at_offset(position.offset).find(|it| !it.kind().is_trivia())?; let token = descend_into_macros(db, position.file_id, token); let mut res = HoverResult::new(); From 6c42eb1930f179bca1867eebcbf82c7bc10dd4c5 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 19:54:07 +0100 Subject: [PATCH 151/312] add failing test --- crates/ra_ide/src/hover.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 24f7eeed33..b2909bf38a 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -504,6 +504,13 @@ fn func(foo: i32) { if true { <|>foo; }; } assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); } + #[test] + fn hover_for_param_edge() { + let (analysis, position) = single_file_with_position("fn func(<|>foo: i32) {}"); + let hover = analysis.hover(position).unwrap().unwrap(); + assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); + } + #[test] fn test_type_of_for_function() { let (analysis, range) = single_file_with_range( From 6c133017a80c41db361d7870bf57db3e43c4074a Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 21:10:25 +0100 Subject: [PATCH 152/312] try both surrounding tokens for hover --- crates/ra_ide/src/hover.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index b2909bf38a..5b48b1998e 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -1,11 +1,11 @@ //! FIXME: write short doc here -use hir::{db::AstDatabase, Adt, HasSource, HirDisplay}; +use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, InFile}; use ra_db::SourceDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, DocCommentsOwner}, - match_ast, AstNode, + match_ast, AstNode, SyntaxToken, }; use crate::{ @@ -156,9 +156,17 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).find(|it| !it.kind().is_trivia())?; - let token = descend_into_macros(db, position.file_id, token); + file.token_at_offset(position.offset) + .filter(|token| !token.kind().is_trivia()) + .map(|token| descend_into_macros(db, position.file_id, token)) + .find_map(|token| hover_token(db, position, token)) +} +fn hover_token( + db: &RootDatabase, + position: FilePosition, + token: InFile, +) -> Option> { let mut res = HoverResult::new(); let mut range = match_ast! { From 4f7da04c6735e1d00fceb6fc6f83542626ce03c9 Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 21:59:25 +0100 Subject: [PATCH 153/312] add tests for goto on tuple fields --- crates/ra_ide/src/goto_definition.rs | 16 ++++++++++++++++ crates/ra_ide/src/goto_type_definition.rs | 18 +++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 96a73675ff..30118b43fa 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -446,6 +446,22 @@ mod tests { ); } + #[test] + fn goto_for_tuple_fields() { + check_goto( + " + //- /lib.rs + struct Foo(u32); + + fn bar() { + let foo = Foo(0); + foo.<|>0; + } + ", + "TUPLE_FIELD_DEF FileId(1) [11; 14)", + ); + } + #[test] fn goto_definition_works_for_ufcs_inherent_methods() { check_goto( diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index cc1b90925d..5501bb7420 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -104,7 +104,7 @@ mod tests { } #[test] - fn goto_type_definition_works_param() { + fn goto_type_definition_for_param() { check_goto( " //- /lib.rs @@ -114,4 +114,20 @@ mod tests { "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", ); } + + #[test] + fn goto_type_definition_for_tuple_field() { + check_goto( + " + //- /lib.rs + struct Foo; + struct Bar(Foo); + fn foo() { + let bar = Bar(Foo); + bar.<|>0; + } + ", + "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + ); + } } From c82529a97f10b1302d2944f1946bcb3479f64e2d Mon Sep 17 00:00:00 2001 From: succcubbus <16743652+succcubbus@users.noreply.github.com> Date: Fri, 13 Dec 2019 22:00:05 +0100 Subject: [PATCH 154/312] for goto and hover pick the token based on a priority --- crates/ra_ide/src/goto_definition.rs | 18 +++++++++++--- crates/ra_ide/src/goto_type_definition.rs | 15 ++++++++++-- crates/ra_ide/src/hover.rs | 30 ++++++++++++++--------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 30118b43fa..27052d72b6 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -3,7 +3,9 @@ use hir::{db::AstDatabase, InFile}; use ra_syntax::{ ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxKind, SyntaxNode, + match_ast, AstNode, + SyntaxKind::*, + SyntaxNode, SyntaxToken, TokenAtOffset, }; use crate::{ @@ -19,8 +21,7 @@ pub(crate) fn goto_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let original_token = - file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; + let original_token = pick_best(file.token_at_offset(position.offset))?; let token = descend_into_macros(db, position.file_id, original_token.clone()); let nav_targets = match_ast! { @@ -38,6 +39,17 @@ pub(crate) fn goto_definition( Some(RangeInfo::new(original_token.text_range(), nav_targets)) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + #[derive(Debug)] pub(crate) enum ReferenceResult { Exact(NavigationTarget), diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs index 5501bb7420..ce8b6c72a1 100644 --- a/crates/ra_ide/src/goto_type_definition.rs +++ b/crates/ra_ide/src/goto_type_definition.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use hir::db::AstDatabase; -use ra_syntax::{ast, AstNode, SyntaxKind}; +use ra_syntax::{ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset}; use crate::{ db::RootDatabase, display::ToNav, expand::descend_into_macros, FilePosition, NavigationTarget, @@ -13,7 +13,7 @@ pub(crate) fn goto_type_definition( position: FilePosition, ) -> Option>> { let file = db.parse_or_expand(position.file_id.into())?; - let token = file.token_at_offset(position.offset).find(|it| it.kind() == SyntaxKind::IDENT)?; + let token = pick_best(file.token_at_offset(position.offset))?; let token = descend_into_macros(db, position.file_id, token); let node = token.value.ancestors().find_map(|token| { @@ -41,6 +41,17 @@ pub(crate) fn goto_type_definition( Some(RangeInfo::new(node.text_range(), vec![nav])) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + #[cfg(test)] mod tests { use crate::mock_analysis::analysis_and_position; diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 5b48b1998e..51e3201282 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -1,11 +1,13 @@ //! FIXME: write short doc here -use hir::{db::AstDatabase, Adt, HasSource, HirDisplay, InFile}; +use hir::{db::AstDatabase, Adt, HasSource, HirDisplay}; use ra_db::SourceDatabase; use ra_syntax::{ algo::find_covering_element, ast::{self, DocCommentsOwner}, - match_ast, AstNode, SyntaxToken, + match_ast, AstNode, + SyntaxKind::*, + SyntaxToken, TokenAtOffset, }; use crate::{ @@ -156,17 +158,9 @@ fn hover_text_from_name_kind( pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option> { let file = db.parse_or_expand(position.file_id.into())?; - file.token_at_offset(position.offset) - .filter(|token| !token.kind().is_trivia()) - .map(|token| descend_into_macros(db, position.file_id, token)) - .find_map(|token| hover_token(db, position, token)) -} + let token = pick_best(file.token_at_offset(position.offset))?; + let token = descend_into_macros(db, position.file_id, token); -fn hover_token( - db: &RootDatabase, - position: FilePosition, - token: InFile, -) -> Option> { let mut res = HoverResult::new(); let mut range = match_ast! { @@ -226,6 +220,18 @@ fn hover_token( Some(RangeInfo::new(range, res)) } +fn pick_best(tokens: TokenAtOffset) -> Option { + return tokens.max_by_key(priority); + fn priority(n: &SyntaxToken) -> usize { + match n.kind() { + IDENT | INT_NUMBER => 3, + L_PAREN | R_PAREN => 2, + kind if kind.is_trivia() => 0, + _ => 1, + } + } +} + pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { let parse = db.parse(frange.file_id); let leaf_node = find_covering_element(parse.tree().syntax(), frange.range); From a234b5a3cab6e134bfb644f91652532b68195f65 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 13 Dec 2019 16:08:47 -0500 Subject: [PATCH 155/312] LSP 3.15 supports the deprecated tag on completions --- crates/ra_lsp_server/src/conv.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index b13093cfe6..5561f6270b 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -130,6 +130,11 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { deprecated: Some(self.deprecated()), ..Default::default() }; + + if self.deprecated() { + res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated]) + } + res.insert_text_format = Some(match self.insert_text_format() { InsertTextFormat::Snippet => lsp_types::InsertTextFormat::Snippet, InsertTextFormat::PlainText => lsp_types::InsertTextFormat::PlainText, From 259c42f00e2e85594c7373166bc8467ce375a045 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 21:43:53 +0100 Subject: [PATCH 156/312] Add macros for known names and paths --- crates/ra_hir/src/code_model.rs | 4 +- crates/ra_hir_def/src/body/lower.rs | 4 +- crates/ra_hir_def/src/builtin_type.rs | 36 ++--- crates/ra_hir_def/src/data.rs | 4 +- crates/ra_hir_def/src/generics.rs | 6 +- crates/ra_hir_def/src/nameres/collector.rs | 4 +- crates/ra_hir_def/src/path.rs | 45 +++--- crates/ra_hir_def/src/resolver.rs | 16 +-- crates/ra_hir_expand/src/builtin_derive.rs | 26 ++-- crates/ra_hir_expand/src/builtin_macro.rs | 16 +-- crates/ra_hir_expand/src/name.rs | 158 ++++++++++++--------- crates/ra_hir_ty/src/autoderef.rs | 4 +- crates/ra_hir_ty/src/infer.rs | 12 +- crates/ra_hir_ty/src/infer/expr.rs | 4 +- crates/ra_hir_ty/src/traits/builtin.rs | 6 +- crates/ra_hir_ty/src/utils.rs | 6 +- 16 files changed, 185 insertions(+), 166 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index c705d16302..d1153fa628 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -17,7 +17,7 @@ use hir_def::{ }; use hir_expand::{ diagnostics::DiagnosticSink, - name::{self, AsName}, + name::{AsName, N}, MacroDefId, }; use hir_ty::{ @@ -723,7 +723,7 @@ impl Local { } pub fn is_self(self, db: &impl HirDatabase) -> bool { - self.name(db) == Some(name::SELF_PARAM) + self.name(db) == Some(N![self]) } pub fn is_mut(self, db: &impl HirDatabase) -> bool { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index cc068ff94f..6c760166fd 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -2,7 +2,7 @@ //! representation. use either::Either; -use hir_expand::name::{self, AsName, Name}; +use hir_expand::name::{AsName, Name, N}; use ra_arena::Arena; use ra_syntax::{ ast::{ @@ -68,7 +68,7 @@ where let ptr = AstPtr::new(&self_param); let param_pat = self.alloc_pat( Pat::Bind { - name: name::SELF_PARAM, + name: N![self], mode: BindingAnnotation::Unannotated, subpat: None, }, diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs index 5e81571443..757123f824 100644 --- a/crates/ra_hir_def/src/builtin_type.rs +++ b/crates/ra_hir_def/src/builtin_type.rs @@ -5,7 +5,7 @@ use std::fmt; -use hir_expand::name::{self, Name}; +use hir_expand::name::{Name, N}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Signedness { @@ -52,26 +52,26 @@ pub enum BuiltinType { impl BuiltinType { #[rustfmt::skip] pub const ALL: &'static [(Name, BuiltinType)] = &[ - (name::CHAR, BuiltinType::Char), - (name::BOOL, BuiltinType::Bool), - (name::STR, BuiltinType::Str ), + (N![char], BuiltinType::Char), + (N![bool], BuiltinType::Bool), + (N![str], BuiltinType::Str), - (name::ISIZE, BuiltinType::Int(BuiltinInt::ISIZE)), - (name::I8, BuiltinType::Int(BuiltinInt::I8)), - (name::I16, BuiltinType::Int(BuiltinInt::I16)), - (name::I32, BuiltinType::Int(BuiltinInt::I32)), - (name::I64, BuiltinType::Int(BuiltinInt::I64)), - (name::I128, BuiltinType::Int(BuiltinInt::I128)), + (N![isize], BuiltinType::Int(BuiltinInt::ISIZE)), + (N![i8], BuiltinType::Int(BuiltinInt::I8)), + (N![i16], BuiltinType::Int(BuiltinInt::I16)), + (N![i32], BuiltinType::Int(BuiltinInt::I32)), + (N![i64], BuiltinType::Int(BuiltinInt::I64)), + (N![i128], BuiltinType::Int(BuiltinInt::I128)), - (name::USIZE, BuiltinType::Int(BuiltinInt::USIZE)), - (name::U8, BuiltinType::Int(BuiltinInt::U8)), - (name::U16, BuiltinType::Int(BuiltinInt::U16)), - (name::U32, BuiltinType::Int(BuiltinInt::U32)), - (name::U64, BuiltinType::Int(BuiltinInt::U64)), - (name::U128, BuiltinType::Int(BuiltinInt::U128)), + (N![usize], BuiltinType::Int(BuiltinInt::USIZE)), + (N![u8], BuiltinType::Int(BuiltinInt::U8)), + (N![u16], BuiltinType::Int(BuiltinInt::U16)), + (N![u32], BuiltinType::Int(BuiltinInt::U32)), + (N![u64], BuiltinType::Int(BuiltinInt::U64)), + (N![u128], BuiltinType::Int(BuiltinInt::U128)), - (name::F32, BuiltinType::Float(BuiltinFloat::F32)), - (name::F64, BuiltinType::Float(BuiltinFloat::F64)), + (N![f32], BuiltinType::Float(BuiltinFloat::F32)), + (N![f64], BuiltinType::Float(BuiltinFloat::F64)), ]; } diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index b2dac183e3..afeac0ec27 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use hir_expand::{ - name::{self, AsName, Name}, + name::{AsName, Name, N}, AstId, }; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; @@ -37,7 +37,7 @@ impl FunctionData { let self_type = if let Some(type_ref) = self_param.ascribed_type() { TypeRef::from_ast(type_ref) } else { - let self_type = TypeRef::Path(name::SELF_TYPE.into()); + let self_type = TypeRef::Path(N![Self].into()); match self_param.kind() { ast::SelfParamKind::Owned => self_type, ast::SelfParamKind::Ref => { diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index e502dd7983..2b13748f36 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use either::Either; use hir_expand::{ - name::{self, AsName, Name}, + name::{AsName, Name, N}, InFile, }; use ra_arena::{map::ArenaMap, Arena}; @@ -90,11 +90,11 @@ impl GenericParams { // traits get the Self type as an implicit first type parameter let self_param_id = - generics.types.alloc(TypeParamData { name: name::SELF_TYPE, default: None }); + generics.types.alloc(TypeParamData { name: N![Self], default: None }); sm.insert(self_param_id, Either::Left(src.value.clone())); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar - let self_param = TypeRef::Path(name::SELF_TYPE.into()); + let self_param = TypeRef::Path(N![Self].into()); generics.fill_bounds(&src.value, self_param); generics.fill(&mut sm, &src.value); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 04aadead19..e81bac914b 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -6,7 +6,7 @@ use hir_expand::{ builtin_derive::find_builtin_derive, builtin_macro::find_builtin_macro, - name::{self, AsName, Name}, + name::{AsName, Name, N}, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, }; use ra_cfg::CfgOptions; @@ -918,7 +918,7 @@ where } fn is_macro_rules(path: &Path) -> bool { - path.as_ident() == Some(&name::MACRO_RULES) + path.as_ident() == Some(&N![macro_rules]) } #[cfg(test)] diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 50f0cad94f..36ad278678 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{self, AsName, Name}, + name::{AsName, Name, N}, }; use ra_db::CrateId; use ra_syntax::{ @@ -276,7 +276,7 @@ impl GenericArgs { } if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((name::OUTPUT_TYPE, type_ref)) + bindings.push((N![Output], type_ref)) } if args.is_empty() && bindings.is_empty() { None @@ -297,68 +297,63 @@ impl From for Path { } pub mod known { - use hir_expand::name; + use hir_expand::name::N; use super::{Path, PathKind}; + macro_rules! P { + ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![N![$start], $(N![$seg],)*]) }; + } + pub fn std_iter_into_iterator() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE], - ) + P![std::iter::IntoIterator] } pub fn std_ops_try() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE]) + P![std::ops::Try] } pub fn std_ops_range() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE]) + P![std::ops::Range] } pub fn std_ops_range_from() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE]) + P![std::ops::RangeFrom] } pub fn std_ops_range_full() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE]) + P![std::ops::RangeFull] } pub fn std_ops_range_inclusive() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE], - ) + P![std::ops::RangeInclusive] } pub fn std_ops_range_to() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE]) + P![std::ops::RangeTo] } pub fn std_ops_range_to_inclusive() -> Path { - Path::from_simple_segments( - PathKind::Abs, - vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE], - ) + P![std::ops::RangeToInclusive] } pub fn std_ops_neg() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NEG_TYPE]) + P![std::ops::Neg] } pub fn std_ops_not() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::NOT_TYPE]) + P![std::ops::Not] } pub fn std_result_result() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE]) + P![std::result::Result] } pub fn std_future_future() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE]) + P![std::future::Future] } pub fn std_boxed_box() -> Path { - Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE]) + P![std::boxed::Box] } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 17b2169d2a..0fb5295279 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use hir_expand::{ - name::{self, Name}, + name::{Name, N}, MacroDefId, }; use ra_db::CrateId; @@ -163,13 +163,13 @@ impl Resolver { } } Scope::ImplBlockScope(impl_) => { - if first_name == &name::SELF_TYPE { + if first_name == &N![Self] { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some((TypeNs::SelfType(*impl_), idx)); } } Scope::AdtScope(adt) => { - if first_name == &name::SELF_TYPE { + if first_name == &N![Self] { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some((TypeNs::AdtSelfType(*adt), idx)); } @@ -223,7 +223,7 @@ impl Resolver { return None; } let n_segments = path.segments.len(); - let tmp = name::SELF_PARAM; + let tmp = N![self]; let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); for scope in self.scopes.iter().rev() { @@ -259,13 +259,13 @@ impl Resolver { Scope::GenericParams { .. } => continue, Scope::ImplBlockScope(impl_) if n_segments > 1 => { - if first_name == &name::SELF_TYPE { + if first_name == &N![Self] { let ty = TypeNs::SelfType(*impl_); return Some(ResolveValueResult::Partial(ty, 1)); } } Scope::AdtScope(adt) if n_segments > 1 => { - if first_name == &name::SELF_TYPE { + if first_name == &N![Self] { let ty = TypeNs::AdtSelfType(*adt); return Some(ResolveValueResult::Partial(ty, 1)); } @@ -439,10 +439,10 @@ impl Scope { } } Scope::ImplBlockScope(i) => { - f(name::SELF_TYPE, ScopeDef::ImplSelfType((*i).into())); + f(N![Self], ScopeDef::ImplSelfType((*i).into())); } Scope::AdtScope(i) => { - f(name::SELF_TYPE, ScopeDef::AdtSelfType((*i).into())); + f(N![Self], ScopeDef::AdtSelfType((*i).into())); } Scope::ExprScope(scope) => { scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 5746376022..d7f8ada786 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -12,10 +12,10 @@ use crate::db::AstDatabase; use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; macro_rules! register_builtin { - ( $(($name:ident, $kind: ident) => $expand:ident),* ) => { + ( $($trait:ident => $expand:ident),* ) => { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinDeriveExpander { - $($kind),* + $($trait),* } impl BuiltinDeriveExpander { @@ -26,7 +26,7 @@ macro_rules! register_builtin { tt: &tt::Subtree, ) -> Result { let expander = match *self { - $( BuiltinDeriveExpander::$kind => $expand, )* + $( BuiltinDeriveExpander::$trait => $expand, )* }; expander(db, id, tt) } @@ -34,7 +34,7 @@ macro_rules! register_builtin { pub fn find_builtin_derive(ident: &name::Name) -> Option { let kind = match ident { - $( id if id == &name::$name => BuiltinDeriveExpander::$kind, )* + $( id if id == &name::N![$trait] => BuiltinDeriveExpander::$trait, )* _ => return None, }; @@ -44,15 +44,15 @@ macro_rules! register_builtin { } register_builtin! { - (COPY_TRAIT, Copy) => copy_expand, - (CLONE_TRAIT, Clone) => clone_expand, - (DEFAULT_TRAIT, Default) => default_expand, - (DEBUG_TRAIT, Debug) => debug_expand, - (HASH_TRAIT, Hash) => hash_expand, - (ORD_TRAIT, Ord) => ord_expand, - (PARTIAL_ORD_TRAIT, PartialOrd) => partial_ord_expand, - (EQ_TRAIT, Eq) => eq_expand, - (PARTIAL_EQ_TRAIT, PartialEq) => partial_eq_expand + Copy => copy_expand, + Clone => clone_expand, + Default => default_expand, + Debug => debug_expand, + Hash => hash_expand, + Ord => ord_expand, + PartialOrd => partial_ord_expand, + Eq => eq_expand, + PartialEq => partial_eq_expand } struct BasicAdtInfo { diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index be5f3cbe35..e5046ad4cb 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -34,7 +34,7 @@ macro_rules! register_builtin { ast_id: AstId, ) -> Option { let kind = match ident { - $( id if id == &name::$name => BuiltinFnLikeExpander::$kind, )* + $( id if id == &name::N![$name] => BuiltinFnLikeExpander::$kind, )* _ => return None, }; @@ -44,15 +44,15 @@ macro_rules! register_builtin { } register_builtin! { - (COLUMN_MACRO, Column) => column_expand, - (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand, - (FILE_MACRO, File) => file_expand, - (LINE_MACRO, Line) => line_expand, - (STRINGIFY_MACRO, Stringify) => stringify_expand, - (FORMAT_ARGS_MACRO, FormatArgs) => format_args_expand, + (column, Column) => column_expand, + (compile_error, CompileError) => compile_error_expand, + (file, File) => file_expand, + (line, Line) => line_expand, + (stringify, Stringify) => stringify_expand, + (format_args, FormatArgs) => format_args_expand, // format_args_nl only differs in that it adds a newline in the end, // so we use the same stub expansion for now - (FORMAT_ARGS_NL_MACRO, FormatArgsNl) => format_args_expand + (format_args_nl, FormatArgsNl) => format_args_expand } fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 9e68dd98d7..8b3141d75c 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -104,73 +104,99 @@ impl AsName for ra_db::Dependency { } } -// Primitives -pub const ISIZE: Name = Name::new_inline_ascii(b"isize"); -pub const I8: Name = Name::new_inline_ascii(b"i8"); -pub const I16: Name = Name::new_inline_ascii(b"i16"); -pub const I32: Name = Name::new_inline_ascii(b"i32"); -pub const I64: Name = Name::new_inline_ascii(b"i64"); -pub const I128: Name = Name::new_inline_ascii(b"i128"); -pub const USIZE: Name = Name::new_inline_ascii(b"usize"); -pub const U8: Name = Name::new_inline_ascii(b"u8"); -pub const U16: Name = Name::new_inline_ascii(b"u16"); -pub const U32: Name = Name::new_inline_ascii(b"u32"); -pub const U64: Name = Name::new_inline_ascii(b"u64"); -pub const U128: Name = Name::new_inline_ascii(b"u128"); -pub const F32: Name = Name::new_inline_ascii(b"f32"); -pub const F64: Name = Name::new_inline_ascii(b"f64"); -pub const BOOL: Name = Name::new_inline_ascii(b"bool"); -pub const CHAR: Name = Name::new_inline_ascii(b"char"); -pub const STR: Name = Name::new_inline_ascii(b"str"); +pub mod known { + macro_rules! known_names { + ($($ident:ident),* $(,)?) => { + $( + #[allow(bad_style)] + pub const $ident: super::Name = + super::Name::new_inline_ascii(stringify!($ident).as_bytes()); + )* + }; + } -// Special names -pub const SELF_PARAM: Name = Name::new_inline_ascii(b"self"); -pub const SELF_TYPE: Name = Name::new_inline_ascii(b"Self"); -pub const MACRO_RULES: Name = Name::new_inline_ascii(b"macro_rules"); + known_names!( + // Primitives + isize, + i8, + i16, + i32, + i64, + i128, + usize, + u8, + u16, + u32, + u64, + u128, + f32, + f64, + bool, + char, + str, + // Special names + macro_rules, + // Components of known path (value or mod name) + std, + iter, + ops, + future, + result, + boxed, + // Components of known path (type name) + IntoIterator, + Item, + Try, + Ok, + Future, + Result, + Output, + Target, + Box, + RangeFrom, + RangeFull, + RangeInclusive, + RangeToInclusive, + RangeTo, + Range, + Neg, + Not, + // Builtin macros + file, + column, + compile_error, + line, + stringify, + format_args, + format_args_nl, + // Builtin derives + Copy, + Clone, + Default, + Debug, + Hash, + Ord, + PartialOrd, + Eq, + PartialEq, + ); -// Components of known path (value or mod name) -pub const STD: Name = Name::new_inline_ascii(b"std"); -pub const ITER: Name = Name::new_inline_ascii(b"iter"); -pub const OPS: Name = Name::new_inline_ascii(b"ops"); -pub const FUTURE: Name = Name::new_inline_ascii(b"future"); -pub const RESULT: Name = Name::new_inline_ascii(b"result"); -pub const BOXED: Name = Name::new_inline_ascii(b"boxed"); + // self/Self cannot be used as an identifier + pub const SELF_PARAM: super::Name = super::Name::new_inline_ascii(b"self"); + pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self"); -// Components of known path (type name) -pub const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(b"IntoIterator"); -pub const ITEM_TYPE: Name = Name::new_inline_ascii(b"Item"); -pub const TRY_TYPE: Name = Name::new_inline_ascii(b"Try"); -pub const OK_TYPE: Name = Name::new_inline_ascii(b"Ok"); -pub const FUTURE_TYPE: Name = Name::new_inline_ascii(b"Future"); -pub const RESULT_TYPE: Name = Name::new_inline_ascii(b"Result"); -pub const OUTPUT_TYPE: Name = Name::new_inline_ascii(b"Output"); -pub const TARGET_TYPE: Name = Name::new_inline_ascii(b"Target"); -pub const BOX_TYPE: Name = Name::new_inline_ascii(b"Box"); -pub const RANGE_FROM_TYPE: Name = Name::new_inline_ascii(b"RangeFrom"); -pub const RANGE_FULL_TYPE: Name = Name::new_inline_ascii(b"RangeFull"); -pub const RANGE_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeInclusive"); -pub const RANGE_TO_INCLUSIVE_TYPE: Name = Name::new_inline_ascii(b"RangeToInclusive"); -pub const RANGE_TO_TYPE: Name = Name::new_inline_ascii(b"RangeTo"); -pub const RANGE_TYPE: Name = Name::new_inline_ascii(b"Range"); -pub const NEG_TYPE: Name = Name::new_inline_ascii(b"Neg"); -pub const NOT_TYPE: Name = Name::new_inline_ascii(b"Not"); + #[macro_export] + macro_rules! N { + (self) => { + $crate::name::known::SELF_PARAM + }; + (Self) => { + $crate::name::known::SELF_TYPE + }; + ($ident:ident) => { + $crate::name::known::$ident + }; + } +} -// Builtin Macros -pub const FILE_MACRO: Name = Name::new_inline_ascii(b"file"); -pub const COLUMN_MACRO: Name = Name::new_inline_ascii(b"column"); -pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(b"compile_error"); -pub const LINE_MACRO: Name = Name::new_inline_ascii(b"line"); -pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(b"stringify"); -pub const FORMAT_ARGS_MACRO: Name = Name::new_inline_ascii(b"format_args"); -pub const FORMAT_ARGS_NL_MACRO: Name = Name::new_inline_ascii(b"format_args_nl"); - -// Builtin derives -pub const COPY_TRAIT: Name = Name::new_inline_ascii(b"Copy"); -pub const CLONE_TRAIT: Name = Name::new_inline_ascii(b"Clone"); -pub const DEFAULT_TRAIT: Name = Name::new_inline_ascii(b"Default"); -pub const DEBUG_TRAIT: Name = Name::new_inline_ascii(b"Debug"); -pub const HASH_TRAIT: Name = Name::new_inline_ascii(b"Hash"); -pub const ORD_TRAIT: Name = Name::new_inline_ascii(b"Ord"); -pub const PARTIAL_ORD_TRAIT: Name = Name::new_inline_ascii(b"PartialOrd"); -pub const EQ_TRAIT: Name = Name::new_inline_ascii(b"Eq"); -pub const PARTIAL_EQ_TRAIT: Name = Name::new_inline_ascii(b"PartialEq"); +pub use crate::N; diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index d557962b4f..04822d56e5 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs @@ -6,7 +6,7 @@ use std::iter::successors; use hir_def::lang_item::LangItemTarget; -use hir_expand::name; +use hir_expand::name::N; use log::{info, warn}; use ra_db::CrateId; @@ -52,7 +52,7 @@ fn deref_by_trait( LangItemTarget::TraitId(it) => it, _ => return None, }; - let target = db.trait_data(deref_trait).associated_type_by_name(&name::TARGET_TYPE)?; + let target = db.trait_data(deref_trait).associated_type_by_name(&N![Target])?; let generic_params = generics(db, target.into()); if generic_params.len() != 1 { diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index a1201b3e47..bb366bb8b4 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -29,7 +29,7 @@ use hir_def::{ type_ref::{Mutability, TypeRef}, AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, }; -use hir_expand::{diagnostics::DiagnosticSink, name}; +use hir_expand::{diagnostics::DiagnosticSink, name::N}; use ra_arena::map::ArenaMap; use ra_prof::profile; @@ -424,31 +424,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn resolve_into_iter_item(&self) -> Option { let path = known::std_iter_into_iterator(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&name::ITEM_TYPE) + self.db.trait_data(trait_).associated_type_by_name(&N![Item]) } fn resolve_ops_try_ok(&self) -> Option { let path = known::std_ops_try(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&name::OK_TYPE) + self.db.trait_data(trait_).associated_type_by_name(&N![Ok]) } fn resolve_ops_neg_output(&self) -> Option { let path = known::std_ops_neg(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) + self.db.trait_data(trait_).associated_type_by_name(&N![Output]) } fn resolve_ops_not_output(&self) -> Option { let path = known::std_ops_not(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) + self.db.trait_data(trait_).associated_type_by_name(&N![Output]) } fn resolve_future_future_output(&self) -> Option { let path = known::std_future_future(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&name::OUTPUT_TYPE) + self.db.trait_data(trait_).associated_type_by_name(&N![Output]) } fn resolve_boxed_box(&self) -> Option { diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index f8c00a7b4a..a6f5c6ec3c 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -10,7 +10,7 @@ use hir_def::{ resolver::resolver_for_expr, AdtId, ContainerId, Lookup, StructFieldId, }; -use hir_expand::name::{self, Name}; +use hir_expand::name::{Name, N}; use ra_syntax::ast::RangeOp; use crate::{ @@ -631,7 +631,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Parent arguments are unknown, except for the receiver type if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { for (_id, param) in parent_generics { - if param.name == name::SELF_TYPE { + if param.name == N![Self] { substs.push(receiver_ty.clone()); } else { substs.push(Ty::Unknown); diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 598fd81e31..27c475a3c4 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -1,7 +1,7 @@ //! This module provides the built-in trait implementations, e.g. to make //! closures implement `Fn`. use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; -use hir_expand::name; +use hir_expand::name::N; use ra_db::CrateId; use super::{AssocTyValue, Impl}; @@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum( // and don't want to return a valid value only to find out later that FnOnce // is broken let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name::OUTPUT_TYPE)?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&N![Output])?; let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value( let output_ty_id = db .trait_data(fn_once_trait) - .associated_type_by_name(&name::OUTPUT_TYPE) + .associated_type_by_name(&N![Output]) .expect("assoc ty value should not exist"); BuiltinImplAssocTyValueData { diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index aeb211a91c..fabf45b539 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -10,10 +10,8 @@ use hir_def::{ type_ref::TypeRef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, }; -use hir_expand::name::{self, Name}; +use hir_expand::name::{Name, N}; -// FIXME: this is wrong, b/c it can't express `trait T: PartialEq<()>`. -// We should return a `TraitREf` here. fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { let resolver = trait_.resolver(db); // returning the iterator directly doesn't easily work because of @@ -24,7 +22,7 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { .where_predicates .iter() .filter_map(|pred| match &pred.type_ref { - TypeRef::Path(p) if p.as_ident() == Some(&name::SELF_TYPE) => pred.bound.as_path(), + TypeRef::Path(p) if p.as_ident() == Some(&N![Self]) => pred.bound.as_path(), _ => None, }) .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { From 6911bc89a784ce72b4dfd8e0ba72bd22ce898395 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 22:01:06 +0100 Subject: [PATCH 157/312] Rename N! to name! --- crates/ra_hir/src/code_model.rs | 4 +-- crates/ra_hir_def/src/body/lower.rs | 4 +-- crates/ra_hir_def/src/builtin_type.rs | 36 +++++++++++----------- crates/ra_hir_def/src/data.rs | 4 +-- crates/ra_hir_def/src/generics.rs | 6 ++-- crates/ra_hir_def/src/nameres/collector.rs | 4 +-- crates/ra_hir_def/src/path.rs | 8 ++--- crates/ra_hir_def/src/resolver.rs | 16 +++++----- crates/ra_hir_expand/src/builtin_derive.rs | 2 +- crates/ra_hir_expand/src/builtin_macro.rs | 2 +- crates/ra_hir_expand/src/name.rs | 4 +-- crates/ra_hir_ty/src/autoderef.rs | 4 +-- crates/ra_hir_ty/src/infer.rs | 12 ++++---- crates/ra_hir_ty/src/infer/expr.rs | 4 +-- crates/ra_hir_ty/src/traits/builtin.rs | 6 ++-- crates/ra_hir_ty/src/utils.rs | 4 +-- 16 files changed, 60 insertions(+), 60 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index d1153fa628..7850ea9a71 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -17,7 +17,7 @@ use hir_def::{ }; use hir_expand::{ diagnostics::DiagnosticSink, - name::{AsName, N}, + name::{name, AsName}, MacroDefId, }; use hir_ty::{ @@ -723,7 +723,7 @@ impl Local { } pub fn is_self(self, db: &impl HirDatabase) -> bool { - self.name(db) == Some(N![self]) + self.name(db) == Some(name![self]) } pub fn is_mut(self, db: &impl HirDatabase) -> bool { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 6c760166fd..61193b4d80 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -2,7 +2,7 @@ //! representation. use either::Either; -use hir_expand::name::{AsName, Name, N}; +use hir_expand::name::{name, AsName, Name}; use ra_arena::Arena; use ra_syntax::{ ast::{ @@ -68,7 +68,7 @@ where let ptr = AstPtr::new(&self_param); let param_pat = self.alloc_pat( Pat::Bind { - name: N![self], + name: name![self], mode: BindingAnnotation::Unannotated, subpat: None, }, diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs index 757123f824..d14901a9b4 100644 --- a/crates/ra_hir_def/src/builtin_type.rs +++ b/crates/ra_hir_def/src/builtin_type.rs @@ -5,7 +5,7 @@ use std::fmt; -use hir_expand::name::{Name, N}; +use hir_expand::name::{name, Name}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] pub enum Signedness { @@ -52,26 +52,26 @@ pub enum BuiltinType { impl BuiltinType { #[rustfmt::skip] pub const ALL: &'static [(Name, BuiltinType)] = &[ - (N![char], BuiltinType::Char), - (N![bool], BuiltinType::Bool), - (N![str], BuiltinType::Str), + (name![char], BuiltinType::Char), + (name![bool], BuiltinType::Bool), + (name![str], BuiltinType::Str), - (N![isize], BuiltinType::Int(BuiltinInt::ISIZE)), - (N![i8], BuiltinType::Int(BuiltinInt::I8)), - (N![i16], BuiltinType::Int(BuiltinInt::I16)), - (N![i32], BuiltinType::Int(BuiltinInt::I32)), - (N![i64], BuiltinType::Int(BuiltinInt::I64)), - (N![i128], BuiltinType::Int(BuiltinInt::I128)), + (name![isize], BuiltinType::Int(BuiltinInt::ISIZE)), + (name![i8], BuiltinType::Int(BuiltinInt::I8)), + (name![i16], BuiltinType::Int(BuiltinInt::I16)), + (name![i32], BuiltinType::Int(BuiltinInt::I32)), + (name![i64], BuiltinType::Int(BuiltinInt::I64)), + (name![i128], BuiltinType::Int(BuiltinInt::I128)), - (N![usize], BuiltinType::Int(BuiltinInt::USIZE)), - (N![u8], BuiltinType::Int(BuiltinInt::U8)), - (N![u16], BuiltinType::Int(BuiltinInt::U16)), - (N![u32], BuiltinType::Int(BuiltinInt::U32)), - (N![u64], BuiltinType::Int(BuiltinInt::U64)), - (N![u128], BuiltinType::Int(BuiltinInt::U128)), + (name![usize], BuiltinType::Int(BuiltinInt::USIZE)), + (name![u8], BuiltinType::Int(BuiltinInt::U8)), + (name![u16], BuiltinType::Int(BuiltinInt::U16)), + (name![u32], BuiltinType::Int(BuiltinInt::U32)), + (name![u64], BuiltinType::Int(BuiltinInt::U64)), + (name![u128], BuiltinType::Int(BuiltinInt::U128)), - (N![f32], BuiltinType::Float(BuiltinFloat::F32)), - (N![f64], BuiltinType::Float(BuiltinFloat::F64)), + (name![f32], BuiltinType::Float(BuiltinFloat::F32)), + (name![f64], BuiltinType::Float(BuiltinFloat::F64)), ]; } diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index afeac0ec27..4f4ef57cc0 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use hir_expand::{ - name::{AsName, Name, N}, + name::{name, AsName, Name}, AstId, }; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; @@ -37,7 +37,7 @@ impl FunctionData { let self_type = if let Some(type_ref) = self_param.ascribed_type() { TypeRef::from_ast(type_ref) } else { - let self_type = TypeRef::Path(N![Self].into()); + let self_type = TypeRef::Path(name![Self].into()); match self_param.kind() { ast::SelfParamKind::Owned => self_type, ast::SelfParamKind::Ref => { diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs index 2b13748f36..e9c28c7309 100644 --- a/crates/ra_hir_def/src/generics.rs +++ b/crates/ra_hir_def/src/generics.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use either::Either; use hir_expand::{ - name::{AsName, Name, N}, + name::{name, AsName, Name}, InFile, }; use ra_arena::{map::ArenaMap, Arena}; @@ -90,11 +90,11 @@ impl GenericParams { // traits get the Self type as an implicit first type parameter let self_param_id = - generics.types.alloc(TypeParamData { name: N![Self], default: None }); + generics.types.alloc(TypeParamData { name: name![Self], default: None }); sm.insert(self_param_id, Either::Left(src.value.clone())); // add super traits as bounds on Self // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar - let self_param = TypeRef::Path(N![Self].into()); + let self_param = TypeRef::Path(name![Self].into()); generics.fill_bounds(&src.value, self_param); generics.fill(&mut sm, &src.value); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e81bac914b..5d7469a6ec 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -6,7 +6,7 @@ use hir_expand::{ builtin_derive::find_builtin_derive, builtin_macro::find_builtin_macro, - name::{AsName, Name, N}, + name::{name, AsName, Name}, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, }; use ra_cfg::CfgOptions; @@ -918,7 +918,7 @@ where } fn is_macro_rules(path: &Path) -> bool { - path.as_ident() == Some(&N![macro_rules]) + path.as_ident() == Some(&name![macro_rules]) } #[cfg(test)] diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 36ad278678..c1376af364 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{AsName, Name, N}, + name::{name, AsName, Name}, }; use ra_db::CrateId; use ra_syntax::{ @@ -276,7 +276,7 @@ impl GenericArgs { } if let Some(ret_type) = ret_type { let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((N![Output], type_ref)) + bindings.push((name![Output], type_ref)) } if args.is_empty() && bindings.is_empty() { None @@ -297,12 +297,12 @@ impl From for Path { } pub mod known { - use hir_expand::name::N; + use hir_expand::name::name; use super::{Path, PathKind}; macro_rules! P { - ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![N![$start], $(N![$seg],)*]) }; + ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![name![$start], $(name![$seg],)*]) }; } pub fn std_iter_into_iterator() -> Path { diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 0fb5295279..b6d595a209 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use hir_expand::{ - name::{Name, N}, + name::{name, Name}, MacroDefId, }; use ra_db::CrateId; @@ -163,13 +163,13 @@ impl Resolver { } } Scope::ImplBlockScope(impl_) => { - if first_name == &N![Self] { + if first_name == &name![Self] { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some((TypeNs::SelfType(*impl_), idx)); } } Scope::AdtScope(adt) => { - if first_name == &N![Self] { + if first_name == &name![Self] { let idx = if path.segments.len() == 1 { None } else { Some(1) }; return Some((TypeNs::AdtSelfType(*adt), idx)); } @@ -223,7 +223,7 @@ impl Resolver { return None; } let n_segments = path.segments.len(); - let tmp = N![self]; + let tmp = name![self]; let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); for scope in self.scopes.iter().rev() { @@ -259,13 +259,13 @@ impl Resolver { Scope::GenericParams { .. } => continue, Scope::ImplBlockScope(impl_) if n_segments > 1 => { - if first_name == &N![Self] { + if first_name == &name![Self] { let ty = TypeNs::SelfType(*impl_); return Some(ResolveValueResult::Partial(ty, 1)); } } Scope::AdtScope(adt) if n_segments > 1 => { - if first_name == &N![Self] { + if first_name == &name![Self] { let ty = TypeNs::AdtSelfType(*adt); return Some(ResolveValueResult::Partial(ty, 1)); } @@ -439,10 +439,10 @@ impl Scope { } } Scope::ImplBlockScope(i) => { - f(N![Self], ScopeDef::ImplSelfType((*i).into())); + f(name![Self], ScopeDef::ImplSelfType((*i).into())); } Scope::AdtScope(i) => { - f(N![Self], ScopeDef::AdtSelfType((*i).into())); + f(name![Self], ScopeDef::AdtSelfType((*i).into())); } Scope::ExprScope(scope) => { scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| { diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index d7f8ada786..b264412538 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -34,7 +34,7 @@ macro_rules! register_builtin { pub fn find_builtin_derive(ident: &name::Name) -> Option { let kind = match ident { - $( id if id == &name::N![$trait] => BuiltinDeriveExpander::$trait, )* + $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )* _ => return None, }; diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index e5046ad4cb..d2b3d769e8 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -34,7 +34,7 @@ macro_rules! register_builtin { ast_id: AstId, ) -> Option { let kind = match ident { - $( id if id == &name::N![$name] => BuiltinFnLikeExpander::$kind, )* + $( id if id == &name::name![$name] => BuiltinFnLikeExpander::$kind, )* _ => return None, }; diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 8b3141d75c..59d8214fde 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -186,7 +186,7 @@ pub mod known { pub const SELF_TYPE: super::Name = super::Name::new_inline_ascii(b"Self"); #[macro_export] - macro_rules! N { + macro_rules! name { (self) => { $crate::name::known::SELF_PARAM }; @@ -199,4 +199,4 @@ pub mod known { } } -pub use crate::N; +pub use crate::name; diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index 04822d56e5..ee48fa5370 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs @@ -6,7 +6,7 @@ use std::iter::successors; use hir_def::lang_item::LangItemTarget; -use hir_expand::name::N; +use hir_expand::name::name; use log::{info, warn}; use ra_db::CrateId; @@ -52,7 +52,7 @@ fn deref_by_trait( LangItemTarget::TraitId(it) => it, _ => return None, }; - let target = db.trait_data(deref_trait).associated_type_by_name(&N![Target])?; + let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; let generic_params = generics(db, target.into()); if generic_params.len() != 1 { diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index bb366bb8b4..edf4e69ba9 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -29,7 +29,7 @@ use hir_def::{ type_ref::{Mutability, TypeRef}, AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, }; -use hir_expand::{diagnostics::DiagnosticSink, name::N}; +use hir_expand::{diagnostics::DiagnosticSink, name::name}; use ra_arena::map::ArenaMap; use ra_prof::profile; @@ -424,31 +424,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn resolve_into_iter_item(&self) -> Option { let path = known::std_iter_into_iterator(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&N![Item]) + self.db.trait_data(trait_).associated_type_by_name(&name![Item]) } fn resolve_ops_try_ok(&self) -> Option { let path = known::std_ops_try(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&N![Ok]) + self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) } fn resolve_ops_neg_output(&self) -> Option { let path = known::std_ops_neg(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&N![Output]) + self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_ops_not_output(&self) -> Option { let path = known::std_ops_not(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&N![Output]) + self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_future_future_output(&self) -> Option { let path = known::std_future_future(); let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; - self.db.trait_data(trait_).associated_type_by_name(&N![Output]) + self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_boxed_box(&self) -> Option { diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index a6f5c6ec3c..2e3cdd53a0 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -10,7 +10,7 @@ use hir_def::{ resolver::resolver_for_expr, AdtId, ContainerId, Lookup, StructFieldId, }; -use hir_expand::name::{Name, N}; +use hir_expand::name::{name, Name}; use ra_syntax::ast::RangeOp; use crate::{ @@ -631,7 +631,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // Parent arguments are unknown, except for the receiver type if let Some(parent_generics) = def_generics.as_ref().map(|p| p.iter_parent()) { for (_id, param) in parent_generics { - if param.name == N![Self] { + if param.name == name![Self] { substs.push(receiver_ty.clone()); } else { substs.push(Ty::Unknown); diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index 27c475a3c4..cd587a3382 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -1,7 +1,7 @@ //! This module provides the built-in trait implementations, e.g. to make //! closures implement `Fn`. use hir_def::{expr::Expr, lang_item::LangItemTarget, TraitId, TypeAliasId}; -use hir_expand::name::N; +use hir_expand::name::name; use ra_db::CrateId; use super::{AssocTyValue, Impl}; @@ -79,7 +79,7 @@ fn closure_fn_trait_impl_datum( // and don't want to return a valid value only to find out later that FnOnce // is broken let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&N![Output])?; + let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -137,7 +137,7 @@ fn closure_fn_trait_output_assoc_ty_value( let output_ty_id = db .trait_data(fn_once_trait) - .associated_type_by_name(&N![Output]) + .associated_type_by_name(&name![Output]) .expect("assoc ty value should not exist"); BuiltinImplAssocTyValueData { diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index fabf45b539..0049d3c6fc 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -10,7 +10,7 @@ use hir_def::{ type_ref::TypeRef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, }; -use hir_expand::name::{Name, N}; +use hir_expand::name::{name, Name}; fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { let resolver = trait_.resolver(db); @@ -22,7 +22,7 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { .where_predicates .iter() .filter_map(|pred| match &pred.type_ref { - TypeRef::Path(p) if p.as_ident() == Some(&N![Self]) => pred.bound.as_path(), + TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(), _ => None, }) .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { From f02fcc16444fcd18ccd51b43fa01bf0233e044fa Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 13 Dec 2019 22:32:44 +0100 Subject: [PATCH 158/312] Use path macro --- crates/ra_hir/src/source_binder.rs | 4 +- crates/ra_hir_def/src/path.rs | 95 ++++++++++-------------------- crates/ra_hir_ty/src/expr.rs | 4 +- crates/ra_hir_ty/src/infer.rs | 26 ++++---- 4 files changed, 49 insertions(+), 80 deletions(-) diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index d3cc5c423e..f82242c3a0 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -15,7 +15,7 @@ use hir_def::{ }, expr::{ExprId, PatId}, nameres::ModuleSource, - path::known, + path::path, resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, AssocItemId, DefWithBodyId, }; @@ -418,7 +418,7 @@ impl SourceAnalyzer { /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool { - let std_future_path = known::std_future_future(); + let std_future_path = path![std::future::Future]; let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) { Some(it) => it.into(), diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index c1376af364..1e9eb14ea5 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -76,10 +76,7 @@ impl Path { } } - pub(crate) fn from_simple_segments( - kind: PathKind, - segments: impl IntoIterator, - ) -> Path { + pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { Path { kind, segments: segments @@ -296,64 +293,36 @@ impl From for Path { } } -pub mod known { - use hir_expand::name::name; +pub use hir_expand::name as __name; - use super::{Path, PathKind}; - - macro_rules! P { - ($start:ident $(:: $seg:ident)*) => { Path::from_simple_segments(PathKind::Abs, vec![name![$start], $(name![$seg],)*]) }; - } - - pub fn std_iter_into_iterator() -> Path { - P![std::iter::IntoIterator] - } - - pub fn std_ops_try() -> Path { - P![std::ops::Try] - } - - pub fn std_ops_range() -> Path { - P![std::ops::Range] - } - - pub fn std_ops_range_from() -> Path { - P![std::ops::RangeFrom] - } - - pub fn std_ops_range_full() -> Path { - P![std::ops::RangeFull] - } - - pub fn std_ops_range_inclusive() -> Path { - P![std::ops::RangeInclusive] - } - - pub fn std_ops_range_to() -> Path { - P![std::ops::RangeTo] - } - - pub fn std_ops_range_to_inclusive() -> Path { - P![std::ops::RangeToInclusive] - } - - pub fn std_ops_neg() -> Path { - P![std::ops::Neg] - } - - pub fn std_ops_not() -> Path { - P![std::ops::Not] - } - - pub fn std_result_result() -> Path { - P![std::result::Result] - } - - pub fn std_future_future() -> Path { - P![std::future::Future] - } - - pub fn std_boxed_box() -> Path { - P![std::boxed::Box] - } +#[macro_export] +macro_rules! __known_path { + (std::iter::IntoIterator) => {}; + (std::result::Result) => {}; + (std::ops::Range) => {}; + (std::ops::RangeFrom) => {}; + (std::ops::RangeFull) => {}; + (std::ops::RangeTo) => {}; + (std::ops::RangeToInclusive) => {}; + (std::ops::RangeInclusive) => {}; + (std::boxed::Box) => {}; + (std::future::Future) => {}; + (std::ops::Try) => {}; + (std::ops::Neg) => {}; + (std::ops::Not) => {}; + ($path:path) => { + compile_error!("Please register your known path in the path module") + }; } + +#[macro_export] +macro_rules! __path { + ($start:ident $(:: $seg:ident)*) => ({ + $crate::__known_path!($start $(:: $seg)*); + $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![ + $crate::path::__name![$start], $($crate::path::__name![$seg],)* + ]) + }); +} + +pub use crate::__path as path; diff --git a/crates/ra_hir_ty/src/expr.rs b/crates/ra_hir_ty/src/expr.rs index d2bd64e5cc..f752a9f09a 100644 --- a/crates/ra_hir_ty/src/expr.rs +++ b/crates/ra_hir_ty/src/expr.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use hir_def::{ - path::{known, Path}, + path::{path, Path}, resolver::HasResolver, AdtId, FunctionId, }; @@ -124,7 +124,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { None => return, }; - let std_result_path = known::std_result_result(); + let std_result_path = path![std::result::Result]; let resolver = self.func.resolver(db); let std_result_enum = match resolver.resolve_known_enum(db, &std_result_path) { diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index edf4e69ba9..f1b7e9442d 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -24,7 +24,7 @@ use hir_def::{ body::Body, data::{ConstData, FunctionData}, expr::{BindingAnnotation, ExprId, PatId}, - path::{known, Path}, + path::{path, Path}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{Mutability, TypeRef}, AdtId, AssocItemId, DefWithBodyId, FunctionId, StructFieldId, TypeAliasId, VariantId, @@ -422,73 +422,73 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } fn resolve_into_iter_item(&self) -> Option { - let path = known::std_iter_into_iterator(); + let path = path![std::iter::IntoIterator]; let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Item]) } fn resolve_ops_try_ok(&self) -> Option { - let path = known::std_ops_try(); + let path = path![std::ops::Try]; let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) } fn resolve_ops_neg_output(&self) -> Option { - let path = known::std_ops_neg(); + let path = path![std::ops::Neg]; let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_ops_not_output(&self) -> Option { - let path = known::std_ops_not(); + let path = path![std::ops::Not]; let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_future_future_output(&self) -> Option { - let path = known::std_future_future(); + let path = path![std::future::Future]; let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; self.db.trait_data(trait_).associated_type_by_name(&name![Output]) } fn resolve_boxed_box(&self) -> Option { - let path = known::std_boxed_box(); + let path = path![std::boxed::Box]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range_full(&self) -> Option { - let path = known::std_ops_range_full(); + let path = path![std::ops::RangeFull]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range(&self) -> Option { - let path = known::std_ops_range(); + let path = path![std::ops::Range]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range_inclusive(&self) -> Option { - let path = known::std_ops_range_inclusive(); + let path = path![std::ops::RangeInclusive]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range_from(&self) -> Option { - let path = known::std_ops_range_from(); + let path = path![std::ops::RangeFrom]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range_to(&self) -> Option { - let path = known::std_ops_range_to(); + let path = path![std::ops::RangeTo]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } fn resolve_range_to_inclusive(&self) -> Option { - let path = known::std_ops_range_to_inclusive(); + let path = path![std::ops::RangeToInclusive]; let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } From 03fe6b38b88b3d4f7f79912e7bf1b5fb14d7bbc2 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 13 Dec 2019 17:35:15 -0500 Subject: [PATCH 159/312] Remove some unwraps in add_new --- crates/ra_assists/src/assists/add_new.rs | 35 +++++++++++------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index d340cac8fd..b2f946fac3 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -139,43 +139,40 @@ fn find_struct_impl( let struct_ty = { let src = InFile { file_id: ctx.frange.file_id.into(), value: strukt.clone() }; - hir::Struct::from_source(db, src).unwrap().ty(db) + hir::Struct::from_source(db, src)?.ty(db) }; - let mut found_new_fn = false; - - let block = module.descendants().filter_map(ast::ImplBlock::cast).find(|impl_blk| { - if found_new_fn { - return false; - } - + let block = module.descendants().filter_map(ast::ImplBlock::cast).find_map(|impl_blk| { let src = InFile { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() }; - let blk = hir::ImplBlock::from_source(db, src).unwrap(); + let blk = hir::ImplBlock::from_source(db, src)?; let same_ty = blk.target_ty(db) == struct_ty; let not_trait_impl = blk.target_trait(db).is_none(); if !(same_ty && not_trait_impl) { - return false; + None + } else { + Some(impl_blk) } - - found_new_fn = has_new_fn(impl_blk); - true }); - if found_new_fn { - None - } else { - Some(block) + if let Some(ref impl_blk) = block { + if has_new_fn(impl_blk) { + return None; + } } + + Some(block) } fn has_new_fn(imp: &ast::ImplBlock) -> bool { if let Some(il) = imp.item_list() { for item in il.impl_items() { if let ast::ImplItem::FnDef(f) = item { - if f.name().unwrap().text().eq_ignore_ascii_case("new") { - return true; + if let Some(name) = f.name() { + if name.text().eq_ignore_ascii_case("new") { + return true; + } } } } From 67641d3f5fd1cfd49673c4eea9e3d646ed97e108 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sat, 14 Dec 2019 13:24:07 +0200 Subject: [PATCH 160/312] added decorations --- crates/ra_ide/src/syntax_highlighting.rs | 4 +- editors/code/package.json | 56 +++++++++++++++++++++++- editors/code/src/highlighting.ts | 6 +++ 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index cd9d8b058f..7be25b234f 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -225,8 +225,8 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { Def(hir::ModuleDef::EnumVariant(_)) => "constant", Def(hir::ModuleDef::Const(_)) => "constant", Def(hir::ModuleDef::Static(_)) => "constant", - Def(hir::ModuleDef::Trait(_)) => "type.trait", - Def(hir::ModuleDef::TypeAlias(_)) => "type.alias", + Def(hir::ModuleDef::Trait(_)) => "type", + Def(hir::ModuleDef::TypeAlias(_)) => "type", Def(hir::ModuleDef::BuiltinType(_)) => "type.builtin", SelfType(_) => "type.self", TypeParam(_) => "type.param", diff --git a/editors/code/package.json b/editors/code/package.json index 7bc08ec31f..c24e73d24f 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -422,6 +422,33 @@ "highContrast": "#B5CEA8" } }, + { + "id": "ralsp.literal.numeric", + "description": "Color for numeric literals", + "defaults": { + "dark": "#BECEA8", + "light": "#09885A", + "highContrast": "#B5CEA8" + } + }, + { + "id": "ralsp.literal.char", + "description": "Color for character literals", + "defaults": { + "dark": "#BECEA8", + "light": "#09885A", + "highContrast": "#B5CEA8" + } + }, + { + "id": "ralsp.literal.byte", + "description": "Color for byte literals", + "defaults": { + "dark": "#BECEA8", + "light": "#09885A", + "highContrast": "#B5CEA8" + } + }, { "id": "ralsp.macro", "description": "Color for macros", @@ -442,7 +469,34 @@ }, { "id": "ralsp.type", - "description": "Color for types", + "description": "Color for other types (traits, aliases..)", + "defaults": { + "dark": "#4EC9B0", + "light": "#267F99", + "highContrast": "#4EC9B0" + } + }, + { + "id": "ralsp.type.builtin", + "description": "Color for built-in types (&str, bool, u16, u32)", + "defaults": { + "dark": "#4EC9B0", + "light": "#267F99", + "highContrast": "#4EC9B0" + } + }, + { + "id": "ralsp.type.self", + "description": "Color for `Self` param type", + "defaults": { + "dark": "#4EC9B0", + "light": "#267F99", + "highContrast": "#4EC9B0" + } + }, + { + "id": "ralsp.type.param", + "description": "Color for type parameters", "defaults": { "dark": "#4EC9B0", "light": "#267F99", diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 6d50a2f2de..2c8a98aa69 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -53,10 +53,16 @@ export class Highlighter { decoration('parameter'), decoration('constant'), decoration('type'), + decoration('type.self'), + decoration('type.generic'), + decoration('type.param'), decoration('builtin'), decoration('text'), decoration('attribute'), decoration('literal'), + decoration('literal.numeric'), + decoration('literal.char'), + decoration('literal.byte'), decoration('macro'), decoration('variable'), decoration('variable.mut', 'underline'), From 083010f6339e558184f06ce76a18e1ad0b0ee936 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sat, 14 Dec 2019 13:29:42 +0200 Subject: [PATCH 161/312] removed `type.alias` --- crates/ra_ide/src/snapshots/highlighting.html | 26 ++++++++++--------- crates/ra_ide/src/syntax_highlighting.rs | 6 +++-- editors/code/package.json | 9 +++++++ editors/code/src/highlighting.ts | 1 + 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 4166a8f90d..40605d9efd 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -10,8 +10,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } +.literal\.numeric { color: #6A8759; } .macro { color: #94BFF3; } .variable { color: #DCDCCC; } .variable\.mut { color: #DCDCCC; text-decoration: underline; } @@ -22,36 +24,36 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
#[derive(Clone, Debug)]
 struct Foo {
-    pub x: i32,
-    pub y: i32,
+    pub x: i32,
+    pub y: i32,
 }
 
-fn foo<T>() -> T {
+fn foo<T>() -> T {
     unimplemented!();
-    foo::<i32>();
+    foo::<i32>();
 }
 
 // comment
 fn main() {
-    println!("Hello, {}!", 92);
+    println!("Hello, {}!", 92);
 
     let mut vec = Vec::new();
     if true {
-        vec.push(Foo { x: 0, y: 1 });
+        vec.push(Foo { x: 0, y: 1 });
     }
-    unsafe { vec.set_len(0); }
+    unsafe { vec.set_len(0); }
 
-    let mut x = 42;
+    let mut x = 42;
     let y = &mut x;
     let z = &y;
 
     y;
 }
 
-enum E<X> {
-    V(X)
+enum E<X> {
+    V(X)
 }
 
-impl<X> E<X> {
-    fn new<T>() -> E<T> {}
+impl<X> E<X> {
+    fn new<T>() -> E<T> {}
 }
\ No newline at end of file diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 7be25b234f..235e09ffca 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -118,7 +118,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "literal.numeric", BYTE => "literal.byte", CHAR => "literal.char", - LIFETIME => "lifetime", + LIFETIME => "type.lifetime", T![unsafe] => "keyword.unsafe", k if is_control_keyword(k) => "keyword.control", k if k.is_keyword() => "keyword", @@ -218,7 +218,7 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { Field(_) => "field", AssocItem(hir::AssocItem::Function(_)) => "function", AssocItem(hir::AssocItem::Const(_)) => "constant", - AssocItem(hir::AssocItem::TypeAlias(_)) => "type.alias", + AssocItem(hir::AssocItem::TypeAlias(_)) => "type", Def(hir::ModuleDef::Module(_)) => "module", Def(hir::ModuleDef::Function(_)) => "function", Def(hir::ModuleDef::Adt(_)) => "type", @@ -259,8 +259,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } +.literal\\.numeric { color: #6A8759; } .macro { color: #94BFF3; } .variable { color: #DCDCCC; } .variable\\.mut { color: #DCDCCC; text-decoration: underline; } diff --git a/editors/code/package.json b/editors/code/package.json index c24e73d24f..68b3b6e056 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -485,6 +485,15 @@ "highContrast": "#4EC9B0" } }, + { + "id": "ralsp.type.lifetime", + "description": "Color for `Self` param type", + "defaults": { + "dark": "#4EC9B0", + "light": "#267F99", + "highContrast": "#4EC9B0" + } + }, { "id": "ralsp.type.self", "description": "Color for `Self` param type", diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index 2c8a98aa69..d7c0ae1316 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -56,6 +56,7 @@ export class Highlighter { decoration('type.self'), decoration('type.generic'), decoration('type.param'), + decoration('type.lifetime'), decoration('builtin'), decoration('text'), decoration('attribute'), From f720855e1e45985463e31e0a6a2a76bb6ffd1cfa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 14 Dec 2019 16:45:14 +0100 Subject: [PATCH 162/312] Use all-features by default --- crates/ra_project_model/src/cargo_workspace.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 4a0437da32..c862d3912c 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -24,7 +24,7 @@ pub struct CargoWorkspace { pub(crate) workspace_root: PathBuf, } -#[derive(Deserialize, Clone, Debug, PartialEq, Eq, Default)] +#[derive(Deserialize, Clone, Debug, PartialEq, Eq)] #[serde(rename_all = "camelCase", default)] pub struct CargoFeatures { /// Do not activate the `default` feature. @@ -38,6 +38,12 @@ pub struct CargoFeatures { pub features: Vec, } +impl Default for CargoFeatures { + fn default() -> Self { + CargoFeatures { no_default_features: false, all_features: true, features: Vec::new() } + } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct Package(RawId); impl_arena_id!(Package); From 61360fdfec981eadef1eefb595c8b32c951771e8 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 15 Dec 2019 01:20:07 +0800 Subject: [PATCH 163/312] Fix original_source find order --- crates/ra_hir/src/lib.rs | 3 +- crates/ra_hir_expand/src/lib.rs | 29 +++++-- .../ra_ide/src/display/navigation_target.rs | 19 ++++- crates/ra_ide/src/expand.rs | 79 ++++++++++--------- crates/ra_ide/src/goto_definition.rs | 34 ++++++-- 5 files changed, 109 insertions(+), 55 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e7602ee305..2bf729b6d6 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -58,6 +58,7 @@ pub use hir_def::{ type_ref::Mutability, }; pub use hir_expand::{ - name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, + name::Name, ExpansionOrigin, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, + MacroFile, }; pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 94e1e466a5..d1a43fe6cf 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -214,7 +214,17 @@ pub struct ExpansionInfo { exp_map: Arc, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ExpansionOrigin { + Call, + Def, +} + impl ExpansionInfo { + pub fn call_node(&self) -> Option> { + Some(self.arg.with_value(self.arg.value.parent()?)) + } + pub fn map_token_down(&self, token: InFile<&SyntaxToken>) -> Option> { assert_eq!(token.file_id, self.arg.file_id); let range = token.value.text_range().checked_sub(self.arg.value.text_range().start())?; @@ -228,21 +238,26 @@ impl ExpansionInfo { Some(self.expanded.with_value(token)) } - pub fn map_token_up(&self, token: InFile<&SyntaxToken>) -> Option> { + pub fn map_token_up( + &self, + token: InFile<&SyntaxToken>, + ) -> Option<(InFile, ExpansionOrigin)> { let token_id = self.exp_map.token_by_range(token.value.text_range())?; let (token_id, origin) = self.macro_def.0.map_id_up(token_id); - let (token_map, tt) = match origin { - mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), - mbe::Origin::Def => { - (&self.macro_def.1, self.def.as_ref().map(|tt| tt.syntax().clone())) - } + let (token_map, tt, origin) = match origin { + mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone(), ExpansionOrigin::Call), + mbe::Origin::Def => ( + &self.macro_def.1, + self.def.as_ref().map(|tt| tt.syntax().clone()), + ExpansionOrigin::Def, + ), }; let range = token_map.range_by_token(token_id)?; let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) .into_token()?; - Some(tt.with_value(token)) + Some((tt.with_value(token), origin)) } } diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6a6b49afdf..6a2bf72731 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -7,10 +7,14 @@ use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, match_ast, AstNode, SmolStr, SyntaxKind::{self, BIND_PAT, TYPE_PARAM}, - TextRange, + SyntaxNode, TextRange, }; -use crate::{db::RootDatabase, expand::original_range, FileSymbol}; +use crate::{ + db::RootDatabase, + expand::{original_range_by_kind, OriginalRangeKind}, + FileRange, FileSymbol, +}; use super::short_label::ShortLabel; @@ -416,3 +420,14 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> } } } + +fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { + if let Some(range) = original_range_by_kind(db, node, OriginalRangeKind::CallToken) { + return range; + } + if let Some(range) = original_range_by_kind(db, node, OriginalRangeKind::WholeCall) { + return range; + } + + FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } +} diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 661628ae46..327393dbbe 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -1,57 +1,62 @@ //! Utilities to work with files, produced by macros. use std::iter::successors; -use hir::InFile; +use hir::{ExpansionOrigin, InFile}; use ra_db::FileId; use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; use crate::{db::RootDatabase, FileRange}; -pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { - let expansion = match node.file_id.expansion_info(db) { - None => { - return FileRange { - file_id: node.file_id.original_file(db), - range: node.value.text_range(), - } - } - Some(it) => it, - }; +#[derive(Debug, PartialEq, Eq)] +pub(crate) enum OriginalRangeKind { + /// Return range if any token is matched + #[allow(dead_code)] + Any, + /// Return range if token is inside macro_call + CallToken, + /// Return whole macro call range if matched + WholeCall, +} + +pub(crate) fn original_range_by_kind( + db: &RootDatabase, + node: InFile<&SyntaxNode>, + kind: OriginalRangeKind, +) -> Option { + let expansion = node.file_id.expansion_info(db)?; + + // the input node has only one token ? + let single = node.value.first_token()? == node.value.last_token()?; + // FIXME: We should handle recurside macro expansions + let range = match kind { + OriginalRangeKind::WholeCall => expansion.call_node()?.map(|node| node.text_range()), + _ => node.value.descendants().find_map(|it| { + let first = it.first_token()?; + let last = it.last_token()?; - let range = node.value.descendants_with_tokens().find_map(|it| { - match it.as_token() { - // FIXME: Remove this branch after all `tt::TokenTree`s have a proper `TokenId`, - // and return the range of the overall macro expansions if mapping first and last tokens fails. - Some(token) => { - let token = expansion.map_token_up(node.with_value(&token))?; - Some(token.with_value(token.value.text_range())) + if !single && first == last { + return None; } - None => { - // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens - let n = it.into_node()?; - let first = expansion.map_token_up(node.with_value(&n.first_token()?))?; - let last = expansion.map_token_up(node.with_value(&n.last_token()?))?; - // FIXME: Is is possible ? - if first.file_id != last.file_id { - return None; - } + // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens + let (first, first_origin) = expansion.map_token_up(node.with_value(&first))?; + let (last, last_origin) = expansion.map_token_up(node.with_value(&last))?; - // FIXME: Add union method in TextRange - let range = union_range(first.value.text_range(), last.value.text_range()); - Some(first.with_value(range)) + if first.file_id != last.file_id + || first_origin != last_origin + || (kind == OriginalRangeKind::CallToken && first_origin != ExpansionOrigin::Call) + { + return None; } - } - }); - return match range { - Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.value }, - None => { - FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } - } + // FIXME: Add union method in TextRange + Some(first.with_value(union_range(first.value.text_range(), last.value.text_range()))) + })?, }; + return Some(FileRange { file_id: range.file_id.original_file(db), range: range.value }); + fn union_range(a: TextRange, b: TextRange) -> TextRange { let start = a.start().min(b.start()); let end = a.end().max(b.end()); diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index cfe62037fc..2c634990da 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -209,7 +209,7 @@ fn named_target(db: &RootDatabase, node: InFile<&SyntaxNode>) -> Option (fn $name() {}) } - define_fn!( - foo - ) + define_fn!(foo); fn bar() { <|>foo(); } ", - "foo FN_DEF FileId(1) [80; 83) [80; 83)", + "foo FN_DEF FileId(1) [64; 80) [75; 78)", + "define_fn!(foo);|foo", ); } #[test] fn goto_definition_works_for_macro_defined_fn_no_arg() { - check_goto( + check_goto_with_range_content( " //- /lib.rs macro_rules! define_fn { @@ -373,7 +390,8 @@ mod tests { <|>foo(); } ", - "foo FN_DEF FileId(1) [39; 42) [39; 42)", + "foo FN_DEF FileId(1) [51; 64) [51; 64)", + "define_fn!();|define_fn!();", ); } From b53587c7bdd67c63bd33a745fdaeb22a847b6c2f Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 15 Dec 2019 01:46:39 +0800 Subject: [PATCH 164/312] Re-export Origin to replace ExpansionOrigin --- crates/ra_hir/src/lib.rs | 3 +-- crates/ra_hir_expand/src/lib.rs | 20 +++++++------------- crates/ra_ide/src/expand.rs | 4 ++-- crates/ra_mbe/src/lib.rs | 1 + 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 2bf729b6d6..8b9562722d 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -58,7 +58,6 @@ pub use hir_def::{ type_ref::Mutability, }; pub use hir_expand::{ - name::Name, ExpansionOrigin, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, - MacroFile, + name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index d1a43fe6cf..cb4e1950bf 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -214,11 +214,7 @@ pub struct ExpansionInfo { exp_map: Arc, } -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ExpansionOrigin { - Call, - Def, -} +pub use mbe::Origin; impl ExpansionInfo { pub fn call_node(&self) -> Option> { @@ -241,17 +237,15 @@ impl ExpansionInfo { pub fn map_token_up( &self, token: InFile<&SyntaxToken>, - ) -> Option<(InFile, ExpansionOrigin)> { + ) -> Option<(InFile, Origin)> { let token_id = self.exp_map.token_by_range(token.value.text_range())?; let (token_id, origin) = self.macro_def.0.map_id_up(token_id); - let (token_map, tt, origin) = match origin { - mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone(), ExpansionOrigin::Call), - mbe::Origin::Def => ( - &self.macro_def.1, - self.def.as_ref().map(|tt| tt.syntax().clone()), - ExpansionOrigin::Def, - ), + let (token_map, tt) = match origin { + mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()), + mbe::Origin::Def => { + (&self.macro_def.1, self.def.as_ref().map(|tt| tt.syntax().clone())) + } }; let range = token_map.range_by_token(token_id)?; diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 327393dbbe..258478bc13 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -1,7 +1,7 @@ //! Utilities to work with files, produced by macros. use std::iter::successors; -use hir::{ExpansionOrigin, InFile}; +use hir::{InFile, Origin}; use ra_db::FileId; use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; @@ -45,7 +45,7 @@ pub(crate) fn original_range_by_kind( if first.file_id != last.file_id || first_origin != last_origin - || (kind == OriginalRangeKind::CallToken && first_origin != ExpansionOrigin::Call) + || (kind == OriginalRangeKind::CallToken && first_origin != Origin::Call) { return None; } diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 0d2d43bef4..ce2deadf6e 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -104,6 +104,7 @@ impl Shift { } } +#[derive(Debug, Eq, PartialEq)] pub enum Origin { Def, Call, From 2619950b3b405324ab1c1745876165c834b3b4b9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 13 Dec 2019 12:12:36 +0100 Subject: [PATCH 165/312] Use different types for path with and without generics --- crates/ra_assists/src/assists/add_import.rs | 6 +- crates/ra_hir/src/lib.rs | 2 +- crates/ra_hir/src/source_binder.rs | 56 +-- crates/ra_hir_def/src/attr.rs | 6 +- crates/ra_hir_def/src/body.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 4 +- crates/ra_hir_def/src/nameres/collector.rs | 14 +- .../ra_hir_def/src/nameres/path_resolution.rs | 24 +- crates/ra_hir_def/src/nameres/raw.rs | 12 +- crates/ra_hir_def/src/path.rs | 349 ++++++++---------- crates/ra_hir_def/src/path/lower.rs | 176 +++++++++ .../src/path/{ => lower}/lower_use.rs | 23 +- crates/ra_hir_def/src/resolver.rs | 46 ++- crates/ra_hir_ty/src/infer.rs | 2 +- crates/ra_hir_ty/src/infer/path.rs | 25 +- crates/ra_hir_ty/src/lower.rs | 70 ++-- crates/ra_hir_ty/src/utils.rs | 5 +- .../src/completion/completion_context.rs | 7 +- 18 files changed, 473 insertions(+), 356 deletions(-) create mode 100644 crates/ra_hir_def/src/path/lower.rs rename crates/ra_hir_def/src/path/{ => lower}/lower_use.rs (81%) diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index 363ade016b..f81b4184a0 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs @@ -578,7 +578,7 @@ fn apply_auto_import( fn collect_hir_path_segments(path: &hir::Path) -> Option> { let mut ps = Vec::::with_capacity(10); - match path.kind { + match path.kind() { hir::PathKind::Abs => ps.push("".into()), hir::PathKind::Crate => ps.push("crate".into()), hir::PathKind::Plain => {} @@ -586,9 +586,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option> { hir::PathKind::Super => ps.push("super".into()), hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, } - for s in path.segments.iter() { - ps.push(s.name.to_string().into()); - } + ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); Some(ps) } diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e7602ee305..451b227a6e 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -54,7 +54,7 @@ pub use hir_def::{ builtin_type::BuiltinType, docs::Documentation, nameres::ModuleSource, - path::{Path, PathKind}, + path::{ModPath, Path, PathKind}, type_ref::Mutability, }; pub use hir_expand::{ diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index f82242c3a0..d326169b33 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -258,7 +258,7 @@ impl SourceAnalyzer { ) -> Option { let hygiene = Hygiene::new(db, macro_call.file_id); let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &hygiene))?; - self.resolver.resolve_path_as_macro(db, &path).map(|it| it.into()) + self.resolver.resolve_path_as_macro(db, path.mod_path()).map(|it| it.into()) } pub fn resolve_hir_path( @@ -266,40 +266,42 @@ impl SourceAnalyzer { db: &impl HirDatabase, path: &crate::Path, ) -> Option { - let types = self.resolver.resolve_path_in_type_ns_fully(db, &path).map(|ty| match ty { - TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), - TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), - TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { - PathResolution::Def(Adt::from(it).into()) - } - TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), - TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), - TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), - TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), - }); - let values = self.resolver.resolve_path_in_value_ns_fully(db, &path).and_then(|val| { - let res = match val { - ValueNs::LocalBinding(pat_id) => { - let var = Local { parent: self.body_owner?, pat_id }; - PathResolution::Local(var) + let types = + self.resolver.resolve_path_in_type_ns_fully(db, path.mod_path()).map(|ty| match ty { + TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), + TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), + TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { + PathResolution::Def(Adt::from(it).into()) } - ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), - ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), - ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), - ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), - ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), - }; - Some(res) - }); + TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), + TypeNs::BuiltinType(it) => PathResolution::Def(it.into()), + TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), + }); + let values = + self.resolver.resolve_path_in_value_ns_fully(db, path.mod_path()).and_then(|val| { + let res = match val { + ValueNs::LocalBinding(pat_id) => { + let var = Local { parent: self.body_owner?, pat_id }; + PathResolution::Local(var) + } + ValueNs::FunctionId(it) => PathResolution::Def(Function::from(it).into()), + ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()), + ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()), + ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()), + ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()), + }; + Some(res) + }); let items = self .resolver - .resolve_module_path_in_items(db, &path) + .resolve_module_path_in_items(db, path.mod_path()) .take_types() .map(|it| PathResolution::Def(it.into())); types.or(values).or(items).or_else(|| { self.resolver - .resolve_path_as_macro(db, &path) + .resolve_path_as_macro(db, path.mod_path()) .map(|def| PathResolution::Macro(def.into())) }) } diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 5bf82e191c..9efa4970c1 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -12,7 +12,7 @@ use ra_syntax::{ use tt::Subtree; use crate::{ - db::DefDatabase, path::Path, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, + db::DefDatabase, path::ModPath, src::HasChildSource, src::HasSource, AdtId, AttrDefId, Lookup, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -94,7 +94,7 @@ impl Attrs { #[derive(Debug, Clone, PartialEq, Eq)] pub struct Attr { - pub(crate) path: Path, + pub(crate) path: ModPath, pub(crate) input: Option, } @@ -106,7 +106,7 @@ pub enum AttrInput { impl Attr { fn from_src(ast: ast::Attr, hygiene: &Hygiene) -> Option { - let path = Path::from_src(ast.path()?, hygiene)?; + let path = ModPath::from_src(ast.path()?, hygiene)?; let input = match ast.input() { None => None, Some(ast::AttrInput::Literal(lit)) => { diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index b3bc336cf9..7787cb87ff 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -83,7 +83,7 @@ impl Expander { fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option { self.crate_def_map - .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) + .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) .0 .take_macros() } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index bd237a7b3b..9aae7e48e2 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -74,7 +74,7 @@ use crate::{ builtin_type::BuiltinType, db::DefDatabase, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, - path::Path, + path::ModPath, per_ns::PerNs, AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, }; @@ -329,7 +329,7 @@ impl CrateDefMap { &self, db: &impl DefDatabase, original_module: LocalModuleId, - path: &Path, + path: &ModPath, shadow: BuiltinShadowMode, ) -> (PerNs, Option) { let res = diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 5d7469a6ec..912a073eac 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -22,7 +22,7 @@ use crate::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, }, - path::{Path, PathKind}, + path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, @@ -101,7 +101,7 @@ struct ImportDirective { struct MacroDirective { module_id: LocalModuleId, ast_id: AstId, - path: Path, + path: ModPath, legacy: Option, } @@ -113,7 +113,7 @@ struct DefCollector<'a, DB> { unresolved_imports: Vec, resolved_imports: Vec, unexpanded_macros: Vec, - unexpanded_attribute_macros: Vec<(LocalModuleId, AstId, Path)>, + unexpanded_attribute_macros: Vec<(LocalModuleId, AstId, ModPath)>, mod_dirs: FxHashMap, cfg_options: &'a CfgOptions, } @@ -428,7 +428,7 @@ where } else { match import.path.segments.last() { Some(last_segment) => { - let name = import.alias.clone().unwrap_or_else(|| last_segment.name.clone()); + let name = import.alias.clone().unwrap_or_else(|| last_segment.clone()); log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def); // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658 @@ -565,7 +565,7 @@ where res } - fn resolve_attribute_macro(&self, path: &Path) -> Option { + fn resolve_attribute_macro(&self, path: &ModPath) -> Option { // FIXME this is currently super hacky, just enough to support the // built-in derives if let Some(name) = path.as_ident() { @@ -829,7 +829,7 @@ where tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok _ => continue, // anything else would be an error (which we currently ignore) }; - let path = Path::from_tt_ident(ident); + let path = ModPath::from_tt_ident(ident); let ast_id = AstId::new(self.file_id, def.kind.ast_id()); self.def_collector.unexpanded_attribute_macros.push((self.module_id, ast_id, path)); @@ -917,7 +917,7 @@ where } } -fn is_macro_rules(path: &Path) -> bool { +fn is_macro_rules(path: &ModPath) -> bool { path.as_ident() == Some(&name![macro_rules]) } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index aab4b1dd97..4a249e7e72 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -17,7 +17,7 @@ use test_utils::tested_by; use crate::{ db::DefDatabase, nameres::{BuiltinShadowMode, CrateDefMap}, - path::{Path, PathKind}, + path::{ModPath, PathKind}, per_ns::PerNs, AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId, }; @@ -69,7 +69,7 @@ impl CrateDefMap { db: &impl DefDatabase, mode: ResolveMode, original_module: LocalModuleId, - path: &Path, + path: &ModPath, shadow: BuiltinShadowMode, ) -> ResolvePathResult { // if it is not the last segment, we prefer the module to the builtin @@ -113,7 +113,7 @@ impl CrateDefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in crate root (+ extern prelude)", segment); - self.resolve_name_in_crate_root_or_extern_prelude(&segment.name, prefer_module(idx)) + self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx)) } PathKind::Plain => { let (idx, segment) = match segments.next() { @@ -121,7 +121,7 @@ impl CrateDefMap { None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; log::debug!("resolving {:?} in module", segment); - self.resolve_name_in_module(db, original_module, &segment.name, prefer_module(idx)) + self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) } PathKind::Super => { if let Some(p) = self.modules[original_module].parent { @@ -137,7 +137,7 @@ impl CrateDefMap { Some((_, segment)) => segment, None => return ResolvePathResult::empty(ReachedFixedPoint::Yes), }; - if let Some(def) = self.extern_prelude.get(&segment.name) { + if let Some(def) = self.extern_prelude.get(&segment) { log::debug!("absolute path {:?} resolved to crate {:?}", path, def); PerNs::types(*def) } else { @@ -168,8 +168,10 @@ impl CrateDefMap { curr_per_ns = match curr { ModuleDefId::ModuleId(module) => { if module.krate != self.krate { - let path = - Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ }; + let path = ModPath { + segments: path.segments[i..].to_vec(), + kind: PathKind::Self_, + }; log::debug!("resolving {:?} in other crate", path); let defp_map = db.crate_def_map(module.krate); let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow); @@ -182,10 +184,10 @@ impl CrateDefMap { } // Since it is a qualified path here, it should not contains legacy macros - match self[module.local_id].scope.get(&segment.name, prefer_module(i)) { + match self[module.local_id].scope.get(&segment, prefer_module(i)) { Some(res) => res.def, _ => { - log::debug!("path segment {:?} not found", segment.name); + log::debug!("path segment {:?} not found", segment); return ResolvePathResult::empty(ReachedFixedPoint::No); } } @@ -194,7 +196,7 @@ impl CrateDefMap { // enum variant tested_by!(can_import_enum_variant); let enum_data = db.enum_data(e); - match enum_data.variant(&segment.name) { + match enum_data.variant(&segment) { Some(local_id) => { let variant = EnumVariantId { parent: e, local_id }; PerNs::both(variant.into(), variant.into()) @@ -214,7 +216,7 @@ impl CrateDefMap { // (`Struct::method`), or some other kind of associated item log::debug!( "path segment {:?} resolved to non-module {:?}, but is not last", - segment.name, + segment, curr, ); diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index a2821e1c3c..ecb4d7c03d 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -22,7 +22,7 @@ use ra_syntax::{ use test_utils::tested_by; use crate::{ - attr::Attrs, db::DefDatabase, path::Path, trace::Trace, FileAstId, HirFileId, InFile, + attr::Attrs, db::DefDatabase, path::ModPath, trace::Trace, FileAstId, HirFileId, InFile, LocalImportId, }; @@ -154,7 +154,7 @@ pub(super) enum ModuleData { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ImportData { - pub(super) path: Path, + pub(super) path: ModPath, pub(super) alias: Option, pub(super) is_glob: bool, pub(super) is_prelude: bool, @@ -206,7 +206,7 @@ impl_arena_id!(Macro); #[derive(Debug, PartialEq, Eq)] pub(super) struct MacroData { pub(super) ast_id: FileAstId, - pub(super) path: Path, + pub(super) path: ModPath, pub(super) name: Option, pub(super) export: bool, pub(super) builtin: bool, @@ -327,7 +327,7 @@ impl RawItemsCollector { let attrs = self.parse_attrs(&use_item); let mut buf = Vec::new(); - Path::expand_use_item( + ModPath::expand_use_item( InFile { value: use_item, file_id: self.file_id }, &self.hygiene, |path, use_tree, is_glob, alias| { @@ -353,7 +353,7 @@ impl RawItemsCollector { extern_crate: ast::ExternCrateItem, ) { if let Some(name_ref) = extern_crate.name_ref() { - let path = Path::from_name_ref(&name_ref); + let path = ModPath::from_name_ref(&name_ref); let alias = extern_crate.alias().and_then(|a| a.name()).map(|it| it.as_name()); let attrs = self.parse_attrs(&extern_crate); // FIXME: cfg_attr @@ -377,7 +377,7 @@ impl RawItemsCollector { fn add_macro(&mut self, current_module: Option, m: ast::MacroCall) { let attrs = self.parse_attrs(&m); - let path = match m.path().and_then(|path| Path::from_src(path, &self.hygiene)) { + let path = match m.path().and_then(|path| ModPath::from_src(path, &self.hygiene)) { Some(it) => it, _ => return, }; diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 1e9eb14ea5..20d6d98ea0 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -1,31 +1,78 @@ //! A desugared representation of paths like `crate::foo` or `::bar`. -mod lower_use; +mod lower; use std::{iter, sync::Arc}; -use either::Either; use hir_expand::{ hygiene::Hygiene, - name::{name, AsName, Name}, + name::{AsName, Name}, }; use ra_db::CrateId; -use ra_syntax::{ - ast::{self, TypeAscriptionOwner}, - AstNode, -}; +use ra_syntax::ast; use crate::{type_ref::TypeRef, InFile}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct Path { +pub struct ModPath { pub kind: PathKind, - pub segments: Vec, + pub segments: Vec, +} + +impl ModPath { + pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { + lower::lower_path(path, hygiene).map(|it| it.mod_path) + } + + pub fn from_simple_segments( + kind: PathKind, + segments: impl IntoIterator, + ) -> ModPath { + let segments = segments.into_iter().collect::>(); + ModPath { kind, segments } + } + + pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> ModPath { + name_ref.as_name().into() + } + + /// Converts an `tt::Ident` into a single-identifier `Path`. + pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath { + ident.as_name().into() + } + + /// Calls `cb` with all paths, represented by this use item. + pub(crate) fn expand_use_item( + item_src: InFile, + hygiene: &Hygiene, + mut cb: impl FnMut(ModPath, &ast::UseTree, /* is_glob */ bool, Option), + ) { + if let Some(tree) = item_src.value.use_tree() { + lower::lower_use_tree(None, tree, hygiene, &mut cb); + } + } + + pub fn is_ident(&self) -> bool { + self.kind == PathKind::Plain && self.segments.len() == 1 + } + + pub fn is_self(&self) -> bool { + self.kind == PathKind::Self_ && self.segments.is_empty() + } + + /// If this path is a single identifier, like `foo`, return its name. + pub fn as_ident(&self) -> Option<&Name> { + if self.kind != PathKind::Plain || self.segments.len() > 1 { + return None; + } + self.segments.first() + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct PathSegment { - pub name: Name, - pub args_and_bindings: Option>, +pub struct Path { + mod_path: ModPath, + /// Invariant: the same len as self.path.segments + generic_args: Vec>>, } /// Generic arguments to a path segment (e.g. the `i32` in `Option`). This @@ -65,221 +112,110 @@ pub enum PathKind { } impl Path { - /// Calls `cb` with all paths, represented by this use item. - pub(crate) fn expand_use_item( - item_src: InFile, - hygiene: &Hygiene, - mut cb: impl FnMut(Path, &ast::UseTree, bool, Option), - ) { - if let Some(tree) = item_src.value.use_tree() { - lower_use::lower_use_tree(None, tree, hygiene, &mut cb); - } - } - - pub fn from_simple_segments(kind: PathKind, segments: impl IntoIterator) -> Path { - Path { - kind, - segments: segments - .into_iter() - .map(|name| PathSegment { name, args_and_bindings: None }) - .collect(), - } - } - /// Converts an `ast::Path` to `Path`. Works with use trees. /// DEPRECATED: It does not handle `$crate` from macro call. pub fn from_ast(path: ast::Path) -> Option { - Path::from_src(path, &Hygiene::new_unhygienic()) + lower::lower_path(path, &Hygiene::new_unhygienic()) } /// Converts an `ast::Path` to `Path`. Works with use trees. /// It correctly handles `$crate` based path from macro call. - pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option { - let mut kind = PathKind::Plain; - let mut segments = Vec::new(); - loop { - let segment = path.segment()?; - - if segment.has_colon_colon() { - kind = PathKind::Abs; - } - - match segment.kind()? { - ast::PathSegmentKind::Name(name_ref) => { - // FIXME: this should just return name - match hygiene.name_ref_to_name(name_ref) { - Either::Left(name) => { - let args = segment - .type_arg_list() - .and_then(GenericArgs::from_ast) - .or_else(|| { - GenericArgs::from_fn_like_path_ast( - segment.param_list(), - segment.ret_type(), - ) - }) - .map(Arc::new); - let segment = PathSegment { name, args_and_bindings: args }; - segments.push(segment); - } - Either::Right(crate_id) => { - kind = PathKind::DollarCrate(crate_id); - break; - } - } - } - ast::PathSegmentKind::Type { type_ref, trait_ref } => { - assert!(path.qualifier().is_none()); // this can only occur at the first segment - - let self_type = TypeRef::from_ast(type_ref?); - - match trait_ref { - // ::foo - None => { - kind = PathKind::Type(Box::new(self_type)); - } - // >::Foo desugars to Trait::Foo - Some(trait_ref) => { - let path = Path::from_src(trait_ref.path()?, hygiene)?; - kind = path.kind; - let mut prefix_segments = path.segments; - prefix_segments.reverse(); - segments.extend(prefix_segments); - // Insert the type reference (T in the above example) as Self parameter for the trait - let mut last_segment = segments.last_mut()?; - if last_segment.args_and_bindings.is_none() { - last_segment.args_and_bindings = - Some(Arc::new(GenericArgs::empty())); - }; - let args = last_segment.args_and_bindings.as_mut().unwrap(); - let mut args_inner = Arc::make_mut(args); - args_inner.has_self_type = true; - args_inner.args.insert(0, GenericArg::Type(self_type)); - } - } - } - ast::PathSegmentKind::CrateKw => { - kind = PathKind::Crate; - break; - } - ast::PathSegmentKind::SelfKw => { - kind = PathKind::Self_; - break; - } - ast::PathSegmentKind::SuperKw => { - kind = PathKind::Super; - break; - } - } - path = match qualifier(&path) { - Some(it) => it, - None => break, - }; - } - segments.reverse(); - return Some(Path { kind, segments }); - - fn qualifier(path: &ast::Path) -> Option { - if let Some(q) = path.qualifier() { - return Some(q); - } - // FIXME: this bottom up traversal is not too precise. - // Should we handle do a top-down analysis, recording results? - let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?; - let use_tree = use_tree_list.parent_use_tree(); - use_tree.path() - } + pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { + lower::lower_path(path, hygiene) } /// Converts an `ast::NameRef` into a single-identifier `Path`. pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { - name_ref.as_name().into() - } - - /// Converts an `tt::Ident` into a single-identifier `Path`. - pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path { - ident.as_name().into() - } - - /// `true` is this path is a single identifier, like `foo` - pub fn is_ident(&self) -> bool { - self.kind == PathKind::Plain && self.segments.len() == 1 + Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } } /// `true` if this path is just a standalone `self` pub fn is_self(&self) -> bool { - self.kind == PathKind::Self_ && self.segments.is_empty() + self.mod_path.is_self() } - /// If this path is a single identifier, like `foo`, return its name. - pub fn as_ident(&self) -> Option<&Name> { - if self.kind != PathKind::Plain || self.segments.len() > 1 { + pub fn kind(&self) -> &PathKind { + &self.mod_path.kind + } + + pub fn segments(&self) -> PathSegments<'_> { + PathSegments { + segments: self.mod_path.segments.as_slice(), + generic_args: self.generic_args.as_slice(), + } + } + + pub fn mod_path(&self) -> &ModPath { + &self.mod_path + } + + pub fn qualifier(&self) -> Option { + if self.mod_path.is_ident() { return None; } - self.segments.first().map(|s| &s.name) + let res = Path { + mod_path: ModPath { + kind: self.mod_path.kind.clone(), + segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), + }, + generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), + }; + Some(res) } +} - pub fn expand_macro_expr(&self) -> Option { - self.as_ident().and_then(|name| Some(name.clone())) +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct PathSegment<'a> { + pub name: &'a Name, + pub args_and_bindings: Option<&'a GenericArgs>, +} + +pub struct PathSegments<'a> { + segments: &'a [Name], + generic_args: &'a [Option>], +} + +impl<'a> PathSegments<'a> { + pub const EMPTY: PathSegments<'static> = PathSegments { segments: &[], generic_args: &[] }; + pub fn is_empty(&self) -> bool { + self.len() == 0 } - - pub fn is_type_relative(&self) -> bool { - match self.kind { - PathKind::Type(_) => true, - _ => false, - } + pub fn len(&self) -> usize { + self.segments.len() + } + pub fn first(&self) -> Option> { + self.get(0) + } + pub fn last(&self) -> Option> { + self.get(self.len().checked_sub(1)?) + } + pub fn get(&self, idx: usize) -> Option> { + assert_eq!(self.segments.len(), self.generic_args.len()); + let res = PathSegment { + name: self.segments.get(idx)?, + args_and_bindings: self.generic_args.get(idx).unwrap().as_ref().map(|it| &**it), + }; + Some(res) + } + pub fn skip(&self, len: usize) -> PathSegments<'a> { + assert_eq!(self.segments.len(), self.generic_args.len()); + PathSegments { segments: &self.segments[len..], generic_args: &self.generic_args[len..] } + } + pub fn take(&self, len: usize) -> PathSegments<'a> { + assert_eq!(self.segments.len(), self.generic_args.len()); + PathSegments { segments: &self.segments[..len], generic_args: &self.generic_args[..len] } + } + pub fn iter(&self) -> impl Iterator> { + self.segments.iter().zip(self.generic_args.iter()).map(|(name, args)| PathSegment { + name, + args_and_bindings: args.as_ref().map(|it| &**it), + }) } } impl GenericArgs { pub(crate) fn from_ast(node: ast::TypeArgList) -> Option { - let mut args = Vec::new(); - for type_arg in node.type_args() { - let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); - args.push(GenericArg::Type(type_ref)); - } - // lifetimes ignored for now - let mut bindings = Vec::new(); - for assoc_type_arg in node.assoc_type_args() { - if let Some(name_ref) = assoc_type_arg.name_ref() { - let name = name_ref.as_name(); - let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); - bindings.push((name, type_ref)); - } - } - if args.is_empty() && bindings.is_empty() { - None - } else { - Some(GenericArgs { args, has_self_type: false, bindings }) - } - } - - /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) - /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). - pub(crate) fn from_fn_like_path_ast( - params: Option, - ret_type: Option, - ) -> Option { - let mut args = Vec::new(); - let mut bindings = Vec::new(); - if let Some(params) = params { - let mut param_types = Vec::new(); - for param in params.params() { - let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); - param_types.push(type_ref); - } - let arg = GenericArg::Type(TypeRef::Tuple(param_types)); - args.push(arg); - } - if let Some(ret_type) = ret_type { - let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); - bindings.push((name![Output], type_ref)) - } - if args.is_empty() && bindings.is_empty() { - None - } else { - Some(GenericArgs { args, has_self_type: false, bindings }) - } + lower::lower_generic_args(node) } pub(crate) fn empty() -> GenericArgs { @@ -289,7 +225,16 @@ impl GenericArgs { impl From for Path { fn from(name: Name) -> Path { - Path::from_simple_segments(PathKind::Plain, iter::once(name)) + Path { + mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), + generic_args: vec![None], + } + } +} + +impl From for ModPath { + fn from(name: Name) -> ModPath { + ModPath::from_simple_segments(PathKind::Plain, iter::once(name)) } } @@ -319,7 +264,7 @@ macro_rules! __known_path { macro_rules! __path { ($start:ident $(:: $seg:ident)*) => ({ $crate::__known_path!($start $(:: $seg)*); - $crate::path::Path::from_simple_segments($crate::path::PathKind::Abs, vec![ + $crate::path::ModPath::from_simple_segments($crate::path::PathKind::Abs, vec![ $crate::path::__name![$start], $($crate::path::__name![$seg],)* ]) }); diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs new file mode 100644 index 0000000000..a2e9951980 --- /dev/null +++ b/crates/ra_hir_def/src/path/lower.rs @@ -0,0 +1,176 @@ +//! Transforms syntax into `Path` objects, ideally with accounting for hygiene + +mod lower_use; + +use std::sync::Arc; + +use either::Either; +use hir_expand::{ + hygiene::Hygiene, + name::{name, AsName}, +}; +use ra_syntax::ast::{self, AstNode, TypeAscriptionOwner}; + +use crate::{ + path::{GenericArg, GenericArgs, ModPath, Path, PathKind}, + type_ref::TypeRef, +}; + +pub(super) use lower_use::lower_use_tree; + +/// Converts an `ast::Path` to `Path`. Works with use trees. +/// It correctly handles `$crate` based path from macro call. +pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option { + let mut kind = PathKind::Plain; + let mut segments = Vec::new(); + let mut generic_args = Vec::new(); + loop { + let segment = path.segment()?; + + if segment.has_colon_colon() { + kind = PathKind::Abs; + } + + match segment.kind()? { + ast::PathSegmentKind::Name(name_ref) => { + // FIXME: this should just return name + match hygiene.name_ref_to_name(name_ref) { + Either::Left(name) => { + let args = segment + .type_arg_list() + .and_then(lower_generic_args) + .or_else(|| { + lower_generic_args_from_fn_path( + segment.param_list(), + segment.ret_type(), + ) + }) + .map(Arc::new); + segments.push(name); + generic_args.push(args) + } + Either::Right(crate_id) => { + kind = PathKind::DollarCrate(crate_id); + break; + } + } + } + ast::PathSegmentKind::Type { type_ref, trait_ref } => { + assert!(path.qualifier().is_none()); // this can only occur at the first segment + + let self_type = TypeRef::from_ast(type_ref?); + + match trait_ref { + // ::foo + None => { + kind = PathKind::Type(Box::new(self_type)); + } + // >::Foo desugars to Trait::Foo + Some(trait_ref) => { + let path = Path::from_src(trait_ref.path()?, hygiene)?; + kind = path.mod_path.kind; + + let mut prefix_segments = path.mod_path.segments; + prefix_segments.reverse(); + segments.extend(prefix_segments); + + let mut prefix_args = path.generic_args; + prefix_args.reverse(); + generic_args.extend(prefix_args); + + // Insert the type reference (T in the above example) as Self parameter for the trait + let last_segment = generic_args.last_mut()?; + if last_segment.is_none() { + *last_segment = Some(Arc::new(GenericArgs::empty())); + }; + let args = last_segment.as_mut().unwrap(); + let mut args_inner = Arc::make_mut(args); + args_inner.has_self_type = true; + args_inner.args.insert(0, GenericArg::Type(self_type)); + } + } + } + ast::PathSegmentKind::CrateKw => { + kind = PathKind::Crate; + break; + } + ast::PathSegmentKind::SelfKw => { + kind = PathKind::Self_; + break; + } + ast::PathSegmentKind::SuperKw => { + kind = PathKind::Super; + break; + } + } + path = match qualifier(&path) { + Some(it) => it, + None => break, + }; + } + segments.reverse(); + generic_args.reverse(); + let mod_path = ModPath { kind, segments }; + return Some(Path { mod_path, generic_args }); + + fn qualifier(path: &ast::Path) -> Option { + if let Some(q) = path.qualifier() { + return Some(q); + } + // FIXME: this bottom up traversal is not too precise. + // Should we handle do a top-down analysis, recording results? + let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?; + let use_tree = use_tree_list.parent_use_tree(); + use_tree.path() + } +} + +pub(super) fn lower_generic_args(node: ast::TypeArgList) -> Option { + let mut args = Vec::new(); + for type_arg in node.type_args() { + let type_ref = TypeRef::from_ast_opt(type_arg.type_ref()); + args.push(GenericArg::Type(type_ref)); + } + // lifetimes ignored for now + let mut bindings = Vec::new(); + for assoc_type_arg in node.assoc_type_args() { + if let Some(name_ref) = assoc_type_arg.name_ref() { + let name = name_ref.as_name(); + let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref()); + bindings.push((name, type_ref)); + } + } + if args.is_empty() && bindings.is_empty() { + None + } else { + Some(GenericArgs { args, has_self_type: false, bindings }) + } +} + +/// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y) +/// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`). +fn lower_generic_args_from_fn_path( + params: Option, + ret_type: Option, +) -> Option { + let mut args = Vec::new(); + let mut bindings = Vec::new(); + if let Some(params) = params { + let mut param_types = Vec::new(); + for param in params.params() { + let type_ref = TypeRef::from_ast_opt(param.ascribed_type()); + param_types.push(type_ref); + } + let arg = GenericArg::Type(TypeRef::Tuple(param_types)); + args.push(arg); + } + if let Some(ret_type) = ret_type { + let type_ref = TypeRef::from_ast_opt(ret_type.type_ref()); + bindings.push((name![Output], type_ref)) + } + if args.is_empty() && bindings.is_empty() { + None + } else { + Some(GenericArgs { args, has_self_type: false, bindings }) + } +} diff --git a/crates/ra_hir_def/src/path/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs similarity index 81% rename from crates/ra_hir_def/src/path/lower_use.rs rename to crates/ra_hir_def/src/path/lower/lower_use.rs index e2e1f716dc..ea3fdb56cc 100644 --- a/crates/ra_hir_def/src/path/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs @@ -10,13 +10,13 @@ use hir_expand::{ }; use ra_syntax::ast::{self, NameOwner}; -use crate::path::{Path, PathKind, PathSegment}; +use crate::path::{ModPath, PathKind}; pub(crate) fn lower_use_tree( - prefix: Option, + prefix: Option, tree: ast::UseTree, hygiene: &Hygiene, - cb: &mut dyn FnMut(Path, &ast::UseTree, bool, Option), + cb: &mut dyn FnMut(ModPath, &ast::UseTree, bool, Option), ) { if let Some(use_tree_list) = tree.use_tree_list() { let prefix = match tree.path() { @@ -57,7 +57,7 @@ pub(crate) fn lower_use_tree( } } -fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Option { +fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Option { let prefix = if let Some(qual) = path.qualifier() { Some(convert_path(prefix, qual, hygiene)?) } else { @@ -70,18 +70,15 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt match hygiene.name_ref_to_name(name_ref) { Either::Left(name) => { // no type args in use - let mut res = prefix.unwrap_or_else(|| Path { + let mut res = prefix.unwrap_or_else(|| ModPath { kind: PathKind::Plain, segments: Vec::with_capacity(1), }); - res.segments.push(PathSegment { - name, - args_and_bindings: None, // no type args in use - }); + res.segments.push(name); res } Either::Right(crate_id) => { - return Some(Path::from_simple_segments( + return Some(ModPath::from_simple_segments( PathKind::DollarCrate(crate_id), iter::empty(), )) @@ -92,19 +89,19 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> Opt if prefix.is_some() { return None; } - Path::from_simple_segments(PathKind::Crate, iter::empty()) + ModPath::from_simple_segments(PathKind::Crate, iter::empty()) } ast::PathSegmentKind::SelfKw => { if prefix.is_some() { return None; } - Path::from_simple_segments(PathKind::Self_, iter::empty()) + ModPath::from_simple_segments(PathKind::Self_, iter::empty()) } ast::PathSegmentKind::SuperKw => { if prefix.is_some() { return None; } - Path::from_simple_segments(PathKind::Super, iter::empty()) + ModPath::from_simple_segments(PathKind::Super, iter::empty()) } ast::PathSegmentKind::Type { .. } => { // not allowed in imports diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index b6d595a209..2694c0438b 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -15,7 +15,7 @@ use crate::{ expr::{ExprId, PatId}, generics::GenericParams, nameres::{BuiltinShadowMode, CrateDefMap}, - path::{Path, PathKind}, + path::{ModPath, PathKind}, per_ns::PerNs, AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, @@ -91,7 +91,7 @@ pub enum ValueNs { impl Resolver { /// Resolve known trait from std, like `std::futures::Future` - pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &Path) -> Option { + pub fn resolve_known_trait(&self, db: &impl DefDatabase, path: &ModPath) -> Option { let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::TraitId(it) => Some(it), @@ -100,7 +100,7 @@ impl Resolver { } /// Resolve known struct from std, like `std::boxed::Box` - pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &Path) -> Option { + pub fn resolve_known_struct(&self, db: &impl DefDatabase, path: &ModPath) -> Option { let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::AdtId(AdtId::StructId(it)) => Some(it), @@ -109,7 +109,7 @@ impl Resolver { } /// Resolve known enum from std, like `std::result::Result` - pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &Path) -> Option { + pub fn resolve_known_enum(&self, db: &impl DefDatabase, path: &ModPath) -> Option { let res = self.resolve_module_path(db, path, BuiltinShadowMode::Other).take_types()?; match res { ModuleDefId::AdtId(AdtId::EnumId(it)) => Some(it), @@ -120,33 +120,30 @@ impl Resolver { fn resolve_module_path( &self, db: &impl DefDatabase, - path: &Path, + path: &ModPath, shadow: BuiltinShadowMode, ) -> PerNs { let (item_map, module) = match self.module() { Some(it) => it, None => return PerNs::none(), }; - let (module_res, segment_index) = item_map.resolve_path(db, module, path, shadow); + let (module_res, segment_index) = item_map.resolve_path(db, module, &path, shadow); if segment_index.is_some() { return PerNs::none(); } module_res } - pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &Path) -> PerNs { + pub fn resolve_module_path_in_items(&self, db: &impl DefDatabase, path: &ModPath) -> PerNs { self.resolve_module_path(db, path, BuiltinShadowMode::Module) } pub fn resolve_path_in_type_ns( &self, db: &impl DefDatabase, - path: &Path, + path: &ModPath, ) -> Option<(TypeNs, Option)> { - if path.is_type_relative() { - return None; - } - let first_name = &path.segments.first()?.name; + let first_name = path.segments.first()?; let skip_to_mod = path.kind != PathKind::Plain; for scope in self.scopes.iter().rev() { match scope { @@ -178,7 +175,7 @@ impl Resolver { let (module_def, idx) = m.crate_def_map.resolve_path( db, m.module_id, - path, + &path, BuiltinShadowMode::Other, ); let res = match module_def.take_types()? { @@ -205,7 +202,7 @@ impl Resolver { pub fn resolve_path_in_type_ns_fully( &self, db: &impl DefDatabase, - path: &Path, + path: &ModPath, ) -> Option { let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?; if unresolved.is_some() { @@ -214,17 +211,14 @@ impl Resolver { Some(res) } - pub fn resolve_path_in_value_ns<'p>( + pub fn resolve_path_in_value_ns( &self, db: &impl DefDatabase, - path: &'p Path, + path: &ModPath, ) -> Option { - if path.is_type_relative() { - return None; - } let n_segments = path.segments.len(); let tmp = name![self]; - let first_name = if path.is_self() { &tmp } else { &path.segments.first()?.name }; + let first_name = if path.is_self() { &tmp } else { &path.segments.first()? }; let skip_to_mod = path.kind != PathKind::Plain && !path.is_self(); for scope in self.scopes.iter().rev() { match scope { @@ -276,7 +270,7 @@ impl Resolver { let (module_def, idx) = m.crate_def_map.resolve_path( db, m.module_id, - path, + &path, BuiltinShadowMode::Other, ); return match idx { @@ -322,7 +316,7 @@ impl Resolver { pub fn resolve_path_in_value_ns_fully( &self, db: &impl DefDatabase, - path: &Path, + path: &ModPath, ) -> Option { match self.resolve_path_in_value_ns(db, path)? { ResolveValueResult::ValueNs(it) => Some(it), @@ -330,9 +324,13 @@ impl Resolver { } } - pub fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option { + pub fn resolve_path_as_macro( + &self, + db: &impl DefDatabase, + path: &ModPath, + ) -> Option { let (item_map, module) = self.module()?; - item_map.resolve_path(db, module, path, BuiltinShadowMode::Other).0.take_macros() + item_map.resolve_path(db, module, &path, BuiltinShadowMode::Other).0.take_macros() } pub fn process_all_names(&self, db: &impl DefDatabase, f: &mut dyn FnMut(Name, ScopeDef)) { diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index f1b7e9442d..af42854cce 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -386,7 +386,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let resolver = &self.resolver; // FIXME: this should resolve assoc items as well, see this example: // https://play.rust-lang.org/?gist=087992e9e22495446c01c0d4e2d69521 - match resolver.resolve_path_in_type_ns_fully(self.db, &path) { + match resolver.resolve_path_in_type_ns_fully(self.db, path.mod_path()) { Some(TypeNs::AdtId(AdtId::StructId(strukt))) => { let substs = Ty::substs_from_path(self.db, resolver, path, strukt.into()); let ty = self.db.ty(strukt.into()); diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 37db005ea5..3bae0ca6c2 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -32,21 +32,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { path: &Path, id: ExprOrPatId, ) -> Option { - let (value, self_subst) = if let PathKind::Type(type_ref) = &path.kind { - if path.segments.is_empty() { + let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() { + if path.segments().is_empty() { // This can't actually happen syntax-wise return None; } let ty = self.make_ty(type_ref); - let remaining_segments_for_ty = &path.segments[..path.segments.len() - 1]; + let remaining_segments_for_ty = path.segments().take(path.segments().len() - 1); let ty = Ty::from_type_relative_path(self.db, resolver, ty, remaining_segments_for_ty); self.resolve_ty_assoc_item( ty, - &path.segments.last().expect("path had at least one segment").name, + &path.segments().last().expect("path had at least one segment").name, id, )? } else { - let value_or_partial = resolver.resolve_path_in_value_ns(self.db, &path)?; + let value_or_partial = resolver.resolve_path_in_value_ns(self.db, path.mod_path())?; match value_or_partial { ResolveValueResult::ValueNs(it) => (it, None), @@ -85,13 +85,13 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { remaining_index: usize, id: ExprOrPatId, ) -> Option<(ValueNs, Option)> { - assert!(remaining_index < path.segments.len()); + assert!(remaining_index < path.segments().len()); // there may be more intermediate segments between the resolved one and // the end. Only the last segment needs to be resolved to a value; from // the segments before that, we need to get either a type or a trait ref. - let resolved_segment = &path.segments[remaining_index - 1]; - let remaining_segments = &path.segments[remaining_index..]; + let resolved_segment = path.segments().get(remaining_index - 1).unwrap(); + let remaining_segments = path.segments().skip(remaining_index); let is_before_last = remaining_segments.len() == 1; match (def, is_before_last) { @@ -112,7 +112,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // trait but it's not the last segment, so the next segment // should resolve to an associated type of that trait (e.g. `::Item::default`) - let remaining_segments_for_ty = &remaining_segments[..remaining_segments.len() - 1]; + let remaining_segments_for_ty = + remaining_segments.take(remaining_segments.len() - 1); let ty = Ty::from_partly_resolved_hir_path( self.db, &self.resolver, @@ -138,7 +139,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn resolve_trait_assoc_item( &mut self, trait_ref: TraitRef, - segment: &PathSegment, + segment: PathSegment<'_>, id: ExprOrPatId, ) -> Option<(ValueNs, Option)> { let trait_ = trait_ref.trait_; @@ -150,7 +151,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .map(|(_name, id)| (*id).into()) .find_map(|item| match item { AssocItemId::FunctionId(func) => { - if segment.name == self.db.function_data(func).name { + if segment.name == &self.db.function_data(func).name { Some(AssocItemId::FunctionId(func)) } else { None @@ -158,7 +159,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } AssocItemId::ConstId(konst) => { - if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == &segment.name) + if self.db.const_data(konst).name.as_ref().map_or(false, |n| n == segment.name) { Some(AssocItemId::ConstId(konst)) } else { diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 5f795bc022..a4ddfc8efb 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, generics::WherePredicate, - path::{GenericArg, Path, PathKind, PathSegment}, + path::{GenericArg, Path, PathKind, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, @@ -101,13 +101,13 @@ impl Ty { TypeRef::Path(path) => path, _ => return None, }; - if let PathKind::Type(_) = &path.kind { + if let PathKind::Type(_) = path.kind() { return None; } - if path.segments.len() > 1 { + if path.segments().len() > 1 { return None; } - let resolution = match resolver.resolve_path_in_type_ns(db, path) { + let resolution = match resolver.resolve_path_in_type_ns(db, path.mod_path()) { Some((it, None)) => it, _ => return None, }; @@ -124,11 +124,11 @@ impl Ty { db: &impl HirDatabase, resolver: &Resolver, ty: Ty, - remaining_segments: &[PathSegment], + remaining_segments: PathSegments<'_>, ) -> Ty { if remaining_segments.len() == 1 { // resolve unselected assoc types - let segment = &remaining_segments[0]; + let segment = remaining_segments.first().unwrap(); Ty::select_associated_type(db, resolver, ty, segment) } else if remaining_segments.len() > 1 { // FIXME report error (ambiguous associated type) @@ -142,15 +142,15 @@ impl Ty { db: &impl HirDatabase, resolver: &Resolver, resolution: TypeNs, - resolved_segment: &PathSegment, - remaining_segments: &[PathSegment], + resolved_segment: PathSegment<'_>, + remaining_segments: PathSegments<'_>, ) -> Ty { let ty = match resolution { TypeNs::TraitId(trait_) => { let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None); return if remaining_segments.len() == 1 { - let segment = &remaining_segments[0]; + let segment = remaining_segments.first().unwrap(); let associated_ty = associated_type_by_name_including_super_traits( db, trait_ref.trait_, @@ -202,21 +202,21 @@ impl Ty { pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { // Resolve the path (in type namespace) - if let PathKind::Type(type_ref) = &path.kind { + if let PathKind::Type(type_ref) = path.kind() { let ty = Ty::from_hir(db, resolver, &type_ref); - let remaining_segments = &path.segments[..]; - return Ty::from_type_relative_path(db, resolver, ty, remaining_segments); + return Ty::from_type_relative_path(db, resolver, ty, path.segments()); } - let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { - Some(it) => it, - None => return Ty::Unknown, - }; + let (resolution, remaining_index) = + match resolver.resolve_path_in_type_ns(db, path.mod_path()) { + Some(it) => it, + None => return Ty::Unknown, + }; let (resolved_segment, remaining_segments) = match remaining_index { None => ( - path.segments.last().expect("resolved path has at least one element"), - &[] as &[PathSegment], + path.segments().last().expect("resolved path has at least one element"), + PathSegments::EMPTY, ), - Some(i) => (&path.segments[i - 1], &path.segments[i..]), + Some(i) => (path.segments().get(i - 1).unwrap(), path.segments().skip(i)), }; Ty::from_partly_resolved_hir_path( db, @@ -231,7 +231,7 @@ impl Ty { db: &impl HirDatabase, resolver: &Resolver, self_ty: Ty, - segment: &PathSegment, + segment: PathSegment<'_>, ) -> Ty { let param_idx = match self_ty { Ty::Param { idx, .. } => idx, @@ -261,7 +261,7 @@ impl Ty { fn from_hir_path_inner( db: &impl HirDatabase, resolver: &Resolver, - segment: &PathSegment, + segment: PathSegment<'_>, typable: TyDefId, ) -> Ty { let generic_def = match typable { @@ -284,7 +284,7 @@ impl Ty { // special-case enum variants resolved: ValueTyDefId, ) -> Substs { - let last = path.segments.last().expect("path should have at least one segment"); + let last = path.segments().last().expect("path should have at least one segment"); let (segment, generic_def) = match resolved { ValueTyDefId::FunctionId(it) => (last, Some(it.into())), ValueTyDefId::StructId(it) => (last, Some(it.into())), @@ -296,13 +296,11 @@ impl Ty { // referring to the variant. So `Option::::None` and // `Option::None::` are both allowed (though the former is // preferred). See also `def_ids_for_path_segments` in rustc. - let len = path.segments.len(); - let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { - // Option::::None - &path.segments[len - 2] - } else { - // Option::None:: - last + let len = path.segments().len(); + let penultimate = if len >= 2 { path.segments().get(len - 2) } else { None }; + let segment = match penultimate { + Some(segment) if segment.args_and_bindings.is_some() => segment, + _ => last, }; (segment, Some(var.parent.into())) } @@ -314,7 +312,7 @@ impl Ty { pub(super) fn substs_from_path_segment( db: &impl HirDatabase, resolver: &Resolver, - segment: &PathSegment, + segment: PathSegment<'_>, def_generic: Option, add_self_param: bool, ) -> Substs { @@ -372,11 +370,11 @@ impl TraitRef { path: &Path, explicit_self_ty: Option, ) -> Option { - let resolved = match resolver.resolve_path_in_type_ns_fully(db, &path)? { + let resolved = match resolver.resolve_path_in_type_ns_fully(db, path.mod_path())? { TypeNs::TraitId(tr) => tr, _ => return None, }; - let segment = path.segments.last().expect("path should have at least one segment"); + let segment = path.segments().last().expect("path should have at least one segment"); Some(TraitRef::from_resolved_path(db, resolver, resolved.into(), segment, explicit_self_ty)) } @@ -384,7 +382,7 @@ impl TraitRef { db: &impl HirDatabase, resolver: &Resolver, resolved: TraitId, - segment: &PathSegment, + segment: PathSegment<'_>, explicit_self_ty: Option, ) -> Self { let mut substs = TraitRef::substs_from_path(db, resolver, segment, resolved); @@ -410,7 +408,7 @@ impl TraitRef { fn substs_from_path( db: &impl HirDatabase, resolver: &Resolver, - segment: &PathSegment, + segment: PathSegment<'_>, resolved: TraitId, ) -> Substs { let has_self_param = @@ -464,12 +462,12 @@ fn assoc_type_bindings_from_type_bound<'a>( trait_ref: TraitRef, ) -> impl Iterator + 'a { let last_segment = match bound { - TypeBound::Path(path) => path.segments.last(), + TypeBound::Path(path) => path.segments().last(), TypeBound::Error => None, }; last_segment .into_iter() - .flat_map(|segment| segment.args_and_bindings.iter()) + .flat_map(|segment| segment.args_and_bindings.into_iter()) .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) .map(move |(name, type_ref)| { let associated_ty = diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 0049d3c6fc..29799a8cbd 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -6,6 +6,7 @@ use hir_def::{ adt::VariantData, db::DefDatabase, generics::{GenericParams, TypeParamData}, + path::Path, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, @@ -22,10 +23,10 @@ fn direct_super_traits(db: &impl DefDatabase, trait_: TraitId) -> Vec { .where_predicates .iter() .filter_map(|pred| match &pred.type_ref { - TypeRef::Path(p) if p.as_ident() == Some(&name![Self]) => pred.bound.as_path(), + TypeRef::Path(p) if p == &Path::from(name![Self]) => pred.bound.as_path(), _ => None, }) - .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path) { + .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { Some(TypeNs::TraitId(t)) => Some(t), _ => None, }) diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index ca0a483d4b..981da2b794 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -188,10 +188,9 @@ impl<'a> CompletionContext<'a> { self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); self.has_type_args = segment.type_arg_list().is_some(); - if let Some(mut path) = hir::Path::from_ast(path.clone()) { - if !path.is_ident() { - path.segments.pop().unwrap(); - self.path_prefix = Some(path); + if let Some(path) = hir::Path::from_ast(path.clone()) { + if let Some(path_prefix) = path.qualifier() { + self.path_prefix = Some(path_prefix); return; } } From 3ba4b3c554ee94cf96d62c57f9bb80eaff19beed Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 15 Dec 2019 02:34:16 +0800 Subject: [PATCH 166/312] Use simpler logic on original_range --- .../ra_ide/src/display/navigation_target.rs | 19 +---- crates/ra_ide/src/expand.rs | 73 ++++++++++--------- 2 files changed, 41 insertions(+), 51 deletions(-) diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6a2bf72731..6a6b49afdf 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -7,14 +7,10 @@ use ra_syntax::{ ast::{self, DocCommentsOwner, NameOwner}, match_ast, AstNode, SmolStr, SyntaxKind::{self, BIND_PAT, TYPE_PARAM}, - SyntaxNode, TextRange, + TextRange, }; -use crate::{ - db::RootDatabase, - expand::{original_range_by_kind, OriginalRangeKind}, - FileRange, FileSymbol, -}; +use crate::{db::RootDatabase, expand::original_range, FileSymbol}; use super::short_label::ShortLabel; @@ -420,14 +416,3 @@ pub(crate) fn description_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> } } } - -fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { - if let Some(range) = original_range_by_kind(db, node, OriginalRangeKind::CallToken) { - return range; - } - if let Some(range) = original_range_by_kind(db, node, OriginalRangeKind::WholeCall) { - return range; - } - - FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } -} diff --git a/crates/ra_ide/src/expand.rs b/crates/ra_ide/src/expand.rs index 258478bc13..7a22bb0a4e 100644 --- a/crates/ra_ide/src/expand.rs +++ b/crates/ra_ide/src/expand.rs @@ -7,55 +7,60 @@ use ra_syntax::{ast, AstNode, SyntaxNode, SyntaxToken, TextRange}; use crate::{db::RootDatabase, FileRange}; -#[derive(Debug, PartialEq, Eq)] -pub(crate) enum OriginalRangeKind { - /// Return range if any token is matched - #[allow(dead_code)] - Any, - /// Return range if token is inside macro_call - CallToken, - /// Return whole macro call range if matched - WholeCall, +pub(crate) fn original_range(db: &RootDatabase, node: InFile<&SyntaxNode>) -> FileRange { + if let Some((range, Origin::Call)) = original_range_and_origin(db, node) { + return range; + } + + if let Some(expansion) = node.file_id.expansion_info(db) { + if let Some(call_node) = expansion.call_node() { + return FileRange { + file_id: call_node.file_id.original_file(db), + range: call_node.value.text_range(), + }; + } + } + + FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() } } -pub(crate) fn original_range_by_kind( +fn original_range_and_origin( db: &RootDatabase, node: InFile<&SyntaxNode>, - kind: OriginalRangeKind, -) -> Option { +) -> Option<(FileRange, Origin)> { let expansion = node.file_id.expansion_info(db)?; // the input node has only one token ? let single = node.value.first_token()? == node.value.last_token()?; // FIXME: We should handle recurside macro expansions - let range = match kind { - OriginalRangeKind::WholeCall => expansion.call_node()?.map(|node| node.text_range()), - _ => node.value.descendants().find_map(|it| { - let first = it.first_token()?; - let last = it.last_token()?; + let (range, origin) = node.value.descendants().find_map(|it| { + let first = it.first_token()?; + let last = it.last_token()?; - if !single && first == last { - return None; - } + if !single && first == last { + return None; + } - // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens - let (first, first_origin) = expansion.map_token_up(node.with_value(&first))?; - let (last, last_origin) = expansion.map_token_up(node.with_value(&last))?; + // Try to map first and last tokens of node, and, if success, return the union range of mapped tokens + let (first, first_origin) = expansion.map_token_up(node.with_value(&first))?; + let (last, last_origin) = expansion.map_token_up(node.with_value(&last))?; - if first.file_id != last.file_id - || first_origin != last_origin - || (kind == OriginalRangeKind::CallToken && first_origin != Origin::Call) - { - return None; - } + if first.file_id != last.file_id || first_origin != last_origin { + return None; + } - // FIXME: Add union method in TextRange - Some(first.with_value(union_range(first.value.text_range(), last.value.text_range()))) - })?, - }; + // FIXME: Add union method in TextRange + Some(( + first.with_value(union_range(first.value.text_range(), last.value.text_range())), + first_origin, + )) + })?; - return Some(FileRange { file_id: range.file_id.original_file(db), range: range.value }); + return Some(( + FileRange { file_id: range.file_id.original_file(db), range: range.value }, + origin, + )); fn union_range(a: TextRange, b: TextRange) -> TextRange { let start = a.start().min(b.start()); From feb5a4a8b8b0a30d71cf34c7927bd41cbae4e104 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 10:20:22 +0200 Subject: [PATCH 167/312] fixed rainbow-highlighting test --- crates/ra_ide/src/snapshots/rainbow_highlighting.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 9dfbc80475..ecf26c7084 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -10,8 +10,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } +.literal\.numeric { color: #6A8759; } .macro { color: #94BFF3; } .variable { color: #DCDCCC; } .variable\.mut { color: #DCDCCC; text-decoration: underline; } From 50ecb1e19bc555aa627224d41a5ca243e44296f4 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 12:33:14 +0200 Subject: [PATCH 168/312] introduce named constants for highlighting tag names. --- crates/ra_ide/src/syntax_highlighting.rs | 104 +++++++++++++++-------- 1 file changed, 67 insertions(+), 37 deletions(-) diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 235e09ffca..d0cefea0f9 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -16,6 +16,32 @@ use crate::{ FileId, }; +const HIGHLIGHT_TAG_FIELD: &'static str = "field"; +const HIGHLIGHT_TAG_FUNCTION: &'static str = "function"; +const HIGHLIGHT_TAG_MODULE: &'static str = "module"; +const HIGHLIGHT_TAG_TYPE: &'static str = "type"; +const HIGHLIGHT_TAG_CONSTANT: &'static str = "constant"; +const HIGHLIGHT_TAG_MACRO: &'static str = "macro"; +const HIGHLIGHT_TAG_VARIABLE: &'static str = "variable"; +const HIGHLIGHT_TAG_VARIABLE_MUT: &'static str = "variable.mut"; +const HIGHLIGHT_TAG_TEXT: &'static str = "text"; + +const HIGHLIGHT_TAG_TYPE_BUILTIN: &'static str = "type.builtin"; +const HIGHLIGHT_TAG_TYPE_SELF: &'static str = "type.self"; +const HIGHLIGHT_TAG_TYPE_PARAM: &'static str = "type.param"; +const HIGHLIGHT_TAG_TYPE_LIFETIME: &'static str = "type.lifetime"; + +const HIGHLIGHT_TAG_LITERAL_BYTE: &'static str = "literal.byte"; +const HIGHLIGHT_TAG_LITERAL_NUMERIC: &'static str = "literal.numeric"; +const HIGHLIGHT_TAG_LITERAL_CHAR: &'static str = "literal.char"; +const HIGHLIGHT_TAG_LITERAL_COMMENT: &'static str = "comment"; +const HIGHLIGHT_TAG_LITERAL_STRING: &'static str = "string"; +const HIGHLIGHT_TAG_LITERAL_ATTRIBUTE: &'static str = "attribute"; + +const HIGHLIGHT_TAG_KEYWORD_UNSAFE: &'static str = "keyword.unsafe"; +const HIGHLIGHT_TAG_KEYWORD_CONTROL: &'static str = "keyword.control"; +const HIGHLIGHT_TAG_KEYWORD: &'static str = "keyword"; + #[derive(Debug)] pub struct HighlightedRange { pub range: TextRange, @@ -71,9 +97,9 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec "comment", - STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => "string", - ATTR => "attribute", + COMMENT => HIGHLIGHT_TAG_LITERAL_COMMENT, + STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HIGHLIGHT_TAG_LITERAL_STRING, + ATTR => HIGHLIGHT_TAG_LITERAL_ATTRIBUTE, NAME_REF => { if node.ancestors().any(|it| it.kind() == ATTR) { continue; @@ -90,7 +116,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); @@ -107,21 +133,25 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec highlight_name(db, name_kind), - None => name.syntax().parent().map_or("function", |x| match x.kind() { - STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", - TYPE_PARAM => "type.param", - RECORD_FIELD_DEF => "field", - _ => "function", - }), + None => { + name.syntax().parent().map_or(HIGHLIGHT_TAG_FUNCTION, |x| match x.kind() { + STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => { + HIGHLIGHT_TAG_TYPE + } + TYPE_PARAM => HIGHLIGHT_TAG_TYPE_PARAM, + RECORD_FIELD_DEF => HIGHLIGHT_TAG_FIELD, + _ => HIGHLIGHT_TAG_FUNCTION, + }) + } } } - INT_NUMBER | FLOAT_NUMBER => "literal.numeric", - BYTE => "literal.byte", - CHAR => "literal.char", - LIFETIME => "type.lifetime", - T![unsafe] => "keyword.unsafe", - k if is_control_keyword(k) => "keyword.control", - k if k.is_keyword() => "keyword", + INT_NUMBER | FLOAT_NUMBER => HIGHLIGHT_TAG_LITERAL_NUMERIC, + BYTE => HIGHLIGHT_TAG_LITERAL_BYTE, + CHAR => HIGHLIGHT_TAG_LITERAL_CHAR, + LIFETIME => HIGHLIGHT_TAG_TYPE_LIFETIME, + T![unsafe] => HIGHLIGHT_TAG_KEYWORD_UNSAFE, + k if is_control_keyword(k) => HIGHLIGHT_TAG_KEYWORD_CONTROL, + k if k.is_keyword() => HIGHLIGHT_TAG_KEYWORD, _ => { if let Some(macro_call) = node.as_node().cloned().and_then(ast::MacroCall::cast) { if let Some(path) = macro_call.path() { @@ -138,7 +168,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec &'static str { match name_kind { - Macro(_) => "macro", - Field(_) => "field", - AssocItem(hir::AssocItem::Function(_)) => "function", - AssocItem(hir::AssocItem::Const(_)) => "constant", - AssocItem(hir::AssocItem::TypeAlias(_)) => "type", - Def(hir::ModuleDef::Module(_)) => "module", - Def(hir::ModuleDef::Function(_)) => "function", - Def(hir::ModuleDef::Adt(_)) => "type", - Def(hir::ModuleDef::EnumVariant(_)) => "constant", - Def(hir::ModuleDef::Const(_)) => "constant", - Def(hir::ModuleDef::Static(_)) => "constant", - Def(hir::ModuleDef::Trait(_)) => "type", - Def(hir::ModuleDef::TypeAlias(_)) => "type", - Def(hir::ModuleDef::BuiltinType(_)) => "type.builtin", - SelfType(_) => "type.self", - TypeParam(_) => "type.param", + Macro(_) => HIGHLIGHT_TAG_MACRO, + Field(_) => HIGHLIGHT_TAG_FIELD, + AssocItem(hir::AssocItem::Function(_)) => HIGHLIGHT_TAG_FUNCTION, + AssocItem(hir::AssocItem::Const(_)) => HIGHLIGHT_TAG_CONSTANT, + AssocItem(hir::AssocItem::TypeAlias(_)) => HIGHLIGHT_TAG_TYPE, + Def(hir::ModuleDef::Module(_)) => HIGHLIGHT_TAG_MODULE, + Def(hir::ModuleDef::Function(_)) => HIGHLIGHT_TAG_FUNCTION, + Def(hir::ModuleDef::Adt(_)) => HIGHLIGHT_TAG_TYPE, + Def(hir::ModuleDef::EnumVariant(_)) => HIGHLIGHT_TAG_CONSTANT, + Def(hir::ModuleDef::Const(_)) => HIGHLIGHT_TAG_CONSTANT, + Def(hir::ModuleDef::Static(_)) => HIGHLIGHT_TAG_CONSTANT, + Def(hir::ModuleDef::Trait(_)) => HIGHLIGHT_TAG_TYPE, + Def(hir::ModuleDef::TypeAlias(_)) => HIGHLIGHT_TAG_TYPE, + Def(hir::ModuleDef::BuiltinType(_)) => HIGHLIGHT_TAG_TYPE_BUILTIN, + SelfType(_) => HIGHLIGHT_TAG_TYPE_SELF, + TypeParam(_) => HIGHLIGHT_TAG_TYPE_PARAM, Local(local) => { if local.is_mut(db) { - "variable.mut" + HIGHLIGHT_TAG_VARIABLE_MUT } else if local.ty(db).is_mutable_reference() { - "variable.mut" + HIGHLIGHT_TAG_VARIABLE_MUT } else { - "variable" + HIGHLIGHT_TAG_VARIABLE } } } From 9a6d496497df35c0dbd8fa40574d47d0463997dd Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 13:18:37 +0200 Subject: [PATCH 169/312] use a module instead of prefixed consts. --- crates/ra_ide/src/syntax_highlighting.rs | 124 +++++++++++------------ 1 file changed, 61 insertions(+), 63 deletions(-) diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index d0cefea0f9..eb3dd17793 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -16,31 +16,33 @@ use crate::{ FileId, }; -const HIGHLIGHT_TAG_FIELD: &'static str = "field"; -const HIGHLIGHT_TAG_FUNCTION: &'static str = "function"; -const HIGHLIGHT_TAG_MODULE: &'static str = "module"; -const HIGHLIGHT_TAG_TYPE: &'static str = "type"; -const HIGHLIGHT_TAG_CONSTANT: &'static str = "constant"; -const HIGHLIGHT_TAG_MACRO: &'static str = "macro"; -const HIGHLIGHT_TAG_VARIABLE: &'static str = "variable"; -const HIGHLIGHT_TAG_VARIABLE_MUT: &'static str = "variable.mut"; -const HIGHLIGHT_TAG_TEXT: &'static str = "text"; +pub mod tags { + pub(crate) const FIELD: &'static str = "field"; + pub(crate) const FUNCTION: &'static str = "function"; + pub(crate) const MODULE: &'static str = "module"; + pub(crate) const TYPE: &'static str = "type"; + pub(crate) const CONSTANT: &'static str = "constant"; + pub(crate) const MACRO: &'static str = "macro"; + pub(crate) const VARIABLE: &'static str = "variable"; + pub(crate) const VARIABLE_MUT: &'static str = "variable.mut"; + pub(crate) const TEXT: &'static str = "text"; -const HIGHLIGHT_TAG_TYPE_BUILTIN: &'static str = "type.builtin"; -const HIGHLIGHT_TAG_TYPE_SELF: &'static str = "type.self"; -const HIGHLIGHT_TAG_TYPE_PARAM: &'static str = "type.param"; -const HIGHLIGHT_TAG_TYPE_LIFETIME: &'static str = "type.lifetime"; + pub(crate) const TYPE_BUILTIN: &'static str = "type.builtin"; + pub(crate) const TYPE_SELF: &'static str = "type.self"; + pub(crate) const TYPE_PARAM: &'static str = "type.param"; + pub(crate) const TYPE_LIFETIME: &'static str = "type.lifetime"; -const HIGHLIGHT_TAG_LITERAL_BYTE: &'static str = "literal.byte"; -const HIGHLIGHT_TAG_LITERAL_NUMERIC: &'static str = "literal.numeric"; -const HIGHLIGHT_TAG_LITERAL_CHAR: &'static str = "literal.char"; -const HIGHLIGHT_TAG_LITERAL_COMMENT: &'static str = "comment"; -const HIGHLIGHT_TAG_LITERAL_STRING: &'static str = "string"; -const HIGHLIGHT_TAG_LITERAL_ATTRIBUTE: &'static str = "attribute"; + pub(crate) const LITERAL_BYTE: &'static str = "literal.byte"; + pub(crate) const LITERAL_NUMERIC: &'static str = "literal.numeric"; + pub(crate) const LITERAL_CHAR: &'static str = "literal.char"; + pub(crate) const LITERAL_COMMENT: &'static str = "comment"; + pub(crate) const LITERAL_STRING: &'static str = "string"; + pub(crate) const LITERAL_ATTRIBUTE: &'static str = "attribute"; -const HIGHLIGHT_TAG_KEYWORD_UNSAFE: &'static str = "keyword.unsafe"; -const HIGHLIGHT_TAG_KEYWORD_CONTROL: &'static str = "keyword.control"; -const HIGHLIGHT_TAG_KEYWORD: &'static str = "keyword"; + pub(crate) const KEYWORD_UNSAFE: &'static str = "keyword.unsafe"; + pub(crate) const KEYWORD_CONTROL: &'static str = "keyword.control"; + pub(crate) const KEYWORD: &'static str = "keyword"; +} #[derive(Debug)] pub struct HighlightedRange { @@ -97,9 +99,9 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec HIGHLIGHT_TAG_LITERAL_COMMENT, - STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => HIGHLIGHT_TAG_LITERAL_STRING, - ATTR => HIGHLIGHT_TAG_LITERAL_ATTRIBUTE, + COMMENT => tags::LITERAL_COMMENT, + STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, + ATTR => tags::LITERAL_ATTRIBUTE, NAME_REF => { if node.ancestors().any(|it| it.kind() == ATTR) { continue; @@ -116,7 +118,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec { let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); @@ -133,25 +135,21 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec highlight_name(db, name_kind), - None => { - name.syntax().parent().map_or(HIGHLIGHT_TAG_FUNCTION, |x| match x.kind() { - STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => { - HIGHLIGHT_TAG_TYPE - } - TYPE_PARAM => HIGHLIGHT_TAG_TYPE_PARAM, - RECORD_FIELD_DEF => HIGHLIGHT_TAG_FIELD, - _ => HIGHLIGHT_TAG_FUNCTION, - }) - } + None => name.syntax().parent().map_or(tags::FUNCTION, |x| match x.kind() { + STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => tags::TYPE, + TYPE_PARAM => tags::TYPE_PARAM, + RECORD_FIELD_DEF => tags::FIELD, + _ => tags::FUNCTION, + }), } } - INT_NUMBER | FLOAT_NUMBER => HIGHLIGHT_TAG_LITERAL_NUMERIC, - BYTE => HIGHLIGHT_TAG_LITERAL_BYTE, - CHAR => HIGHLIGHT_TAG_LITERAL_CHAR, - LIFETIME => HIGHLIGHT_TAG_TYPE_LIFETIME, - T![unsafe] => HIGHLIGHT_TAG_KEYWORD_UNSAFE, - k if is_control_keyword(k) => HIGHLIGHT_TAG_KEYWORD_CONTROL, - k if k.is_keyword() => HIGHLIGHT_TAG_KEYWORD, + INT_NUMBER | FLOAT_NUMBER => tags::LITERAL_NUMERIC, + BYTE => tags::LITERAL_BYTE, + CHAR => tags::LITERAL_CHAR, + LIFETIME => tags::TYPE_LIFETIME, + T![unsafe] => tags::KEYWORD_UNSAFE, + k if is_control_keyword(k) => tags::KEYWORD_CONTROL, + k if k.is_keyword() => tags::KEYWORD, _ => { if let Some(macro_call) = node.as_node().cloned().and_then(ast::MacroCall::cast) { if let Some(path) = macro_call.path() { @@ -168,7 +166,7 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec &'static str { match name_kind { - Macro(_) => HIGHLIGHT_TAG_MACRO, - Field(_) => HIGHLIGHT_TAG_FIELD, - AssocItem(hir::AssocItem::Function(_)) => HIGHLIGHT_TAG_FUNCTION, - AssocItem(hir::AssocItem::Const(_)) => HIGHLIGHT_TAG_CONSTANT, - AssocItem(hir::AssocItem::TypeAlias(_)) => HIGHLIGHT_TAG_TYPE, - Def(hir::ModuleDef::Module(_)) => HIGHLIGHT_TAG_MODULE, - Def(hir::ModuleDef::Function(_)) => HIGHLIGHT_TAG_FUNCTION, - Def(hir::ModuleDef::Adt(_)) => HIGHLIGHT_TAG_TYPE, - Def(hir::ModuleDef::EnumVariant(_)) => HIGHLIGHT_TAG_CONSTANT, - Def(hir::ModuleDef::Const(_)) => HIGHLIGHT_TAG_CONSTANT, - Def(hir::ModuleDef::Static(_)) => HIGHLIGHT_TAG_CONSTANT, - Def(hir::ModuleDef::Trait(_)) => HIGHLIGHT_TAG_TYPE, - Def(hir::ModuleDef::TypeAlias(_)) => HIGHLIGHT_TAG_TYPE, - Def(hir::ModuleDef::BuiltinType(_)) => HIGHLIGHT_TAG_TYPE_BUILTIN, - SelfType(_) => HIGHLIGHT_TAG_TYPE_SELF, - TypeParam(_) => HIGHLIGHT_TAG_TYPE_PARAM, + Macro(_) => tags::MACRO, + Field(_) => tags::FIELD, + AssocItem(hir::AssocItem::Function(_)) => tags::FUNCTION, + AssocItem(hir::AssocItem::Const(_)) => tags::CONSTANT, + AssocItem(hir::AssocItem::TypeAlias(_)) => tags::TYPE, + Def(hir::ModuleDef::Module(_)) => tags::MODULE, + Def(hir::ModuleDef::Function(_)) => tags::FUNCTION, + Def(hir::ModuleDef::Adt(_)) => tags::TYPE, + Def(hir::ModuleDef::EnumVariant(_)) => tags::CONSTANT, + Def(hir::ModuleDef::Const(_)) => tags::CONSTANT, + Def(hir::ModuleDef::Static(_)) => tags::CONSTANT, + Def(hir::ModuleDef::Trait(_)) => tags::TYPE, + Def(hir::ModuleDef::TypeAlias(_)) => tags::TYPE, + Def(hir::ModuleDef::BuiltinType(_)) => tags::TYPE_BUILTIN, + SelfType(_) => tags::TYPE_SELF, + TypeParam(_) => tags::TYPE_PARAM, Local(local) => { if local.is_mut(db) { - HIGHLIGHT_TAG_VARIABLE_MUT + tags::VARIABLE_MUT } else if local.ty(db).is_mutable_reference() { - HIGHLIGHT_TAG_VARIABLE_MUT + tags::VARIABLE_MUT } else { - HIGHLIGHT_TAG_VARIABLE + tags::VARIABLE } } } From 1d9b585c62dc92889380c9ae130d15ce7f9b08d4 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 15:07:33 +0200 Subject: [PATCH 170/312] make drive comparison case-insensitive. --- editors/code/src/notifications/publish_decorations.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 00ffb7776b..120eabbc6f 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -10,10 +10,19 @@ export interface PublishDecorationsParams { export function handle(params: PublishDecorationsParams) { const targetEditor = vscode.window.visibleTextEditors.find( - editor => editor.document.uri.toString() === params.uri, + editor => { + const unescapedUri = unescape(editor.document.uri.toString()); + // Unescaped URI should be something like: + // file:///c:/Workspace/ra-test/src/main.rs + // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. + const uriWithLowercasedDrive = params.uri.substr(0, 8) + params.uri[8].toLowerCase() + params.uri.substr(9); + return unescapedUri === uriWithLowercasedDrive + } ); + if (!Server.config.highlightingOn || !targetEditor) { return; } + Server.highlighter.setHighlights(targetEditor, params.decorations); } From 324cbe839f3110bd4d51726d5a7afe29808ade02 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 16:51:57 +0200 Subject: [PATCH 171/312] Lowercase drive letters on windows before sending to extension. --- crates/ra_lsp_server/src/world.rs | 34 +++++++++++++++++++ .../src/notifications/publish_decorations.ts | 3 +- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 927449b45d..be3a5bfb8f 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -22,6 +22,7 @@ use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; +use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -235,6 +236,9 @@ impl WorldSnapshot { let path = self.vfs.read().file2path(VfsFile(id.0)); let url = Url::from_file_path(&path) .map_err(|_| format!("can't convert path to url: {}", path.display()))?; + + #[cfg(target_os = "windows")] + let url = lowercase_drive_letter(&url); Ok(url) } @@ -279,3 +283,33 @@ impl WorldSnapshot { self.analysis.feature_flags() } } + +#[cfg(target_os = "windows")] +fn lowercase_drive_letter(url: &Url) -> Url { + let s = url.to_string(); + let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); + + if drive_partition.len() == 1 { + return url.clone(); + } + + let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; + let url = Url::from_str(&joined).expect("This came from a valid `Url`"); + url +} + +#[test] +fn test_lowercase_drive_letter_with_drive() { + let url = Url::from_file_path("C:\\Test").unwrap(); + let url = lowercase_drive_letter(&url); + + assert_eq!(url.to_string(), "file:///c:/Test"); +} + +#[test] +fn test_drive_without_colon_passthrough() { + let url = Url::from_file_path(r#"\\localhost\C$\my_dir"#).expect("Should work"); + let url = lowercase_drive_letter(&url); + + assert_eq!(url.to_string(), "file:///C$/my_dir"); +} diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 120eabbc6f..4441e2b28d 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -15,8 +15,7 @@ export function handle(params: PublishDecorationsParams) { // Unescaped URI should be something like: // file:///c:/Workspace/ra-test/src/main.rs // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. - const uriWithLowercasedDrive = params.uri.substr(0, 8) + params.uri[8].toLowerCase() + params.uri.substr(9); - return unescapedUri === uriWithLowercasedDrive + return unescapedUri === params.uri } ); From 498a7912e923ad8ce349f6874568373f430e9602 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 16:55:39 +0200 Subject: [PATCH 172/312] fixed comment --- editors/code/src/notifications/publish_decorations.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 4441e2b28d..2ccd2d5850 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -12,9 +12,8 @@ export function handle(params: PublishDecorationsParams) { const targetEditor = vscode.window.visibleTextEditors.find( editor => { const unescapedUri = unescape(editor.document.uri.toString()); - // Unescaped URI should be something like: + // Unescaped URI looks like: // file:///c:/Workspace/ra-test/src/main.rs - // RA server might send it with the drive letter uppercased, so we force only the drive letter to lowercase. return unescapedUri === params.uri } ); From ebf302d2610527c35b8fb794a03cc1c280c8a9d3 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:03:39 +0200 Subject: [PATCH 173/312] move import inside cfg block --- crates/ra_lsp_server/src/world.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index be3a5bfb8f..f139a57280 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -22,7 +22,6 @@ use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; -use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -286,6 +285,8 @@ impl WorldSnapshot { #[cfg(target_os = "windows")] fn lowercase_drive_letter(url: &Url) -> Url { + use std::str::FromStr; + let s = url.to_string(); let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); From 75353753cdcb993c277ce1d8bb366c708eabe2c6 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:10:39 +0200 Subject: [PATCH 174/312] `npm run fix` --- .../code/src/notifications/publish_decorations.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/editors/code/src/notifications/publish_decorations.ts b/editors/code/src/notifications/publish_decorations.ts index 2ccd2d5850..f23e286ad5 100644 --- a/editors/code/src/notifications/publish_decorations.ts +++ b/editors/code/src/notifications/publish_decorations.ts @@ -9,14 +9,12 @@ export interface PublishDecorationsParams { } export function handle(params: PublishDecorationsParams) { - const targetEditor = vscode.window.visibleTextEditors.find( - editor => { - const unescapedUri = unescape(editor.document.uri.toString()); - // Unescaped URI looks like: - // file:///c:/Workspace/ra-test/src/main.rs - return unescapedUri === params.uri - } - ); + const targetEditor = vscode.window.visibleTextEditors.find(editor => { + const unescapedUri = unescape(editor.document.uri.toString()); + // Unescaped URI looks like: + // file:///c:/Workspace/ra-test/src/main.rs + return unescapedUri === params.uri; + }); if (!Server.config.highlightingOn || !targetEditor) { return; From 2e2fae32dff6cab508768953bbd34b88b5bea166 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:46:00 +0200 Subject: [PATCH 175/312] improved path checking to consider only paths that may contain a windows drive. --- crates/ra_lsp_server/src/world.rs | 64 +++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index f139a57280..63a8200123 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -17,11 +17,13 @@ use ra_project_model::{get_rustc_cfg_options, ProjectWorkspace}; use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch}; use ra_vfs_glob::{Glob, RustPackageFilterBuilder}; use relative_path::RelativePathBuf; +use std::path::{Component, Prefix}; use crate::{ main_loop::pending_requests::{CompletedRequest, LatestRequests}, LspError, Result, }; +use std::str::FromStr; #[derive(Debug, Clone)] pub struct Options { @@ -233,11 +235,8 @@ impl WorldSnapshot { pub fn file_id_to_uri(&self, id: FileId) -> Result { let path = self.vfs.read().file2path(VfsFile(id.0)); - let url = Url::from_file_path(&path) - .map_err(|_| format!("can't convert path to url: {}", path.display()))?; + let url = url_from_path_with_drive_lowercasing(path)?; - #[cfg(target_os = "windows")] - let url = lowercase_drive_letter(&url); Ok(url) } @@ -283,34 +282,59 @@ impl WorldSnapshot { } } -#[cfg(target_os = "windows")] -fn lowercase_drive_letter(url: &Url) -> Url { - use std::str::FromStr; +/// Returns a `Url` object from a given path, will lowercase drive letters if present. +/// This will only happen when processing windows paths. +/// +/// When processing non-windows path, this is essentially the same as `Url::from_file_path`. +fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { + let component_has_windows_drive = path + .as_ref() + .components() + .find(|comp| { + if let Component::Prefix(c) = comp { + match c.kind() { + Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true, + _ => return false, + } + } + false + }) + .is_some(); - let s = url.to_string(); - let drive_partition: Vec<&str> = s.rsplitn(2, ':').collect::>(); + // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters. + if component_has_windows_drive { + let url_original = Url::from_file_path(&path) + .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?; - if drive_partition.len() == 1 { - return url.clone(); + let drive_partition: Vec<&str> = + url_original.as_str().rsplitn(2, ':').collect::>(); + + // There is a drive partition, but we never found a colon. + // This should not happen, but in this case we just pass it through. + if drive_partition.len() == 1 { + return Ok(url_original); + } + + let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; + let url = Url::from_str(&joined).expect("This came from a valid `Url`"); + + Ok(url) + } else { + Ok(Url::from_file_path(&path) + .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?) } - - let joined = drive_partition[1].to_ascii_lowercase() + ":" + drive_partition[0]; - let url = Url::from_str(&joined).expect("This came from a valid `Url`"); - url } #[test] fn test_lowercase_drive_letter_with_drive() { - let url = Url::from_file_path("C:\\Test").unwrap(); - let url = lowercase_drive_letter(&url); + let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); assert_eq!(url.to_string(), "file:///c:/Test"); } #[test] fn test_drive_without_colon_passthrough() { - let url = Url::from_file_path(r#"\\localhost\C$\my_dir"#).expect("Should work"); - let url = lowercase_drive_letter(&url); + let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); - assert_eq!(url.to_string(), "file:///C$/my_dir"); + assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); } From 40116af598ef51cab8a1059dceda7508f994387c Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 17:54:24 +0200 Subject: [PATCH 176/312] cfg gated tests that only work on windows. --- crates/ra_lsp_server/src/world.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 63a8200123..8b48726ee2 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -325,16 +325,22 @@ fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { } } -#[test] -fn test_lowercase_drive_letter_with_drive() { - let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); +// `Url` is not able to parse windows paths on unix machines. +#[cfg(target_os = "windows")] +#[cfg(test)] +mod path_conversion_windows_tests { + use super::url_from_path_with_drive_lowercasing; + #[test] + fn test_lowercase_drive_letter_with_drive() { + let url = url_from_path_with_drive_lowercasing("C:\\Test").unwrap(); - assert_eq!(url.to_string(), "file:///c:/Test"); -} - -#[test] -fn test_drive_without_colon_passthrough() { - let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); - - assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); + assert_eq!(url.to_string(), "file:///c:/Test"); + } + + #[test] + fn test_drive_without_colon_passthrough() { + let url = url_from_path_with_drive_lowercasing(r#"\\localhost\C$\my_dir"#).unwrap(); + + assert_eq!(url.to_string(), "file://localhost/C$/my_dir"); + } } From eed57dcded5eb661d05c23a642ca03f9b87391fa Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 15 Dec 2019 17:12:52 +0100 Subject: [PATCH 177/312] Add a rudimentary json regex to get at information like `endLine` --- editors/code/package.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/editors/code/package.json b/editors/code/package.json index 43db61a8bc..ebb1b4a98b 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -313,6 +313,18 @@ "column": 3 } ] + }, + { + "name": "rustc-json", + "patterns": [{ + "regexp": "^.*\"message\":{\"message\":\"([^\"]*).*?\"file_name\":\"([^\"]+).*?\"line_start\":(\\d+).*?\"line_end\":(\\d+).*?\"column_start\":(\\d+).*?\"column_end\":(\\d+).*}$", + "message": 1, + "file": 2, + "line": 3, + "endLine": 4, + "column": 5, + "endColumn": 6 + }] } ], "problemMatchers": [ @@ -324,6 +336,14 @@ ], "pattern": "$rustc" }, + { + "name": "rustc-json", + "fileLocation": [ + "relative", + "${workspaceRoot}" + ], + "pattern": "$rustc-json" + }, { "name": "rustc-watch", "fileLocation": [ From 6fba427bf35bebdc7aa08a241ecbe83a2f725127 Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Sun, 15 Dec 2019 18:15:24 +0200 Subject: [PATCH 178/312] remove unnecessary turbofish. --- crates/ra_lsp_server/src/world.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 8b48726ee2..16cc11e8ce 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -306,8 +306,7 @@ fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { let url_original = Url::from_file_path(&path) .map_err(|_| format!("can't convert path to url: {}", path.as_ref().display()))?; - let drive_partition: Vec<&str> = - url_original.as_str().rsplitn(2, ':').collect::>(); + let drive_partition: Vec<&str> = url_original.as_str().rsplitn(2, ':').collect(); // There is a drive partition, but we never found a colon. // This should not happen, but in this case we just pass it through. From 5166f6e5f20ce807a8f41d5039d2135a7eb13d29 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Sun, 15 Dec 2019 17:19:41 +0100 Subject: [PATCH 179/312] Properly format json --- editors/code/package.json | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index ebb1b4a98b..9290599c7a 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -316,15 +316,17 @@ }, { "name": "rustc-json", - "patterns": [{ - "regexp": "^.*\"message\":{\"message\":\"([^\"]*).*?\"file_name\":\"([^\"]+).*?\"line_start\":(\\d+).*?\"line_end\":(\\d+).*?\"column_start\":(\\d+).*?\"column_end\":(\\d+).*}$", - "message": 1, - "file": 2, - "line": 3, - "endLine": 4, - "column": 5, - "endColumn": 6 - }] + "patterns": [ + { + "regexp": "^.*\"message\":{\"message\":\"([^\"]*).*?\"file_name\":\"([^\"]+).*?\"line_start\":(\\d+).*?\"line_end\":(\\d+).*?\"column_start\":(\\d+).*?\"column_end\":(\\d+).*}$", + "message": 1, + "file": 2, + "line": 3, + "endLine": 4, + "column": 5, + "endColumn": 6 + } + ] } ], "problemMatchers": [ From ac961b261458bfeb23f7d4e896d5f957b0854a3a Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 6 Dec 2019 12:45:00 +0100 Subject: [PATCH 180/312] Add test for unifying impl Trait --- crates/ra_hir_ty/src/tests/traits.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 6139adb72e..a926d01e53 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1,4 +1,4 @@ -use super::{infer, type_at, type_at_pos}; +use super::{infer, infer_with_mismatches, type_at, type_at_pos}; use crate::test_db::TestDB; use insta::assert_snapshot; use ra_db::fixture::WithFixture; @@ -1486,3 +1486,29 @@ fn test() where T: Trait, U: Trait { // this is a legitimate cycle assert_eq!(t, "{unknown}"); } + +#[test] +fn unify_impl_trait() { + assert_snapshot!( + infer_with_mismatches(r#" +trait Trait {} + +fn foo(x: impl Trait) { loop {} } +fn bar(x: impl Trait) -> T { loop {} } + +struct S(T); +impl Trait for S {} + +fn default() -> T { loop {} } + +fn test() -> impl Trait { + let s1 = S(default()); + foo(s1); + let x: i32 = bar(S(default())); + S(default()) +} +"#, true), + @r###" + "### + ); +} From 6e1c2d0df89a390be33c81b6e03a5ad352763593 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 15 Dec 2019 18:56:38 +0100 Subject: [PATCH 181/312] Handle impl Trait more correctly When calling a function, argument-position impl Trait is transparent; same for return-position impl Trait when inside the function. So in these cases, we need to represent that type not by `Ty::Opaque`, but by a type variable that can be unified with whatever flows into there. --- crates/ra_hir_ty/src/infer.rs | 25 +++++++++++++++++++++- crates/ra_hir_ty/src/infer/expr.rs | 1 + crates/ra_hir_ty/src/tests/traits.rs | 31 ++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index af42854cce..1aa1330a6c 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -274,6 +274,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.normalize_associated_types_in(ty) } + /// Replaces `impl Trait` in `ty` by type variables and obligations for + /// those variables. This is done for function arguments when calling a + /// function, and for return types when inside the function body, i.e. in + /// the cases where the `impl Trait` is 'transparent'. In other cases, `impl + /// Trait` is represented by `Ty::Opaque`. + fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty { + ty.fold(&mut |ty| match ty { + Ty::Opaque(preds) => { + let var = self.table.new_type_var(); + let var_subst = Substs::builder(1).push(var.clone()).build(); + self.obligations.extend( + preds + .iter() + .map(|pred| pred.clone().subst_bound_vars(&var_subst)) + .filter_map(Obligation::from_predicate), + ); + var + } + _ => ty, + }) + } + /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { match ty { @@ -414,7 +436,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.infer_pat(*pat, &ty, BindingMode::default()); } - self.return_ty = self.make_ty(&data.ret_type); + let return_ty = self.make_ty(&data.ret_type); + self.return_ty = self.insert_vars_for_impl_trait(return_ty); } fn infer_body(&mut self) { diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 2e3cdd53a0..924ad3e813 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -613,6 +613,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { continue; } + let param_ty = self.insert_vars_for_impl_trait(param_ty); let param_ty = self.normalize_associated_types_in(param_ty); self.infer_expr_coerce(arg, &Expectation::has_type(param_ty.clone())); } diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index a926d01e53..d8673c90d3 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1509,6 +1509,37 @@ fn test() -> impl Trait { } "#, true), @r###" + [27; 28) 'x': impl Trait + [47; 58) '{ loop {} }': () + [49; 56) 'loop {}': ! + [54; 56) '{}': () + [69; 70) 'x': impl Trait + [92; 103) '{ loop {} }': T + [94; 101) 'loop {}': ! + [99; 101) '{}': () + [172; 183) '{ loop {} }': T + [174; 181) 'loop {}': ! + [179; 181) '{}': () + [214; 310) '{ ...t()) }': S + [224; 226) 's1': S + [229; 230) 'S': S(T) -> S + [229; 241) 'S(default())': S + [231; 238) 'default': fn default() -> T + [231; 240) 'default()': u32 + [247; 250) 'foo': fn foo(impl Trait) -> () + [247; 254) 'foo(s1)': () + [251; 253) 's1': S + [264; 265) 'x': i32 + [273; 276) 'bar': fn bar(impl Trait) -> T + [273; 290) 'bar(S(...lt()))': i32 + [277; 278) 'S': S(T) -> S + [277; 289) 'S(default())': S + [279; 286) 'default': fn default() -> T + [279; 288) 'default()': i32 + [296; 297) 'S': S(T) -> S + [296; 308) 'S(default())': S + [298; 305) 'default': fn default() -> T + [298; 307) 'default()': i32 "### ); } From a85cd6455a66ca75ba9991d91acf36f55cb74e8c Mon Sep 17 00:00:00 2001 From: Vadzim Dambrouski Date: Sun, 15 Dec 2019 23:02:13 +0530 Subject: [PATCH 182/312] Add option to disable all-targets. Can be useful in embedded. --- editors/code/package.json | 5 +++++ editors/code/src/commands/cargo_watch.ts | 5 ++++- editors/code/src/config.ts | 9 +++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 9290599c7a..df8e9eecb9 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -237,6 +237,11 @@ "description": "A list of patterns for cargo-watch to ignore (will be passed as `--ignore`)", "default": [] }, + "rust-analyzer.cargo-watch.allTargets": { + "type": "boolean", + "description": "Check all targets and tests (will be passed as `--all-targets`)", + "default": true + }, "rust-analyzer.trace.server": { "type": "string", "scope": "window", diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 512362eb18..45f1dd49f4 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts @@ -83,7 +83,10 @@ export class CargoWatchProvider implements vscode.Disposable { let args = Server.config.cargoWatchOptions.command + - ' --all-targets --message-format json'; + ' --message-format json'; + if (Server.config.cargoWatchOptions.allTargets) { + args += ' --all-targets'; + } if (Server.config.cargoWatchOptions.command.length > 0) { // Excape the double quote string: args += ' ' + Server.config.cargoWatchOptions.arguments; diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index defdfeb9c4..a6e0f6454f 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -13,6 +13,7 @@ export interface CargoWatchOptions { command: string; trace: CargoWatchTraceOptions; ignore: string[]; + allTargets: boolean; } export interface CargoFeatures { @@ -40,6 +41,7 @@ export class Config { arguments: '', command: '', ignore: [], + allTargets: true, }; public cargoFeatures: CargoFeatures = { noDefaultFeatures: false, @@ -132,6 +134,13 @@ export class Config { ); } + if (config.has('cargo-watch.allTargets')) { + this.cargoWatchOptions.allTargets = config.get( + 'cargo-watch.allTargets', + true, + ); + } + if (config.has('lruCapacity')) { this.lruCapacity = config.get('lruCapacity') as number; } From 91853590a9ee78406e892ca92305edef3a5b9213 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sun, 15 Dec 2019 21:06:08 +0100 Subject: [PATCH 183/312] Add test mark --- crates/ra_hir_ty/src/infer.rs | 2 ++ crates/ra_hir_ty/src/marks.rs | 1 + crates/ra_hir_ty/src/tests/traits.rs | 8 ++++++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 1aa1330a6c..98ba05fc27 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -32,6 +32,7 @@ use hir_def::{ use hir_expand::{diagnostics::DiagnosticSink, name::name}; use ra_arena::map::ArenaMap; use ra_prof::profile; +use test_utils::tested_by; use super::{ primitive::{FloatTy, IntTy}, @@ -282,6 +283,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { fn insert_vars_for_impl_trait(&mut self, ty: Ty) -> Ty { ty.fold(&mut |ty| match ty { Ty::Opaque(preds) => { + tested_by!(insert_vars_for_impl_trait); let var = self.table.new_type_var(); let var_subst = Substs::builder(1).push(var.clone()).build(); self.obligations.extend( diff --git a/crates/ra_hir_ty/src/marks.rs b/crates/ra_hir_ty/src/marks.rs index 0f754eb9c7..fe74acf119 100644 --- a/crates/ra_hir_ty/src/marks.rs +++ b/crates/ra_hir_ty/src/marks.rs @@ -6,4 +6,5 @@ test_utils::marks!( type_var_resolves_to_int_var match_ergonomics_ref coerce_merge_fail_fallback + insert_vars_for_impl_trait ); diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index d8673c90d3..802937cb02 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -1,7 +1,10 @@ +use insta::assert_snapshot; + +use ra_db::fixture::WithFixture; +use test_utils::covers; + use super::{infer, infer_with_mismatches, type_at, type_at_pos}; use crate::test_db::TestDB; -use insta::assert_snapshot; -use ra_db::fixture::WithFixture; #[test] fn infer_await() { @@ -1489,6 +1492,7 @@ fn test() where T: Trait, U: Trait { #[test] fn unify_impl_trait() { + covers!(insert_vars_for_impl_trait); assert_snapshot!( infer_with_mismatches(r#" trait Trait {} From 22ae4cb90699d64b8bb455635bad7abb406bb39e Mon Sep 17 00:00:00 2001 From: Vadzim Dambrouski Date: Mon, 16 Dec 2019 09:01:38 +0530 Subject: [PATCH 184/312] Fix formatting --- editors/code/src/commands/cargo_watch.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 45f1dd49f4..748be535cc 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts @@ -82,8 +82,7 @@ export class CargoWatchProvider implements vscode.Disposable { } let args = - Server.config.cargoWatchOptions.command + - ' --message-format json'; + Server.config.cargoWatchOptions.command + ' --message-format json'; if (Server.config.cargoWatchOptions.allTargets) { args += ' --all-targets'; } From 624abc1db3a291c76b7c6dbcea39e85ae5cb8f6b Mon Sep 17 00:00:00 2001 From: Omer Ben-Amram Date: Mon, 16 Dec 2019 17:32:46 +0200 Subject: [PATCH 185/312] Fixed a typo thanks @lnicola --- editors/code/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editors/code/package.json b/editors/code/package.json index 9290599c7a..d6d47e3a1b 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -524,7 +524,7 @@ }, { "id": "ralsp.type.lifetime", - "description": "Color for `Self` param type", + "description": "Color for lifetimes parameters", "defaults": { "dark": "#4EC9B0", "light": "#267F99", From dd2f2dc376bb09d5fdf05f58693eefc1f5e794a4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 16 Dec 2019 18:41:03 +0100 Subject: [PATCH 186/312] link website --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 979e4ef88a..deaa147ba9 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0 ## Quick Links * API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide/ - +* Website: https://rust-analyzer.github.io/ ## License From 3e2f4e42937cb6e6855df94e424b55ed102af44d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 12:11:01 +0100 Subject: [PATCH 187/312] Improve recovery for incomplete lambdas --- .../ra_parser/src/grammar/expressions/atom.rs | 7 +- .../parser/err/0039_lambda_recovery.rs | 5 ++ .../parser/err/0039_lambda_recovery.txt | 83 +++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs create mode 100644 crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index f06191963f..09f0a2d98a 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -248,7 +248,12 @@ fn lambda_expr(p: &mut Parser) -> CompletedMarker { p.error("expected `{`"); } } - expr(p); + + if p.at_ts(EXPR_FIRST) { + expr(p); + } else { + p.error("expected expression"); + } m.complete(p, LAMBDA_EXPR) } diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs new file mode 100644 index 0000000000..a2f74bd879 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.rs @@ -0,0 +1,5 @@ +fn foo() -> i32 { + [1, 2, 3].iter() + .map(|it|) + .max::(); +} diff --git a/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt new file mode 100644 index 0000000000..d1544634ce --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0039_lambda_recovery.txt @@ -0,0 +1,83 @@ +SOURCE_FILE@[0; 83) + FN_DEF@[0; 82) + FN_KW@[0; 2) "fn" + WHITESPACE@[2; 3) " " + NAME@[3; 6) + IDENT@[3; 6) "foo" + PARAM_LIST@[6; 8) + L_PAREN@[6; 7) "(" + R_PAREN@[7; 8) ")" + WHITESPACE@[8; 9) " " + RET_TYPE@[9; 15) + THIN_ARROW@[9; 11) "->" + WHITESPACE@[11; 12) " " + PATH_TYPE@[12; 15) + PATH@[12; 15) + PATH_SEGMENT@[12; 15) + NAME_REF@[12; 15) + IDENT@[12; 15) "i32" + WHITESPACE@[15; 16) " " + BLOCK_EXPR@[16; 82) + BLOCK@[16; 82) + L_CURLY@[16; 17) "{" + WHITESPACE@[17; 22) "\n " + EXPR_STMT@[22; 80) + METHOD_CALL_EXPR@[22; 79) + METHOD_CALL_EXPR@[22; 57) + METHOD_CALL_EXPR@[22; 38) + ARRAY_EXPR@[22; 31) + L_BRACK@[22; 23) "[" + LITERAL@[23; 24) + INT_NUMBER@[23; 24) "1" + COMMA@[24; 25) "," + WHITESPACE@[25; 26) " " + LITERAL@[26; 27) + INT_NUMBER@[26; 27) "2" + COMMA@[27; 28) "," + WHITESPACE@[28; 29) " " + LITERAL@[29; 30) + INT_NUMBER@[29; 30) "3" + R_BRACK@[30; 31) "]" + DOT@[31; 32) "." + NAME_REF@[32; 36) + IDENT@[32; 36) "iter" + ARG_LIST@[36; 38) + L_PAREN@[36; 37) "(" + R_PAREN@[37; 38) ")" + WHITESPACE@[38; 47) "\n " + DOT@[47; 48) "." + NAME_REF@[48; 51) + IDENT@[48; 51) "map" + ARG_LIST@[51; 57) + L_PAREN@[51; 52) "(" + LAMBDA_EXPR@[52; 56) + PARAM_LIST@[52; 56) + PIPE@[52; 53) "|" + PARAM@[53; 55) + BIND_PAT@[53; 55) + NAME@[53; 55) + IDENT@[53; 55) "it" + PIPE@[55; 56) "|" + R_PAREN@[56; 57) ")" + WHITESPACE@[57; 66) "\n " + DOT@[66; 67) "." + NAME_REF@[67; 70) + IDENT@[67; 70) "max" + TYPE_ARG_LIST@[70; 77) + COLONCOLON@[70; 72) "::" + L_ANGLE@[72; 73) "<" + TYPE_ARG@[73; 76) + PATH_TYPE@[73; 76) + PATH@[73; 76) + PATH_SEGMENT@[73; 76) + NAME_REF@[73; 76) + IDENT@[73; 76) "i32" + R_ANGLE@[76; 77) ">" + ARG_LIST@[77; 79) + L_PAREN@[77; 78) "(" + R_PAREN@[78; 79) ")" + SEMI@[79; 80) ";" + WHITESPACE@[80; 81) "\n" + R_CURLY@[81; 82) "}" + WHITESPACE@[82; 83) "\n" +error 56: expected expression From 2432f278cb97701e1ca3750bc691ca9bd757892f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 12:41:44 +0100 Subject: [PATCH 188/312] Default to client watching on VS Code --- editors/code/package.json | 2 +- editors/code/src/config.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index 9290599c7a..34bc81d5fc 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -219,7 +219,7 @@ }, "rust-analyzer.useClientWatching": { "type": "boolean", - "default": false, + "default": true, "description": "client provided file watching instead of notify watching." }, "rust-analyzer.cargo-watch.arguments": { diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index defdfeb9c4..df15c81721 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -30,7 +30,7 @@ export class Config { public displayInlayHints = true; public maxInlayHintLength: null | number = null; public excludeGlobs = []; - public useClientWatching = false; + public useClientWatching = true; public featureFlags = {}; // for internal use public withSysroot: null | boolean = null; @@ -148,7 +148,7 @@ export class Config { this.excludeGlobs = config.get('excludeGlobs') || []; } if (config.has('useClientWatching')) { - this.useClientWatching = config.get('useClientWatching') || false; + this.useClientWatching = config.get('useClientWatching') || true; } if (config.has('featureFlags')) { this.featureFlags = config.get('featureFlags') || {}; From 1c8467e20aa8d481a4583a1c2cf40fad3d2ff53c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 14:43:37 +0100 Subject: [PATCH 189/312] Fix highlighting token names --- crates/ra_ide/src/snapshots/highlighting.html | 2 +- crates/ra_ide/src/snapshots/rainbow_highlighting.html | 2 +- crates/ra_ide/src/syntax_highlighting.rs | 2 +- editors/code/src/highlighting.ts | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 40605d9efd..2157139f66 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -7,9 +7,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string { color: #CC9393; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } -.builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\.builtin { color: #8CD0D3; } .type\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index ecf26c7084..871a52cf62 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -7,9 +7,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string { color: #CC9393; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } -.builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\.builtin { color: #8CD0D3; } .type\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index eb3dd17793..15e75709c1 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -284,9 +284,9 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .string { color: #CC9393; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } -.builtin { color: #DD6718; } .text { color: #DCDCCC; } .type { color: #7CB8BB; } +.type\\.builtin { color: #8CD0D3; } .type\\.param { color: #20999D; } .attribute { color: #94BFF3; } .literal { color: #BFEBBF; } diff --git a/editors/code/src/highlighting.ts b/editors/code/src/highlighting.ts index d7c0ae1316..e1b0d13e70 100644 --- a/editors/code/src/highlighting.ts +++ b/editors/code/src/highlighting.ts @@ -52,12 +52,12 @@ export class Highlighter { decoration('function'), decoration('parameter'), decoration('constant'), - decoration('type'), - decoration('type.self'), + decoration('type.builtin'), decoration('type.generic'), - decoration('type.param'), decoration('type.lifetime'), - decoration('builtin'), + decoration('type.param'), + decoration('type.self'), + decoration('type'), decoration('text'), decoration('attribute'), decoration('literal'), From aca022f1d49a6d945f3ef4f8c781d7337120b68d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 15:38:28 +0100 Subject: [PATCH 190/312] Refactor PathKind --- crates/ra_assists/src/assists/add_import.rs | 10 +++++-- crates/ra_hir_def/src/nameres/collector.rs | 2 +- .../ra_hir_def/src/nameres/path_resolution.rs | 26 ++++++++++++++----- crates/ra_hir_def/src/path.rs | 5 ++-- crates/ra_hir_def/src/path/lower.rs | 4 +-- crates/ra_hir_def/src/path/lower/lower_use.rs | 4 +-- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index f81b4184a0..ceffee9b87 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs @@ -582,8 +582,14 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option> { hir::PathKind::Abs => ps.push("".into()), hir::PathKind::Crate => ps.push("crate".into()), hir::PathKind::Plain => {} - hir::PathKind::Self_ => ps.push("self".into()), - hir::PathKind::Super => ps.push("super".into()), + hir::PathKind::Super(0) => ps.push("self".into()), + hir::PathKind::Super(lvl) => { + let mut chain = "super".to_string(); + for _ in 0..*lvl { + chain += "::super"; + } + ps.push(chain.into()); + } hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, } ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 912a073eac..8bbf7ffa27 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -890,7 +890,7 @@ where // We rewrite simple path `macro_name` to `self::macro_name` to force resolve in module scope only. let mut path = mac.path.clone(); if path.is_ident() { - path.kind = PathKind::Self_; + path.kind = PathKind::Super(0); } self.def_collector.unexpanded_macros.push(MacroDirective { diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 4a249e7e72..a3bfc15421 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -10,6 +10,8 @@ //! //! `ReachedFixedPoint` signals about this. +use std::iter::successors; + use hir_expand::name::Name; use ra_db::Edition; use test_utils::tested_by; @@ -97,9 +99,6 @@ impl CrateDefMap { PathKind::Crate => { PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into()) } - PathKind::Self_ => { - PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into()) - } // plain import or absolute path in 2015: crate-relative with // fallback to extern prelude (with the simplification in // rust-lang/rust#57745) @@ -123,9 +122,22 @@ impl CrateDefMap { log::debug!("resolving {:?} in module", segment); self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) } - PathKind::Super => { - if let Some(p) = self.modules[original_module].parent { - PerNs::types(ModuleId { krate: self.krate, local_id: p }.into()) + // PathKind::Self_ => { + // PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into()) + // } + // PathKind::Super => { + // if let Some(p) = self.modules[original_module].parent { + // PerNs::types(ModuleId { krate: self.krate, local_id: p }.into()) + // } else { + // log::debug!("super path in root module"); + // return ResolvePathResult::empty(ReachedFixedPoint::Yes); + // } + // } + PathKind::Super(lvl) => { + let m = successors(Some(original_module), |m| self.modules[*m].parent) + .nth(lvl as usize); + if let Some(local_id) = m { + PerNs::types(ModuleId { krate: self.krate, local_id }.into()) } else { log::debug!("super path in root module"); return ResolvePathResult::empty(ReachedFixedPoint::Yes); @@ -170,7 +182,7 @@ impl CrateDefMap { if module.krate != self.krate { let path = ModPath { segments: path.segments[i..].to_vec(), - kind: PathKind::Self_, + kind: PathKind::Super(0), }; log::debug!("resolving {:?} in other crate", path); let defp_map = db.crate_def_map(module.krate); diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 20d6d98ea0..3b26e8337f 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -56,7 +56,7 @@ impl ModPath { } pub fn is_self(&self) -> bool { - self.kind == PathKind::Self_ && self.segments.is_empty() + self.kind == PathKind::Super(0) && self.segments.is_empty() } /// If this path is a single identifier, like `foo`, return its name. @@ -100,8 +100,7 @@ pub enum GenericArg { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum PathKind { Plain, - Self_, - Super, + Super(u8), Crate, // Absolute path Abs, diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index a2e9951980..c71b52d898 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs @@ -95,11 +95,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option break; } ast::PathSegmentKind::SelfKw => { - kind = PathKind::Self_; + kind = PathKind::Super(0); break; } ast::PathSegmentKind::SuperKw => { - kind = PathKind::Super; + kind = PathKind::Super(1); break; } } diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index ea3fdb56cc..062c02063e 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs @@ -95,13 +95,13 @@ fn convert_path(prefix: Option, path: ast::Path, hygiene: &Hygiene) -> if prefix.is_some() { return None; } - ModPath::from_simple_segments(PathKind::Self_, iter::empty()) + ModPath::from_simple_segments(PathKind::Super(0), iter::empty()) } ast::PathSegmentKind::SuperKw => { if prefix.is_some() { return None; } - ModPath::from_simple_segments(PathKind::Super, iter::empty()) + ModPath::from_simple_segments(PathKind::Super(1), iter::empty()) } ast::PathSegmentKind::Type { .. } => { // not allowed in imports From 0630f8110f998f937608cb2962875a896a0298ae Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 17 Dec 2019 16:03:15 +0100 Subject: [PATCH 191/312] Drop dead code --- crates/ra_hir_def/src/nameres/path_resolution.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index a3bfc15421..1dbc4f3715 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -122,17 +122,6 @@ impl CrateDefMap { log::debug!("resolving {:?} in module", segment); self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx)) } - // PathKind::Self_ => { - // PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into()) - // } - // PathKind::Super => { - // if let Some(p) = self.modules[original_module].parent { - // PerNs::types(ModuleId { krate: self.krate, local_id: p }.into()) - // } else { - // log::debug!("super path in root module"); - // return ResolvePathResult::empty(ReachedFixedPoint::Yes); - // } - // } PathKind::Super(lvl) => { let m = successors(Some(original_module), |m| self.modules[*m].parent) .nth(lvl as usize); From da29b7fb14bcfd4ace1b743175393bcabdc02693 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 17 Dec 2019 23:48:26 +0800 Subject: [PATCH 192/312] use pretter settings in ts-lint --- editors/code/package-lock.json | 39 ++++++++++++++++++++++++++++++++++ editors/code/package.json | 3 ++- editors/code/tslint.json | 8 +++++-- 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index b1baa437e9..127cdcfa10 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -466,6 +466,16 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, + "eslint-plugin-prettier": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-2.7.0.tgz", + "integrity": "sha512-CStQYJgALoQBw3FsBzH0VOVDRnJ/ZimUlpLm226U8qgqYJfPOY/CPK6wyRInMxh73HSKg5wyRwdS4BVYYHwokA==", + "dev": true, + "requires": { + "fast-diff": "^1.1.1", + "jest-docblock": "^21.0.0" + } + }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", @@ -484,6 +494,12 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -712,6 +728,12 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "jest-docblock": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-21.2.0.tgz", + "integrity": "sha512-5IZ7sY9dBAYSV+YjQ0Ovb540Ku7AO9Z5o2Cg789xj167iQuZ2cG+z0f3Uct6WeYLbU6aQiM2pCs7sZ+4dotydw==", + "dev": true + }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -728,6 +750,12 @@ "esprima": "^4.0.0" } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, "linkify-it": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", @@ -1413,6 +1441,17 @@ "integrity": "sha512-xPw9PgNPLG3iKRxmK7DWr+Ea/SzrvfHtjFt5LBl61gk2UBG/DB9kCXRjv+xyIU1rUtnayLeMUVJBcMX8Z17nDg==", "dev": true }, + "tslint-plugin-prettier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslint-plugin-prettier/-/tslint-plugin-prettier-2.0.1.tgz", + "integrity": "sha512-4FX9JIx/1rKHIPJNfMb+ooX1gPk5Vg3vNi7+dyFYpLO+O57F4g+b/fo1+W/G0SUOkBLHB/YKScxjX/P+7ZT/Tw==", + "dev": true, + "requires": { + "eslint-plugin-prettier": "^2.2.0", + "lines-and-columns": "^1.1.6", + "tslib": "^1.7.1" + } + }, "tsutils": { "version": "2.29.0", "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", diff --git a/editors/code/package.json b/editors/code/package.json index 9290599c7a..ad1ba82efa 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -48,11 +48,12 @@ "rollup": "^1.27.9", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", - "rollup-plugin-typescript": "^1.0.1", "rollup-plugin-sourcemaps": "^0.4.2", + "rollup-plugin-typescript": "^1.0.1", "shx": "^0.3.1", "tslint": "^5.20.1", "tslint-config-prettier": "^1.18.0", + "tslint-plugin-prettier": "^2.0.1", "typescript": "^3.7.3", "vsce": "^1.70.0", "vscode-test": "^1.2.3" diff --git a/editors/code/tslint.json b/editors/code/tslint.json index b69c5574d2..f06fa5fab7 100644 --- a/editors/code/tslint.json +++ b/editors/code/tslint.json @@ -1,9 +1,13 @@ { "defaultSeverity": "error", - "extends": ["tslint:recommended", "tslint-config-prettier"], + "extends": [ + "tslint:recommended", + "tslint-config-prettier", + "tslint-plugin-prettier" + ], "rules": { - "quotemark": [true, "single"], "interface-name": false, + "prettier": true, "object-literal-sort-keys": false, // Allow `_bar` to sort with tsc's `noUnusedParameters` option "variable-name": [true, "allow-leading-underscore"] From f909d2b56c2f21c03beea2275d5e0d9052599302 Mon Sep 17 00:00:00 2001 From: Francisco Lopes Date: Tue, 17 Dec 2019 20:47:20 -0300 Subject: [PATCH 193/312] Cleanup Vim and NeoVim instructions. Fix #2579 --- docs/user/README.md | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/docs/user/README.md b/docs/user/README.md index 04c3493426..9cdabfd421 100644 --- a/docs/user/README.md +++ b/docs/user/README.md @@ -135,37 +135,25 @@ to load path and require it in `init.el` * (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints -## Vim and NeoVim +## Vim and NeoVim (coc-rust-analyzer) -Neovim 0.5 has a built in language server. For a quick start configuration of -rust-analyzer, use [neovim/nvim-lsp](https://github.com/neovim/nvim-lsp#rust_analyzer). -Once `neovim/nvim-lsp` is installed, you can use `call nvim_lsp#setup("rust_analyzer", {})` -or `lua require'nvim_lsp'.rust_analyzer.setup({})` to quickly get set up. - -* Install coc.nvim by following the instructions at [coc.nvim] - - You will need nodejs installed. - - You may want to include some of the sample vim configurations [from here][coc-vim-conf] - - Note that if you use a plugin manager other than `vim-plug`, you may need to manually - checkout the `release` branch wherever your plugin manager cloned it. Otherwise you will - get errors about a missing javascript file. -* Run `:CocInstall coc-rust-analyzer` to install [coc-rust-analyzer], this extension implemented _most_ of the features supported in the VSCode extension: +* Install coc.nvim by following the instructions at [coc.nvim][] (nodejs required) +* Run `:CocInstall coc-rust-analyzer` to install [coc-rust-analyzer], this extension implements _most_ of the features supported in the VSCode extension: - same configurations as VSCode extension, `rust-analyzer.raLspServerPath`, `rust-analyzer.enableCargoWatchOnStartup` etc. - same commands too, `rust-analyzer.analyzerStatus`, `rust-analyzer.startCargoWatch` etc. - highlighting and inlay_hints are not implemented yet [coc.nvim]: https://github.com/neoclide/coc.nvim -[coc-vim-conf]: https://github.com/neoclide/coc.nvim/#example-vim-configuration [coc-rust-analyzer]: https://github.com/fannheyward/coc-rust-analyzer -## Vim and NeoVim Alternative +## Vim and NeoVim (LanguageClient-neovim) * Install LanguageClient-neovim by following the instructions [here][lang-client-neovim] - - No extra run-time is required as this server is written in Rust - The github project wiki has extra tips on configuration * Configure by adding this to your vim/neovim config file (replacing the existing rust specific line if it exists): -``` +```vim let g:LanguageClient_serverCommands = { \ 'rust': ['ra_lsp_server'], \ } @@ -173,6 +161,13 @@ let g:LanguageClient_serverCommands = { [lang-client-neovim]: https://github.com/autozimu/LanguageClient-neovim +## NeoVim (nvim-lsp) + +NeoVim 0.5 (not yet released) has built in language server support. For a quick start configuration +of rust-analyzer, use [neovim/nvim-lsp](https://github.com/neovim/nvim-lsp#rust_analyzer). +Once `neovim/nvim-lsp` is installed, you can use `call nvim_lsp#setup("rust_analyzer", {})` +or `lua require'nvim_lsp'.rust_analyzer.setup({})` to quickly get set up. + ## Sublime Text 3 From d2c1f8ee2606e10e196485d6bdbd87146d2545de Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 17 Dec 2019 13:50:00 +0800 Subject: [PATCH 194/312] Add macro span handling --- editors/code/src/utils/diagnostics/rust.ts | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/editors/code/src/utils/diagnostics/rust.ts b/editors/code/src/utils/diagnostics/rust.ts index b6efc0f564..1f0c0d3e40 100644 --- a/editors/code/src/utils/diagnostics/rust.ts +++ b/editors/code/src/utils/diagnostics/rust.ts @@ -10,6 +10,12 @@ export enum SuggestionApplicability { Unspecified = 'Unspecified', } +export interface RustDiagnosticSpanMacroExpansion { + span: RustDiagnosticSpan; + macro_decl_name: string; + def_site_span?: RustDiagnosticSpan; +} + // Reference: // https://github.com/rust-lang/rust/blob/master/src/libsyntax/json.rs export interface RustDiagnosticSpan { @@ -20,6 +26,7 @@ export interface RustDiagnosticSpan { is_primary: boolean; file_name: string; label?: string; + expansion?: RustDiagnosticSpanMacroExpansion; suggested_replacement?: string; suggestion_applicability?: SuggestionApplicability; } @@ -60,10 +67,41 @@ function mapLevelToSeverity(s: string): vscode.DiagnosticSeverity { return vscode.DiagnosticSeverity.Information; } +/** + * Check whether a file name is from macro invocation + */ +function isFromMacro(fileName: string): boolean { + return fileName.startsWith('<') && fileName.endsWith('>'); +} + +/** + * Converts a Rust macro span to a VsCode location recursively + */ +function mapMacroSpanToLocation( + spanMacro: RustDiagnosticSpanMacroExpansion, +): vscode.Location | undefined { + if (!isFromMacro(spanMacro.span.file_name)) { + return mapSpanToLocation(spanMacro.span); + } + + if (spanMacro.span.expansion) { + return mapMacroSpanToLocation(spanMacro.span.expansion); + } + + return; +} + /** * Converts a Rust span to a VsCode location */ function mapSpanToLocation(span: RustDiagnosticSpan): vscode.Location { + if (isFromMacro(span.file_name) && span.expansion) { + const macroLoc = mapMacroSpanToLocation(span.expansion); + if (macroLoc) { + return macroLoc; + } + } + const fileName = path.join(vscode.workspace.rootPath || '', span.file_name); const fileUri = vscode.Uri.file(fileName); From 63c59308e6ece788084374c4fc393576684992a7 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 17 Dec 2019 13:50:08 +0800 Subject: [PATCH 195/312] Add tests --- .../rust-diagnostics/error/E0277.json | 261 ++++++++++++++++++ .../src/test/utils/diagnotics/rust.test.ts | 34 +++ 2 files changed, 295 insertions(+) create mode 100644 editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json diff --git a/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json b/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json new file mode 100644 index 0000000000..bfef33c7de --- /dev/null +++ b/editors/code/src/test/fixtures/rust-diagnostics/error/E0277.json @@ -0,0 +1,261 @@ +{ + "rendered": "error[E0277]: can't compare `{integer}` with `&str`\n --> src/main.rs:2:5\n |\n2 | assert_eq!(1, \"love\");\n | ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `{integer} == &str`\n |\n = help: the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`\n = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)\n\n", + "children": [ + { + "children": [], + "code": null, + "level": "help", + "message": "the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`", + "rendered": null, + "spans": [] + } + ], + "code": { + "code": "E0277", + "explanation": "\nYou tried to use a type which doesn't implement some trait in a place which\nexpected that trait. Erroneous code example:\n\n```compile_fail,E0277\n// here we declare the Foo trait with a bar method\ntrait Foo {\n fn bar(&self);\n}\n\n// we now declare a function which takes an object implementing the Foo trait\nfn some_func(foo: T) {\n foo.bar();\n}\n\nfn main() {\n // we now call the method with the i32 type, which doesn't implement\n // the Foo trait\n some_func(5i32); // error: the trait bound `i32 : Foo` is not satisfied\n}\n```\n\nIn order to fix this error, verify that the type you're using does implement\nthe trait. Example:\n\n```\ntrait Foo {\n fn bar(&self);\n}\n\nfn some_func(foo: T) {\n foo.bar(); // we can now use this method since i32 implements the\n // Foo trait\n}\n\n// we implement the trait on the i32 type\nimpl Foo for i32 {\n fn bar(&self) {}\n}\n\nfn main() {\n some_func(5i32); // ok!\n}\n```\n\nOr in a generic context, an erroneous code example would look like:\n\n```compile_fail,E0277\nfn some_func(foo: T) {\n println!(\"{:?}\", foo); // error: the trait `core::fmt::Debug` is not\n // implemented for the type `T`\n}\n\nfn main() {\n // We now call the method with the i32 type,\n // which *does* implement the Debug trait.\n some_func(5i32);\n}\n```\n\nNote that the error here is in the definition of the generic function: Although\nwe only call it with a parameter that does implement `Debug`, the compiler\nstill rejects the function: It must work with all possible input types. In\norder to make this example compile, we need to restrict the generic type we're\naccepting:\n\n```\nuse std::fmt;\n\n// Restrict the input type to types that implement Debug.\nfn some_func(foo: T) {\n println!(\"{:?}\", foo);\n}\n\nfn main() {\n // Calling the method is still fine, as i32 implements Debug.\n some_func(5i32);\n\n // This would fail to compile now:\n // struct WithoutDebug;\n // some_func(WithoutDebug);\n}\n```\n\nRust only looks at the signature of the called function, as such it must\nalready specify all requirements that will be used for every type parameter.\n" + }, + "level": "error", + "message": "can't compare `{integer}` with `&str`", + "spans": [ + { + "byte_end": 155, + "byte_start": 153, + "column_end": 33, + "column_start": 31, + "expansion": { + "def_site_span": { + "byte_end": 940, + "byte_start": 0, + "column_end": 6, + "column_start": 1, + "expansion": null, + "file_name": "<::core::macros::assert_eq macros>", + "is_primary": false, + "label": null, + "line_end": 36, + "line_start": 1, + "suggested_replacement": null, + "suggestion_applicability": null, + "text": [ + { + "highlight_end": 35, + "highlight_start": 1, + "text": "($ left : expr, $ right : expr) =>" + }, + { + "highlight_end": 3, + "highlight_start": 1, + "text": "({" + }, + { + "highlight_end": 33, + "highlight_start": 1, + "text": " match (& $ left, & $ right)" + }, + { + "highlight_end": 7, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 34, + "highlight_start": 1, + "text": " (left_val, right_val) =>" + }, + { + "highlight_end": 11, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 46, + "highlight_start": 1, + "text": " if ! (* left_val == * right_val)" + }, + { + "highlight_end": 15, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 25, + "highlight_start": 1, + "text": " panic !" + }, + { + "highlight_end": 57, + "highlight_start": 1, + "text": " (r#\"assertion failed: `(left == right)`" + }, + { + "highlight_end": 16, + "highlight_start": 1, + "text": " left: `{:?}`," + }, + { + "highlight_end": 18, + "highlight_start": 1, + "text": " right: `{:?}`\"#," + }, + { + "highlight_end": 47, + "highlight_start": 1, + "text": " & * left_val, & * right_val)" + }, + { + "highlight_end": 15, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 11, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 7, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 42, + "highlight_start": 1, + "text": " }) ; ($ left : expr, $ right : expr,) =>" + }, + { + "highlight_end": 49, + "highlight_start": 1, + "text": "({ $ crate :: assert_eq ! ($ left, $ right) }) ;" + }, + { + "highlight_end": 53, + "highlight_start": 1, + "text": "($ left : expr, $ right : expr, $ ($ arg : tt) +) =>" + }, + { + "highlight_end": 3, + "highlight_start": 1, + "text": "({" + }, + { + "highlight_end": 37, + "highlight_start": 1, + "text": " match (& ($ left), & ($ right))" + }, + { + "highlight_end": 7, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 34, + "highlight_start": 1, + "text": " (left_val, right_val) =>" + }, + { + "highlight_end": 11, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 46, + "highlight_start": 1, + "text": " if ! (* left_val == * right_val)" + }, + { + "highlight_end": 15, + "highlight_start": 1, + "text": " {" + }, + { + "highlight_end": 25, + "highlight_start": 1, + "text": " panic !" + }, + { + "highlight_end": 57, + "highlight_start": 1, + "text": " (r#\"assertion failed: `(left == right)`" + }, + { + "highlight_end": 16, + "highlight_start": 1, + "text": " left: `{:?}`," + }, + { + "highlight_end": 22, + "highlight_start": 1, + "text": " right: `{:?}`: {}\"#," + }, + { + "highlight_end": 72, + "highlight_start": 1, + "text": " & * left_val, & * right_val, $ crate :: format_args !" + }, + { + "highlight_end": 33, + "highlight_start": 1, + "text": " ($ ($ arg) +))" + }, + { + "highlight_end": 15, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 11, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 7, + "highlight_start": 1, + "text": " }" + }, + { + "highlight_end": 6, + "highlight_start": 1, + "text": " }) ;" + } + ] + }, + "macro_decl_name": "assert_eq!", + "span": { + "byte_end": 38, + "byte_start": 16, + "column_end": 27, + "column_start": 5, + "expansion": null, + "file_name": "src/main.rs", + "is_primary": false, + "label": null, + "line_end": 2, + "line_start": 2, + "suggested_replacement": null, + "suggestion_applicability": null, + "text": [ + { + "highlight_end": 27, + "highlight_start": 5, + "text": " assert_eq!(1, \"love\");" + } + ] + } + }, + "file_name": "<::core::macros::assert_eq macros>", + "is_primary": true, + "label": "no implementation for `{integer} == &str`", + "line_end": 7, + "line_start": 7, + "suggested_replacement": null, + "suggestion_applicability": null, + "text": [ + { + "highlight_end": 33, + "highlight_start": 31, + "text": " if ! (* left_val == * right_val)" + } + ] + } + ] +} diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts index 0222dbbaa0..9acd319b30 100644 --- a/editors/code/src/test/utils/diagnotics/rust.test.ts +++ b/editors/code/src/test/utils/diagnotics/rust.test.ts @@ -199,4 +199,38 @@ describe('mapRustDiagnosticToVsCode', () => { // There are no suggested fixes assert.strictEqual(suggestedFixes.length, 0); }); + + it('should map a macro invocation location to normal file path', () => { + const { location, diagnostic, suggestedFixes } = mapFixtureToVsCode( + 'error/E0277', + ); + + assert.strictEqual( + diagnostic.severity, + vscode.DiagnosticSeverity.Error, + ); + assert.strictEqual( + diagnostic.message, + [ + 'can\'t compare `{integer}` with `&str`', + 'the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`', + ].join('\n'), + ); + assert.strictEqual(diagnostic.code, 'E0277'); + assert.strictEqual(diagnostic.source, 'rustc'); + assert.deepStrictEqual(diagnostic.tags, []); + + // No related information + assert.deepStrictEqual(diagnostic.relatedInformation, []); + + // There are no suggested fixes + assert.strictEqual(suggestedFixes.length, 0); + + // The file url should be normal file + // Ignore the first part because it depends on vs workspace location + assert.strictEqual( + true, + location.uri.toString().endsWith('src/main.rs'), + ); + }); }); From bb9c60d90863b21a0e981f00e354d02b0e9fb584 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Tue, 17 Dec 2019 21:43:19 +0800 Subject: [PATCH 196/312] Use substr instead of endswith --- editors/code/src/test/utils/diagnotics/rust.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/editors/code/src/test/utils/diagnotics/rust.test.ts b/editors/code/src/test/utils/diagnotics/rust.test.ts index 9acd319b30..358325cc8d 100644 --- a/editors/code/src/test/utils/diagnotics/rust.test.ts +++ b/editors/code/src/test/utils/diagnotics/rust.test.ts @@ -212,7 +212,7 @@ describe('mapRustDiagnosticToVsCode', () => { assert.strictEqual( diagnostic.message, [ - 'can\'t compare `{integer}` with `&str`', + "can't compare `{integer}` with `&str`", 'the trait `std::cmp::PartialEq<&str>` is not implemented for `{integer}`', ].join('\n'), ); @@ -229,8 +229,8 @@ describe('mapRustDiagnosticToVsCode', () => { // The file url should be normal file // Ignore the first part because it depends on vs workspace location assert.strictEqual( - true, - location.uri.toString().endsWith('src/main.rs'), + location.uri.path.substr(-'src/main.rs'.length), + 'src/main.rs', ); }); }); From aceb9d7fb0809ccf364514d9177342edea144c59 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 12 Dec 2019 21:47:54 +0800 Subject: [PATCH 197/312] Add token ids for all tt::Leaf --- crates/ra_hir_expand/src/builtin_derive.rs | 28 ++++++++++-- crates/ra_hir_expand/src/quote.rs | 13 +++--- crates/ra_mbe/src/mbe_expander/transcriber.rs | 7 ++- crates/ra_mbe/src/syntax_bridge.rs | 45 +++++++++++-------- crates/ra_mbe/src/tests.rs | 10 ++--- crates/ra_tt/src/lib.rs | 2 + 6 files changed, 72 insertions(+), 33 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index b264412538..62c60e336c 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs @@ -97,11 +97,24 @@ fn parse_adt(tt: &tt::Subtree) -> Result { fn make_type_args(n: usize, bound: Vec) -> Vec { let mut result = Vec::::new(); - result.push(tt::Leaf::Punct(tt::Punct { char: '<', spacing: tt::Spacing::Alone }).into()); + result.push( + tt::Leaf::Punct(tt::Punct { + char: '<', + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + }) + .into(), + ); for i in 0..n { if i > 0 { - result - .push(tt::Leaf::Punct(tt::Punct { char: ',', spacing: tt::Spacing::Alone }).into()); + result.push( + tt::Leaf::Punct(tt::Punct { + char: ',', + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + }) + .into(), + ); } result.push( tt::Leaf::Ident(tt::Ident { @@ -112,7 +125,14 @@ fn make_type_args(n: usize, bound: Vec) -> Vec { ); result.extend(bound.iter().cloned()); } - result.push(tt::Leaf::Punct(tt::Punct { char: '>', spacing: tt::Spacing::Alone }).into()); + result.push( + tt::Leaf::Punct(tt::Punct { + char: '>', + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + }) + .into(), + ); result } diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index aa8a5f23fd..bce38cc679 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -29,6 +29,7 @@ macro_rules! __quote { tt::Leaf::Punct(tt::Punct { char: $first, spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), }).into() ] } @@ -40,10 +41,12 @@ macro_rules! __quote { tt::Leaf::Punct(tt::Punct { char: $first, spacing: tt::Spacing::Joint, + id: tt::TokenId::unspecified(), }).into(), tt::Leaf::Punct(tt::Punct { char: $sec, spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), }).into() ] } @@ -179,15 +182,15 @@ macro_rules! impl_to_to_tokentrees { } impl_to_to_tokentrees! { - u32 => self { tt::Literal{text: self.to_string().into()} }; - usize => self { tt::Literal{text: self.to_string().into()}}; - i32 => self { tt::Literal{text: self.to_string().into()}}; + u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; + usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; + i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; tt::Leaf => self { self }; tt::Literal => self { self }; tt::Ident => self { self }; tt::Punct => self { self }; - &str => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into()}}; - String => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into()}} + &str => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into(), id: tt::TokenId::unspecified()}}; + String => self { tt::Literal{text: format!("{:?}", self.escape_default().to_string()).into(), id: tt::TokenId::unspecified()}} } #[cfg(test)] diff --git a/crates/ra_mbe/src/mbe_expander/transcriber.rs b/crates/ra_mbe/src/mbe_expander/transcriber.rs index f7636db11b..eda66cd506 100644 --- a/crates/ra_mbe/src/mbe_expander/transcriber.rs +++ b/crates/ra_mbe/src/mbe_expander/transcriber.rs @@ -108,7 +108,12 @@ fn expand_var(ctx: &mut ExpandCtx, v: &SmolStr) -> Result let tt = tt::Subtree { delimiter: None, token_trees: vec![ - tt::Leaf::from(tt::Punct { char: '$', spacing: tt::Spacing::Alone }).into(), + tt::Leaf::from(tt::Punct { + char: '$', + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + }) + .into(), tt::Leaf::from(tt::Ident { text: v.clone(), id: tt::TokenId::unspecified() }) .into(), ], diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index b8e2cfc1d8..8f65ff125e 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -136,11 +136,15 @@ fn convert_doc_comment(token: &ra_syntax::SyntaxToken) -> Option tt::TokenTree { - tt::TokenTree::from(tt::Leaf::from(tt::Punct { char: c, spacing: tt::Spacing::Alone })) + tt::TokenTree::from(tt::Leaf::from(tt::Punct { + char: c, + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + })) } fn mk_doc_literal(comment: &ast::Comment) -> tt::TokenTree { - let lit = tt::Literal { text: doc_comment_text(comment) }; + let lit = tt::Literal { text: doc_comment_text(comment), id: tt::TokenId::unspecified() }; tt::TokenTree::from(tt::Leaf::from(lit)) } @@ -223,24 +227,29 @@ impl Convertor { .take(token.text().len() - 1) .chain(std::iter::once(last_spacing)); for (char, spacing) in token.text().chars().zip(spacing_iter) { - token_trees.push(tt::Leaf::from(tt::Punct { char, spacing }).into()); + let id = self.alloc(token.text_range()); + token_trees + .push(tt::Leaf::from(tt::Punct { char, spacing, id }).into()); } } else { - let child: tt::TokenTree = - if token.kind() == T![true] || token.kind() == T![false] { - tt::Leaf::from(tt::Literal { text: token.text().clone() }).into() - } else if token.kind().is_keyword() - || token.kind() == IDENT - || token.kind() == LIFETIME - { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Leaf::from(tt::Ident { text, id }).into() - } else if token.kind().is_literal() { - tt::Leaf::from(tt::Literal { text: token.text().clone() }).into() - } else { - return None; - }; + let child: tt::TokenTree = if token.kind() == T![true] + || token.kind() == T![false] + { + let id = self.alloc(token.text_range()); + tt::Leaf::from(tt::Literal { text: token.text().clone(), id }).into() + } else if token.kind().is_keyword() + || token.kind() == IDENT + || token.kind() == LIFETIME + { + let id = self.alloc(token.text_range()); + let text = token.text().clone(); + tt::Leaf::from(tt::Ident { text, id }).into() + } else if token.kind().is_literal() { + let id = self.alloc(token.text_range()); + tt::Leaf::from(tt::Literal { text: token.text().clone(), id }).into() + } else { + return None; + }; token_trees.push(child); } } diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 148cc26254..70e65bc74c 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -78,12 +78,12 @@ macro_rules! foobar { assert_eq!(expansion.token_trees.len(), 3); // ($e:ident) => { foo bar $e } - // 0 1 2 3 4 - assert_eq!(get_id(&expansion.token_trees[0]), Some(2)); - assert_eq!(get_id(&expansion.token_trees[1]), Some(3)); + // 0123 45 6 7 89 + assert_eq!(get_id(&expansion.token_trees[0]), Some(6)); + assert_eq!(get_id(&expansion.token_trees[1]), Some(7)); - // So baz should be 5 - assert_eq!(get_id(&expansion.token_trees[2]), Some(5)); + // So baz should be 10 + assert_eq!(get_id(&expansion.token_trees[2]), Some(10)); } #[test] diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index e7bfd5fd29..209ca40484 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -64,12 +64,14 @@ pub enum Delimiter { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Literal { pub text: SmolStr, + pub id: TokenId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct Punct { pub char: char, pub spacing: Spacing, + pub id: TokenId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] From 59295854f892b0a8f42a6fbc80b04d1f1c695828 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 13 Dec 2019 01:41:44 +0800 Subject: [PATCH 198/312] Add token id to delims --- crates/ra_hir_expand/src/quote.rs | 14 ++- crates/ra_mbe/src/mbe_expander/matcher.rs | 2 +- crates/ra_mbe/src/subtree_source.rs | 8 +- crates/ra_mbe/src/syntax_bridge.rs | 144 +++++++++++++++------- crates/ra_mbe/src/tests.rs | 14 ++- crates/ra_tt/src/lib.rs | 16 ++- 6 files changed, 134 insertions(+), 64 deletions(-) diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index bce38cc679..49155fe626 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -16,7 +16,10 @@ macro_rules! __quote { { let children = $crate::__quote!($($tt)*); let subtree = tt::Subtree { - delimiter: Some(tt::Delimiter::$delim), + delimiter: Some(tt::Delimiter { + kind: tt::DelimiterKind::$delim, + id: tt::TokenId::unspecified(), + }), token_trees: $crate::quote::IntoTt::to_tokens(children), }; subtree @@ -257,8 +260,13 @@ mod tests { let fields = fields.iter().map(|it| quote!(#it: self.#it.clone(), ).token_trees.clone()).flatten(); - let list = - tt::Subtree { delimiter: Some(tt::Delimiter::Brace), token_trees: fields.collect() }; + let list = tt::Subtree { + delimiter: Some(tt::Delimiter { + kind: tt::DelimiterKind::Brace, + id: tt::TokenId::unspecified(), + }), + token_trees: fields.collect(), + }; let quoted = quote! { impl Clone for #struct_name { diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 3f51364780..c67ae41109 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs @@ -106,7 +106,7 @@ fn match_subtree( } Op::TokenTree(tt::TokenTree::Subtree(lhs)) => { let rhs = src.expect_subtree().map_err(|()| err!("expected subtree"))?; - if lhs.delimiter != rhs.delimiter { + if lhs.delimiter.map(|it| it.kind) != rhs.delimiter.map(|it| it.kind) { bail!("mismatched delimiter") } let mut src = TtIter::new(rhs); diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 061e9f20b2..5a03a372a3 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs @@ -115,10 +115,10 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> { } fn convert_delim(d: Option, closing: bool) -> TtToken { - let (kinds, texts) = match d { - Some(tt::Delimiter::Parenthesis) => ([T!['('], T![')']], "()"), - Some(tt::Delimiter::Brace) => ([T!['{'], T!['}']], "{}"), - Some(tt::Delimiter::Bracket) => ([T!['['], T![']']], "[]"), + let (kinds, texts) = match d.map(|it| it.kind) { + Some(tt::DelimiterKind::Parenthesis) => ([T!['('], T![')']], "()"), + Some(tt::DelimiterKind::Brace) => ([T!['{'], T!['}']], "{}"), + Some(tt::DelimiterKind::Bracket) => ([T!['['], T![']']], "[]"), None => ([L_DOLLAR, R_DOLLAR], ""), }; diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8f65ff125e..a85bb058b7 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -5,6 +5,7 @@ use ra_syntax::{ ast, AstToken, NodeOrToken, Parse, SmolStr, SyntaxKind, SyntaxKind::*, SyntaxNode, SyntaxTreeBuilder, TextRange, TextUnit, T, }; +use rustc_hash::FxHashMap; use std::iter::successors; use tt::buffer::{Cursor, TokenBuffer}; @@ -83,6 +84,15 @@ impl TokenMap { fn insert(&mut self, token_id: tt::TokenId, relative_range: TextRange) { self.entries.push((token_id, relative_range)); } + + fn insert_delim( + &mut self, + _token_id: tt::TokenId, + _open_relative_range: TextRange, + _close_relative_range: TextRange, + ) { + // FIXME: Add entries for delimiter + } } /// Returns the textual content of a doc comment block as a quoted string @@ -121,7 +131,10 @@ fn convert_doc_comment(token: &ra_syntax::SyntaxToken) -> Option (Some(tt::Delimiter::Parenthesis), true), - (T!['{'], T!['}']) => (Some(tt::Delimiter::Brace), true), - (T!['['], T![']']) => (Some(tt::Delimiter::Bracket), true), + let (delimiter_kind, skip_first) = match (first_child.kind(), last_child.kind()) { + (T!['('], T![')']) => (Some(tt::DelimiterKind::Parenthesis), true), + (T!['{'], T!['}']) => (Some(tt::DelimiterKind::Brace), true), + (T!['['], T![']']) => (Some(tt::DelimiterKind::Bracket), true), _ => (None, false), }; + let delimiter = delimiter_kind.map(|kind| tt::Delimiter { + kind, + id: self.alloc_delim(first_child.text_range(), last_child.text_range()), + }); let mut token_trees = Vec::new(); let mut child_iter = tt.children_with_tokens().skip(skip_first as usize).peekable(); @@ -232,25 +249,31 @@ impl Convertor { .push(tt::Leaf::from(tt::Punct { char, spacing, id }).into()); } } else { - let child: tt::TokenTree = if token.kind() == T![true] - || token.kind() == T![false] - { - let id = self.alloc(token.text_range()); - tt::Leaf::from(tt::Literal { text: token.text().clone(), id }).into() - } else if token.kind().is_keyword() - || token.kind() == IDENT - || token.kind() == LIFETIME - { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Leaf::from(tt::Ident { text, id }).into() - } else if token.kind().is_literal() { - let id = self.alloc(token.text_range()); - tt::Leaf::from(tt::Literal { text: token.text().clone(), id }).into() - } else { - return None; + let child: tt::Leaf = match token.kind() { + T![true] | T![false] => { + let id = self.alloc(token.text_range()); + let text = token.text().clone(); + tt::Literal { text, id }.into() + } + IDENT | LIFETIME => { + let id = self.alloc(token.text_range()); + let text = token.text().clone(); + tt::Ident { text, id }.into() + } + k if k.is_keyword() => { + let id = self.alloc(token.text_range()); + let text = token.text().clone(); + tt::Ident { text, id }.into() + } + k if k.is_literal() => { + let id = self.alloc(token.text_range()); + let text = token.text().clone(); + tt::Literal { text, id }.into() + } + _ => return None, }; - token_trees.push(child); + + token_trees.push(child.into()); } } NodeOrToken::Node(node) => { @@ -275,11 +298,26 @@ impl Convertor { self.map.insert(token_id, relative_range); token_id } + + fn alloc_delim( + &mut self, + open_abs_range: TextRange, + close_abs_range: TextRange, + ) -> tt::TokenId { + let open_relative_range = open_abs_range - self.global_offset; + let close_relative_range = close_abs_range - self.global_offset; + let token_id = tt::TokenId(self.next_id); + self.next_id += 1; + + self.map.insert_delim(token_id, open_relative_range, close_relative_range); + token_id + } } struct TtTreeSink<'a> { buf: String, cursor: Cursor<'a>, + open_delims: FxHashMap, text_pos: TextUnit, inner: SyntaxTreeBuilder, token_map: TokenMap, @@ -294,6 +332,7 @@ impl<'a> TtTreeSink<'a> { TtTreeSink { buf: String::new(), cursor, + open_delims: FxHashMap::default(), text_pos: 0.into(), inner: SyntaxTreeBuilder::default(), roots: smallvec::SmallVec::new(), @@ -307,10 +346,10 @@ impl<'a> TtTreeSink<'a> { } fn delim_to_str(d: Option, closing: bool) -> SmolStr { - let texts = match d { - Some(tt::Delimiter::Parenthesis) => "()", - Some(tt::Delimiter::Brace) => "{}", - Some(tt::Delimiter::Bracket) => "[]", + let texts = match d.map(|it| it.kind) { + Some(tt::DelimiterKind::Parenthesis) => "()", + Some(tt::DelimiterKind::Brace) => "{}", + Some(tt::DelimiterKind::Bracket) => "[]", None => return "".into(), }; @@ -331,34 +370,49 @@ impl<'a> TreeSink for TtTreeSink<'a> { break; } - match self.cursor.token_tree() { + let text: Option = match self.cursor.token_tree() { Some(tt::TokenTree::Leaf(leaf)) => { // Mark the range if needed - if let tt::Leaf::Ident(ident) = leaf { - if kind == IDENT { - let range = - TextRange::offset_len(self.text_pos, TextUnit::of_str(&ident.text)); - self.token_map.insert(ident.id, range); - } - } - + let id = match leaf { + tt::Leaf::Ident(ident) => ident.id, + tt::Leaf::Punct(punct) => punct.id, + tt::Leaf::Literal(lit) => lit.id, + }; + let text = SmolStr::new(format!("{}", leaf)); + let range = TextRange::offset_len(self.text_pos, TextUnit::of_str(&text)); + self.token_map.insert(id, range); self.cursor = self.cursor.bump(); - self.buf += &format!("{}", leaf); + Some(text) } Some(tt::TokenTree::Subtree(subtree)) => { self.cursor = self.cursor.subtree().unwrap(); - self.buf += &delim_to_str(subtree.delimiter, false); - } - None => { - if let Some(parent) = self.cursor.end() { - self.cursor = self.cursor.bump(); - self.buf += &delim_to_str(parent.delimiter, true); + if let Some(id) = subtree.delimiter.map(|it| it.id) { + self.open_delims.insert(id, self.text_pos); } + Some(delim_to_str(subtree.delimiter, false)) } + None => self.cursor.end().and_then(|parent| { + self.cursor = self.cursor.bump(); + if let Some(id) = parent.delimiter.map(|it| it.id) { + if let Some(open_delim) = self.open_delims.get(&id) { + let open_range = + TextRange::offset_len(*open_delim, TextUnit::from_usize(1)); + let close_range = + TextRange::offset_len(self.text_pos, TextUnit::from_usize(1)); + self.token_map.insert_delim(id, open_range, close_range); + } + } + + Some(delim_to_str(parent.delimiter, true)) + }), }; + + if let Some(text) = text { + self.buf += &text; + self.text_pos += TextUnit::of_str(&text); + } } - self.text_pos += TextUnit::of_str(&self.buf); let text = SmolStr::new(self.buf.as_str()); self.buf.clear(); self.inner.token(kind, text); @@ -504,7 +558,7 @@ mod tests { let token_tree = ast::TokenTree::cast(token_tree).unwrap(); let tt = ast_to_token_tree(&token_tree).unwrap().0; - assert_eq!(tt.delimiter, Some(tt::Delimiter::Brace)); + assert_eq!(tt.delimiter.map(|it| it.kind), Some(tt::DelimiterKind::Brace)); } #[test] diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 70e65bc74c..6bcfedcac2 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -77,13 +77,15 @@ macro_rules! foobar { } assert_eq!(expansion.token_trees.len(), 3); - // ($e:ident) => { foo bar $e } - // 0123 45 6 7 89 - assert_eq!(get_id(&expansion.token_trees[0]), Some(6)); - assert_eq!(get_id(&expansion.token_trees[1]), Some(7)); + // {($e:ident) => { foo bar $e }} + // 012345 67 8 9 T 12 + assert_eq!(get_id(&expansion.token_trees[0]), Some(9)); + assert_eq!(get_id(&expansion.token_trees[1]), Some(10)); - // So baz should be 10 - assert_eq!(get_id(&expansion.token_trees[2]), Some(10)); + // The input args of macro call include parentheses: + // (baz) + // So baz should be 12+1+1 + assert_eq!(get_id(&expansion.token_trees[2]), Some(14)); } #[test] diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 209ca40484..73d8395a8e 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -55,7 +55,13 @@ pub struct Subtree { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub enum Delimiter { +pub struct Delimiter { + pub id: TokenId, + pub kind: DelimiterKind, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum DelimiterKind { Parenthesis, Brace, Bracket, @@ -97,10 +103,10 @@ impl fmt::Display for TokenTree { impl fmt::Display for Subtree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (l, r) = match self.delimiter { - Some(Delimiter::Parenthesis) => ("(", ")"), - Some(Delimiter::Brace) => ("{", "}"), - Some(Delimiter::Bracket) => ("[", "]"), + let (l, r) = match self.delimiter.map(|it| it.kind) { + Some(DelimiterKind::Parenthesis) => ("(", ")"), + Some(DelimiterKind::Brace) => ("{", "}"), + Some(DelimiterKind::Bracket) => ("[", "]"), None => ("", ""), }; f.write_str(l)?; From 320416d7561e9926ecbbc392cc2efd48740610e0 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 13 Dec 2019 23:55:51 +0800 Subject: [PATCH 199/312] Add TokenTextRange --- crates/ra_hir_expand/src/lib.rs | 4 +-- crates/ra_mbe/src/syntax_bridge.rs | 41 ++++++++++++++++++++++++------ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index cb4e1950bf..720a29ea58 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -227,7 +227,7 @@ impl ExpansionInfo { let token_id = self.macro_arg.1.token_by_range(range)?; let token_id = self.macro_def.0.map_id_down(token_id); - let range = self.exp_map.range_by_token(token_id)?; + let range = self.exp_map.range_by_token(token_id)?.range(token.value.kind())?; let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; @@ -248,7 +248,7 @@ impl ExpansionInfo { } }; - let range = token_map.range_by_token(token_id)?; + let range = token_map.range_by_token(token_id)?.range(token.value.kind())?; let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) .into_token()?; Some((tt.with_value(token), origin)) diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index a85bb058b7..44a51b7a51 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -12,11 +12,30 @@ use tt::buffer::{Cursor, TokenBuffer}; use crate::subtree_source::SubtreeTokenSource; use crate::ExpandError; +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub enum TokenTextRange { + Token(TextRange), + Delimiter(TextRange, TextRange), +} + +impl TokenTextRange { + pub fn range(self, kind: SyntaxKind) -> Option { + match self { + TokenTextRange::Token(it) => Some(it), + TokenTextRange::Delimiter(open, close) => match kind { + T!['{'] | T!['('] | T!['['] => Some(open), + T!['}'] | T![')'] | T![']'] => Some(close), + _ => None, + }, + } + } +} + /// Maps `tt::TokenId` to the relative range of the original token. #[derive(Debug, PartialEq, Eq, Default)] pub struct TokenMap { /// Maps `tt::TokenId` to the *relative* source range. - entries: Vec<(tt::TokenId, TextRange)>, + entries: Vec<(tt::TokenId, TokenTextRange)>, } /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro @@ -72,26 +91,32 @@ pub fn token_tree_to_syntax_node( impl TokenMap { pub fn token_by_range(&self, relative_range: TextRange) -> Option { - let &(token_id, _) = self.entries.iter().find(|(_, range)| *range == relative_range)?; + let &(token_id, _) = self.entries.iter().find(|(_, range)| match range { + TokenTextRange::Token(it) => *it == relative_range, + TokenTextRange::Delimiter(open, close) => { + *open == relative_range || *close == relative_range + } + })?; Some(token_id) } - pub fn range_by_token(&self, token_id: tt::TokenId) -> Option { + pub fn range_by_token(&self, token_id: tt::TokenId) -> Option { let &(_, range) = self.entries.iter().find(|(tid, _)| *tid == token_id)?; Some(range) } fn insert(&mut self, token_id: tt::TokenId, relative_range: TextRange) { - self.entries.push((token_id, relative_range)); + self.entries.push((token_id, TokenTextRange::Token(relative_range))); } fn insert_delim( &mut self, - _token_id: tt::TokenId, - _open_relative_range: TextRange, - _close_relative_range: TextRange, + token_id: tt::TokenId, + open_relative_range: TextRange, + close_relative_range: TextRange, ) { - // FIXME: Add entries for delimiter + self.entries + .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); } } From 325532d11960733bebdd38b19a6f33a891872803 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 14 Dec 2019 03:37:04 +0800 Subject: [PATCH 200/312] Fix shift id for delim and other tokens --- crates/ra_mbe/src/lib.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index ce2deadf6e..45dad2d108 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -67,7 +67,15 @@ impl Shift { .token_trees .iter() .filter_map(|tt| match tt { - tt::TokenTree::Subtree(subtree) => max_id(subtree), + tt::TokenTree::Subtree(subtree) => { + let tree_id = max_id(subtree); + match subtree.delimiter { + Some(it) if it.id != tt::TokenId::unspecified() => { + Some(tree_id.map_or(it.id.0, |t| t.max(it.id.0))) + } + _ => tree_id, + } + } tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) if ident.id != tt::TokenId::unspecified() => { @@ -85,9 +93,13 @@ impl Shift { match t { tt::TokenTree::Leaf(leaf) => match leaf { tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id), - _ => (), + tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id), + tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id), }, - tt::TokenTree::Subtree(tt) => self.shift_all(tt), + tt::TokenTree::Subtree(tt) => { + tt.delimiter.as_mut().map(|it: &mut Delimiter| it.id = self.shift(it.id)); + self.shift_all(tt) + } } } } From e16f3a5ee2f7df3f42827f3f279b5ed6774bde8e Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 14 Dec 2019 03:39:15 +0800 Subject: [PATCH 201/312] Add test for token map --- crates/ra_mbe/src/tests.rs | 43 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 6bcfedcac2..ae7f3dfd40 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -88,6 +88,32 @@ macro_rules! foobar { assert_eq!(get_id(&expansion.token_trees[2]), Some(14)); } +#[test] +fn test_token_map() { + use ra_parser::SyntaxKind::*; + use ra_syntax::T; + + let macro_definition = r#" +macro_rules! foobar { + ($e:ident) => { fn $e() {} } +} +"#; + let rules = create_rules(macro_definition); + let (expansion, (token_map, content)) = expand_and_map(&rules, "foobar!(baz);"); + + let get_text = |id, kind| -> String { + content[token_map.range_by_token(id).unwrap().range(kind).unwrap()].to_string() + }; + + assert_eq!(expansion.token_trees.len(), 4); + // {($e:ident) => { fn $e() {} }} + // 012345 67 8 9 T12 3 + + assert_eq!(get_text(tt::TokenId(9), IDENT), "fn"); + assert_eq!(get_text(tt::TokenId(12), T!['(']), "("); + assert_eq!(get_text(tt::TokenId(13), T!['{']), "{"); +} + #[test] fn test_convert_tt() { let macro_definition = r#" @@ -1443,6 +1469,23 @@ pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { rules.expand(&invocation_tt).unwrap() } +pub(crate) fn expand_and_map( + rules: &MacroRules, + invocation: &str, +) -> (tt::Subtree, (TokenMap, String)) { + let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); + let macro_invocation = + source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); + + let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); + let expanded = rules.expand(&invocation_tt).unwrap(); + + let (node, expanded_token_tree) = + token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); + + (expanded, (expanded_token_tree, node.syntax_node().to_string())) +} + pub(crate) enum MacroKind { Items, Stmts, From 2ea1cfd7804dd57d63196e71f66c22e56cfd79a8 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 18 Dec 2019 11:36:10 +0800 Subject: [PATCH 202/312] Rename range to by_kind --- crates/ra_hir_expand/src/lib.rs | 4 ++-- crates/ra_mbe/src/syntax_bridge.rs | 2 +- crates/ra_mbe/src/tests.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 720a29ea58..2fa5d51402 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs @@ -227,7 +227,7 @@ impl ExpansionInfo { let token_id = self.macro_arg.1.token_by_range(range)?; let token_id = self.macro_def.0.map_id_down(token_id); - let range = self.exp_map.range_by_token(token_id)?.range(token.value.kind())?; + let range = self.exp_map.range_by_token(token_id)?.by_kind(token.value.kind())?; let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; @@ -248,7 +248,7 @@ impl ExpansionInfo { } }; - let range = token_map.range_by_token(token_id)?.range(token.value.kind())?; + let range = token_map.range_by_token(token_id)?.by_kind(token.value.kind())?; let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) .into_token()?; Some((tt.with_value(token), origin)) diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 44a51b7a51..d585d57af1 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -19,7 +19,7 @@ pub enum TokenTextRange { } impl TokenTextRange { - pub fn range(self, kind: SyntaxKind) -> Option { + pub fn by_kind(self, kind: SyntaxKind) -> Option { match self { TokenTextRange::Token(it) => Some(it), TokenTextRange::Delimiter(open, close) => match kind { diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index ae7f3dfd40..ff225f0db2 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -102,7 +102,7 @@ macro_rules! foobar { let (expansion, (token_map, content)) = expand_and_map(&rules, "foobar!(baz);"); let get_text = |id, kind| -> String { - content[token_map.range_by_token(id).unwrap().range(kind).unwrap()].to_string() + content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string() }; assert_eq!(expansion.token_trees.len(), 4); From 41544a40883874553f570e2999bf56d172bd6246 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Wed, 18 Dec 2019 11:47:26 +0800 Subject: [PATCH 203/312] Refactoring --- crates/ra_mbe/src/mbe_expander/matcher.rs | 2 +- crates/ra_mbe/src/subtree_source.rs | 8 +- crates/ra_mbe/src/syntax_bridge.rs | 92 +++++++++++------------ crates/ra_tt/src/lib.rs | 6 +- 4 files changed, 55 insertions(+), 53 deletions(-) diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index c67ae41109..e36b5a412b 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs @@ -106,7 +106,7 @@ fn match_subtree( } Op::TokenTree(tt::TokenTree::Subtree(lhs)) => { let rhs = src.expect_subtree().map_err(|()| err!("expected subtree"))?; - if lhs.delimiter.map(|it| it.kind) != rhs.delimiter.map(|it| it.kind) { + if lhs.delimiter_kind() != rhs.delimiter_kind() { bail!("mismatched delimiter") } let mut src = TtIter::new(rhs); diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 5a03a372a3..b841c39d31 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs @@ -70,11 +70,11 @@ impl<'a> SubtreeTokenSource<'a> { } Some(tt::TokenTree::Subtree(subtree)) => { self.cached_cursor.set(cursor.subtree().unwrap()); - cached.push(Some(convert_delim(subtree.delimiter, false))); + cached.push(Some(convert_delim(subtree.delimiter_kind(), false))); } None => { if let Some(subtree) = cursor.end() { - cached.push(Some(convert_delim(subtree.delimiter, true))); + cached.push(Some(convert_delim(subtree.delimiter_kind(), true))); self.cached_cursor.set(cursor.bump()); } } @@ -114,8 +114,8 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> { } } -fn convert_delim(d: Option, closing: bool) -> TtToken { - let (kinds, texts) = match d.map(|it| it.kind) { +fn convert_delim(d: Option, closing: bool) -> TtToken { + let (kinds, texts) = match d { Some(tt::DelimiterKind::Parenthesis) => ([T!['('], T![')']], "()"), Some(tt::DelimiterKind::Brace) => ([T!['{'], T!['}']], "{}"), Some(tt::DelimiterKind::Bracket) => ([T!['['], T![']']], "[]"), diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index d585d57af1..2c60430d15 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -269,35 +269,33 @@ impl Convertor { .take(token.text().len() - 1) .chain(std::iter::once(last_spacing)); for (char, spacing) in token.text().chars().zip(spacing_iter) { - let id = self.alloc(token.text_range()); - token_trees - .push(tt::Leaf::from(tt::Punct { char, spacing, id }).into()); + token_trees.push( + tt::Leaf::from(tt::Punct { + char, + spacing, + id: self.alloc(token.text_range()), + }) + .into(), + ); } } else { + macro_rules! make_leaf { + ($i:ident) => { + tt::$i { + id: self.alloc(token.text_range()), + text: token.text().clone(), + } + .into() + }; + } + let child: tt::Leaf = match token.kind() { - T![true] | T![false] => { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Literal { text, id }.into() - } - IDENT | LIFETIME => { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Ident { text, id }.into() - } - k if k.is_keyword() => { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Ident { text, id }.into() - } - k if k.is_literal() => { - let id = self.alloc(token.text_range()); - let text = token.text().clone(); - tt::Literal { text, id }.into() - } + T![true] | T![false] => make_leaf!(Literal), + IDENT | LIFETIME => make_leaf!(Ident), + k if k.is_keyword() => make_leaf!(Ident), + k if k.is_literal() => make_leaf!(Literal), _ => return None, }; - token_trees.push(child.into()); } } @@ -370,8 +368,8 @@ impl<'a> TtTreeSink<'a> { } } -fn delim_to_str(d: Option, closing: bool) -> SmolStr { - let texts = match d.map(|it| it.kind) { +fn delim_to_str(d: Option, closing: bool) -> SmolStr { + let texts = match d { Some(tt::DelimiterKind::Parenthesis) => "()", Some(tt::DelimiterKind::Brace) => "{}", Some(tt::DelimiterKind::Bracket) => "[]", @@ -395,7 +393,7 @@ impl<'a> TreeSink for TtTreeSink<'a> { break; } - let text: Option = match self.cursor.token_tree() { + let text: SmolStr = match self.cursor.token_tree() { Some(tt::TokenTree::Leaf(leaf)) => { // Mark the range if needed let id = match leaf { @@ -407,35 +405,35 @@ impl<'a> TreeSink for TtTreeSink<'a> { let range = TextRange::offset_len(self.text_pos, TextUnit::of_str(&text)); self.token_map.insert(id, range); self.cursor = self.cursor.bump(); - Some(text) + text } Some(tt::TokenTree::Subtree(subtree)) => { self.cursor = self.cursor.subtree().unwrap(); if let Some(id) = subtree.delimiter.map(|it| it.id) { self.open_delims.insert(id, self.text_pos); } - Some(delim_to_str(subtree.delimiter, false)) + delim_to_str(subtree.delimiter_kind(), false) } - None => self.cursor.end().and_then(|parent| { - self.cursor = self.cursor.bump(); - if let Some(id) = parent.delimiter.map(|it| it.id) { - if let Some(open_delim) = self.open_delims.get(&id) { - let open_range = - TextRange::offset_len(*open_delim, TextUnit::from_usize(1)); - let close_range = - TextRange::offset_len(self.text_pos, TextUnit::from_usize(1)); - self.token_map.insert_delim(id, open_range, close_range); + None => { + if let Some(parent) = self.cursor.end() { + self.cursor = self.cursor.bump(); + if let Some(id) = parent.delimiter.map(|it| it.id) { + if let Some(open_delim) = self.open_delims.get(&id) { + let open_range = + TextRange::offset_len(*open_delim, TextUnit::from_usize(1)); + let close_range = + TextRange::offset_len(self.text_pos, TextUnit::from_usize(1)); + self.token_map.insert_delim(id, open_range, close_range); + } } + delim_to_str(parent.delimiter_kind(), true) + } else { + continue; } - - Some(delim_to_str(parent.delimiter, true)) - }), + } }; - - if let Some(text) = text { - self.buf += &text; - self.text_pos += TextUnit::of_str(&text); - } + self.buf += &text; + self.text_pos += TextUnit::of_str(&text); } let text = SmolStr::new(self.buf.as_str()); @@ -583,7 +581,7 @@ mod tests { let token_tree = ast::TokenTree::cast(token_tree).unwrap(); let tt = ast_to_token_tree(&token_tree).unwrap().0; - assert_eq!(tt.delimiter.map(|it| it.kind), Some(tt::DelimiterKind::Brace)); + assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace)); } #[test] diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 73d8395a8e..10f424aae9 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs @@ -103,7 +103,7 @@ impl fmt::Display for TokenTree { impl fmt::Display for Subtree { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let (l, r) = match self.delimiter.map(|it| it.kind) { + let (l, r) = match self.delimiter_kind() { Some(DelimiterKind::Parenthesis) => ("(", ")"), Some(DelimiterKind::Brace) => ("{", "}"), Some(DelimiterKind::Bracket) => ("[", "]"), @@ -171,6 +171,10 @@ impl Subtree { self.token_trees.len() + children_count } + + pub fn delimiter_kind(&self) -> Option { + self.delimiter.map(|it| it.kind) + } } pub mod buffer; From 7ec43ee07a26667bb1458990ec667f82670aff22 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Mon, 18 Nov 2019 18:08:39 -0500 Subject: [PATCH 204/312] WIP: See through Macros for SignatureHelp Note: we meed to skip the trivia filter to make sure that `covers!(call_info_bad_offset)` succeeds otherwise we exit call_info too early. Also the test doesn't pass: `FnCallNode::with_node` always detects a MacroCall. --- crates/ra_ide/src/call_info.rs | 39 ++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index b3c323d38c..2da9c4e765 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -1,22 +1,22 @@ //! FIXME: write short doc here -use ra_db::SourceDatabase; +use hir::db::AstDatabase; use ra_syntax::{ - algo::ancestors_at_offset, ast::{self, ArgListOwner}, - match_ast, AstNode, SyntaxNode, TextUnit, + match_ast, AstNode, SyntaxNode, }; use test_utils::tested_by; -use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature}; +use crate::{db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature}; /// Computes parameter information for the given call expression. pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { - let parse = db.parse(position.file_id); - let syntax = parse.tree().syntax().clone(); + let file = db.parse_or_expand(position.file_id.into())?; + let token = file.token_at_offset(position.offset).next()?; + let token = descend_into_macros(db, position.file_id, token); // Find the calling expression and it's NameRef - let calling_node = FnCallNode::with_node(&syntax, position.offset)?; + let calling_node = FnCallNode::with_node(&token.value.parent())?; let name_ref = calling_node.name_ref()?; let name_ref = hir::InFile::new(position.file_id.into(), name_ref.syntax()); @@ -93,8 +93,8 @@ enum FnCallNode { } impl FnCallNode { - fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option { - ancestors_at_offset(syntax, offset).find_map(|node| { + fn with_node(syntax: &SyntaxNode) -> Option { + syntax.ancestors().find_map(|node| { match_ast! { match node { ast::CallExpr(it) => { Some(FnCallNode::CallExpr(it)) }, @@ -589,4 +589,25 @@ fn f() { assert_eq!(info.label(), "foo!()"); assert_eq!(info.doc().map(|it| it.into()), Some("empty macro".to_string())); } + + #[test] + fn fn_signature_for_call_in_macro() { + let info = call_info( + r#" + macro_rules! id { + ($($tt:tt)*) => { $($tt)* } + } + fn foo() { + + } + id! { + fn bar() { + foo(<|>); + } + } + "#, + ); + + assert_eq!(info.label(), "fn foo()"); + } } From cdc6af6bda50641a061608f433ec2cff53bf66d3 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Wed, 18 Dec 2019 08:58:48 -0500 Subject: [PATCH 205/312] Pass test --- crates/ra_ide/src/call_info.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 2da9c4e765..3495cfa6d3 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -18,7 +18,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option Date: Wed, 18 Dec 2019 09:11:47 -0500 Subject: [PATCH 206/312] cargo fmt --- crates/ra_ide/src/call_info.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index 3495cfa6d3..2c2b6fa489 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs @@ -7,7 +7,9 @@ use ra_syntax::{ }; use test_utils::tested_by; -use crate::{db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature}; +use crate::{ + db::RootDatabase, expand::descend_into_macros, CallInfo, FilePosition, FunctionSignature, +}; /// Computes parameter information for the given call expression. pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option { From 6e48a5bf9121f94bd91c9066fc7c4814fb88aff2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 15:40:48 +0100 Subject: [PATCH 207/312] Make reformat hook actually reformat files --- xtask/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 190baeddfc..40a6682be9 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs @@ -144,6 +144,7 @@ pub fn run_fuzzer() -> Result<()> { } pub fn reformat_staged_files() -> Result<()> { + run_rustfmt(Mode::Overwrite)?; let root = project_root(); let output = Command::new("git") .arg("diff") From 69c944a1e27212604ce85154fd40cff1d46ad6f3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 14:52:58 +0100 Subject: [PATCH 208/312] Add blank lines for readability --- crates/ra_ide/src/goto_definition.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index bee8e9df28..3b4d89e3e1 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -285,8 +285,10 @@ mod tests { mod a; mod b; enum E { X(Foo<|>) } + //- /a.rs struct Foo; + //- /b.rs struct Foo; ", @@ -300,6 +302,7 @@ mod tests { " //- /lib.rs mod <|>foo; + //- /foo.rs // empty ", @@ -310,6 +313,7 @@ mod tests { " //- /lib.rs mod <|>foo; + //- /foo/mod.rs // empty ", From 46a299bceece6f8633d7c1518939efbb3a57fae3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 15:33:36 +0100 Subject: [PATCH 209/312] Refactor goto tests to always specify texts --- crates/ra_ide/src/goto_definition.rs | 124 ++++++++++++++++----------- crates/test_utils/src/lib.rs | 4 +- 2 files changed, 76 insertions(+), 52 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 3b4d89e3e1..48757f1706 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -225,30 +225,35 @@ mod tests { use crate::mock_analysis::analysis_and_position; - fn check_goto(fixture: &str, expected: &str) { + fn check_goto(fixture: &str, expected: &str, expected_range: &str) { let (analysis, pos) = analysis_and_position(fixture); let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; assert_eq!(navs.len(), 1); + let nav = navs.pop().unwrap(); - nav.assert_match(expected); - } + let file_text = analysis.file_text(nav.file_id()).unwrap(); - fn check_goto_with_range_content(fixture: &str, expected: &str, expected_range: &str) { - let (analysis, pos) = analysis_and_position(fixture); + let mut actual = file_text[nav.full_range()].to_string(); + if let Some(focus) = nav.focus_range() { + actual += "|"; + actual += &file_text[focus]; + } - let mut navs = analysis.goto_definition(pos).unwrap().unwrap().info; - assert_eq!(navs.len(), 1); - let nav = navs.pop().unwrap(); - let file_text = analysis.file_text(pos.file_id).unwrap(); + if !expected_range.contains("...") { + test_utils::assert_eq_text!(&actual, expected_range); + } else { + let mut parts = expected_range.split("..."); + let prefix = parts.next().unwrap(); + let suffix = parts.next().unwrap(); + assert!( + actual.starts_with(prefix) && actual.ends_with(suffix), + "\nExpected: {}\n Actual: {}\n", + expected_range, + actual + ); + } - let actual_full_range = &file_text[nav.full_range()]; - let actual_range = &file_text[nav.range()]; - - test_utils::assert_eq_text!( - &format!("{}|{}", actual_full_range, actual_range), - expected_range - ); nav.assert_match(expected); } @@ -261,6 +266,7 @@ mod tests { enum E { X(Foo<|>) } ", "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + "struct Foo;|Foo", ); } @@ -273,6 +279,7 @@ mod tests { enum E { X(<|>Foo) } ", "Foo STRUCT_DEF FileId(1) [0; 11) [7; 10)", + "struct Foo;|Foo", ); } @@ -293,6 +300,7 @@ mod tests { struct Foo; ", "Foo STRUCT_DEF FileId(2) [0; 11) [7; 10)", + "struct Foo;|Foo", ); } @@ -307,6 +315,7 @@ mod tests { // empty ", "foo SOURCE_FILE FileId(2) [0; 10)", + "// empty\n\n", ); check_goto( @@ -318,6 +327,7 @@ mod tests { // empty ", "foo SOURCE_FILE FileId(2) [0; 10)", + "// empty\n\n", ); } @@ -327,17 +337,14 @@ mod tests { check_goto( " //- /lib.rs - macro_rules! foo { - () => { - {} - }; - } + macro_rules! foo { () => { () } } fn bar() { <|>foo!(); } ", - "foo MACRO_CALL FileId(1) [0; 50) [13; 16)", + "foo MACRO_CALL FileId(1) [0; 33) [13; 16)", + "macro_rules! foo { () => { () } }|foo", ); } @@ -354,13 +361,10 @@ mod tests { //- /foo/lib.rs #[macro_export] - macro_rules! foo { - () => { - {} - }; - } + macro_rules! foo { () => { () } } ", - "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", + "foo MACRO_CALL FileId(2) [0; 49) [29; 32)", + "#[macro_export]\nmacro_rules! foo { () => { () } }|foo", ); } @@ -373,19 +377,16 @@ mod tests { //- /foo/lib.rs #[macro_export] - macro_rules! foo { - () => { - {} - }; - } + macro_rules! foo { () => { () } } ", - "foo MACRO_CALL FileId(2) [0; 66) [29; 32)", + "foo MACRO_CALL FileId(2) [0; 49) [29; 32)", + "#[macro_export]\nmacro_rules! foo { () => { () } }|foo", ); } #[test] fn goto_definition_works_for_macro_defined_fn_with_arg() { - check_goto_with_range_content( + check_goto( " //- /lib.rs macro_rules! define_fn { @@ -405,7 +406,7 @@ mod tests { #[test] fn goto_definition_works_for_macro_defined_fn_no_arg() { - check_goto_with_range_content( + check_goto( " //- /lib.rs macro_rules! define_fn { @@ -431,14 +432,15 @@ mod tests { //- /lib.rs struct Foo; impl Foo { - fn frobnicate(&self) { } + fn frobnicate(&self) { } } fn bar(foo: &Foo) { foo.frobnicate<|>(); } ", - "frobnicate FN_DEF FileId(1) [27; 52) [30; 40)", + "frobnicate FN_DEF FileId(1) [27; 51) [30; 40)", + "fn frobnicate(&self) { }|frobnicate", ); } @@ -457,6 +459,7 @@ mod tests { } ", "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", + "spam: u32|spam", ); } @@ -477,6 +480,7 @@ mod tests { } ", "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", + "spam: u32|spam", ); } @@ -493,6 +497,7 @@ mod tests { } ", "TUPLE_FIELD_DEF FileId(1) [11; 14)", + "u32", ); } @@ -503,14 +508,15 @@ mod tests { //- /lib.rs struct Foo; impl Foo { - fn frobnicate() { } + fn frobnicate() { } } fn bar(foo: &Foo) { Foo::frobnicate<|>(); } ", - "frobnicate FN_DEF FileId(1) [27; 47) [30; 40)", + "frobnicate FN_DEF FileId(1) [27; 46) [30; 40)", + "fn frobnicate() { }|frobnicate", ); } @@ -528,6 +534,7 @@ mod tests { } ", "frobnicate FN_DEF FileId(1) [16; 32) [19; 29)", + "fn frobnicate();|frobnicate", ); } @@ -547,6 +554,7 @@ mod tests { } ", "frobnicate FN_DEF FileId(1) [30; 46) [33; 43)", + "fn frobnicate();|frobnicate", ); } @@ -563,6 +571,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [12; 73)", + "impl Foo {...}", ); check_goto( @@ -576,6 +585,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [12; 73)", + "impl Foo {...}", ); check_goto( @@ -589,6 +599,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [15; 75)", + "impl Foo {...}", ); check_goto( @@ -601,6 +612,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [15; 62)", + "impl Foo {...}", ); } @@ -620,6 +632,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [49; 115)", + "impl Make for Foo {...}", ); check_goto( @@ -636,6 +649,7 @@ mod tests { } ", "impl IMPL_BLOCK FileId(1) [49; 115)", + "impl Make for Foo {...}", ); } @@ -647,6 +661,7 @@ mod tests { struct Foo<|> { value: u32 } ", "Foo STRUCT_DEF FileId(1) [0; 25) [7; 10)", + "struct Foo { value: u32 }|Foo", ); check_goto( @@ -657,15 +672,16 @@ mod tests { } "#, "field RECORD_FIELD_DEF FileId(1) [17; 30) [17; 22)", + "field: string|field", ); check_goto( " //- /lib.rs - fn foo_test<|>() { - } + fn foo_test<|>() { } ", "foo_test FN_DEF FileId(1) [0; 17) [3; 11)", + "fn foo_test() { }|foo_test", ); check_goto( @@ -676,6 +692,7 @@ mod tests { } ", "Foo ENUM_DEF FileId(1) [0; 25) [5; 8)", + "enum Foo {...}|Foo", ); check_goto( @@ -688,22 +705,25 @@ mod tests { } ", "Variant2 ENUM_VARIANT FileId(1) [29; 37) [29; 37)", + "Variant2|Variant2", ); check_goto( r#" //- /lib.rs - static inner<|>: &str = ""; + static INNER<|>: &str = ""; "#, - "inner STATIC_DEF FileId(1) [0; 24) [7; 12)", + "INNER STATIC_DEF FileId(1) [0; 24) [7; 12)", + "static INNER: &str = \"\";|INNER", ); check_goto( r#" //- /lib.rs - const inner<|>: &str = ""; + const INNER<|>: &str = ""; "#, - "inner CONST_DEF FileId(1) [0; 23) [6; 11)", + "INNER CONST_DEF FileId(1) [0; 23) [6; 11)", + "const INNER: &str = \"\";|INNER", ); check_goto( @@ -712,24 +732,25 @@ mod tests { type Thing<|> = Option<()>; "#, "Thing TYPE_ALIAS_DEF FileId(1) [0; 24) [5; 10)", + "type Thing = Option<()>;|Thing", ); check_goto( r#" //- /lib.rs - trait Foo<|> { - } + trait Foo<|> { } "#, "Foo TRAIT_DEF FileId(1) [0; 13) [6; 9)", + "trait Foo { }|Foo", ); check_goto( r#" //- /lib.rs - mod bar<|> { - } + mod bar<|> { } "#, "bar MODULE FileId(1) [0; 11) [4; 7)", + "mod bar { }|bar", ); } @@ -750,6 +771,7 @@ mod tests { mod confuse_index { fn foo(); } ", "foo FN_DEF FileId(1) [52; 63) [55; 58)", + "fn foo() {}|foo", ); } @@ -778,6 +800,7 @@ mod tests { } ", "foo FN_DEF FileId(1) [398; 415) [401; 404)", + "fn foo() -> i8 {}|foo", ); } @@ -791,6 +814,7 @@ mod tests { } ", "T TYPE_PARAM FileId(1) [11; 12)", + "T", ); } } diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 657ddf2a69..659f77b71a 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -207,8 +207,8 @@ pub fn lines_match(expected: &str, actual: &str) -> bool { // Let's not deal with / vs \ (windows...) // First replace backslash-escaped backslashes with forward slashes // which can occur in, for example, JSON output - let expected = expected.replace("\\\\", "/").replace("\\", "/"); - let mut actual: &str = &actual.replace("\\\\", "/").replace("\\", "/"); + let expected = expected.replace(r"\\", "/").replace(r"\", "/"); + let mut actual: &str = &actual.replace(r"\\", "/").replace(r"\", "/"); for (i, part) in expected.split("[..]").enumerate() { match actual.find(part) { Some(j) => { From 7c25224f0522cb828c4aa2d791562b84ee2995f9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 16:25:15 +0100 Subject: [PATCH 210/312] Don't bother with focus range for navigation to locals --- .../ra_ide/src/display/navigation_target.rs | 15 +++---- crates/ra_ide/src/goto_definition.rs | 41 +++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6a6b49afdf..b9ae678284 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs @@ -328,22 +328,23 @@ impl ToNav for hir::AssocItem { impl ToNav for hir::Local { fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { let src = self.source(db); - let (full_range, focus_range) = match src.value { - Either::Left(it) => { - (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) + let node = match &src.value { + Either::Left(bind_pat) => { + bind_pat.name().map_or_else(|| bind_pat.syntax().clone(), |it| it.syntax().clone()) } - Either::Right(it) => (it.syntax().text_range(), Some(it.self_kw_token().text_range())), + Either::Right(it) => it.syntax().clone(), }; + let full_range = original_range(db, src.with_value(&node)); let name = match self.name(db) { Some(it) => it.to_string().into(), None => "".into(), }; NavigationTarget { - file_id: src.file_id.original_file(db), + file_id: full_range.file_id, name, kind: BIND_PAT, - full_range, - focus_range, + full_range: full_range.range, + focus_range: None, container_name: None, description: None, docs: None, diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 48757f1706..184555792c 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -817,4 +817,45 @@ mod tests { "T", ); } + + #[test] + fn goto_within_macro() { + check_goto( + " + //- /lib.rs + macro_rules! id { + ($($tt:tt)*) => ($($tt)*) + } + + fn foo() { + let x = 1; + id!({ + let y = <|>x; + let z = y; + }); + } + ", + "x BIND_PAT FileId(1) [69; 70)", + "x", + ); + + check_goto( + " + //- /lib.rs + macro_rules! id { + ($($tt:tt)*) => ($($tt)*) + } + + fn foo() { + let x = 1; + id!({ + let y = x; + let z = <|>y; + }); + } + ", + "y BIND_PAT FileId(1) [98; 99)", + "y", + ); + } } From d043689735edc12388e22f49b2319362f3b003fa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:04:20 +0100 Subject: [PATCH 211/312] Touch up docs --- crates/ra_hir_def/src/path.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3b26e8337f..c37364f573 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -100,13 +100,14 @@ pub enum GenericArg { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum PathKind { Plain, + /// `self::` is `Super(0)` Super(u8), Crate, - // Absolute path + /// Absolute path (::foo) Abs, - // Type based path like `::foo` + /// Type based path like `::foo` Type(Box), - // `$crate` from macro expansion + /// `$crate` from macro expansion DollarCrate(CrateId), } From 88c6109897417e7ab815ea1711f49545bff94601 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:06:52 +0100 Subject: [PATCH 212/312] Move PathKindUp --- crates/ra_hir_def/src/path.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index c37364f573..e38d924faa 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -18,6 +18,20 @@ pub struct ModPath { pub segments: Vec, } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum PathKind { + Plain, + /// `self::` is `Super(0)` + Super(u8), + Crate, + /// Absolute path (::foo) + Abs, + /// Type based path like `::foo` + Type(Box), + /// `$crate` from macro expansion + DollarCrate(CrateId), +} + impl ModPath { pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option { lower::lower_path(path, hygiene).map(|it| it.mod_path) @@ -97,20 +111,6 @@ pub enum GenericArg { // or lifetime... } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub enum PathKind { - Plain, - /// `self::` is `Super(0)` - Super(u8), - Crate, - /// Absolute path (::foo) - Abs, - /// Type based path like `::foo` - Type(Box), - /// `$crate` from macro expansion - DollarCrate(CrateId), -} - impl Path { /// Converts an `ast::Path` to `Path`. Works with use trees. /// DEPRECATED: It does not handle `$crate` from macro call. From 04715cbe1caf92e55d393a352a12454ba958845e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:41:33 +0100 Subject: [PATCH 213/312] Forbid ::foo syntax in mod paths --- crates/ra_assists/src/assists/add_import.rs | 2 +- crates/ra_hir_def/src/body.rs | 12 ++++++++---- crates/ra_hir_def/src/nameres/path_resolution.rs | 5 ----- crates/ra_hir_def/src/path.rs | 12 +++++++++--- crates/ra_hir_def/src/path/lower.rs | 6 ++++-- crates/ra_hir_ty/src/infer/path.rs | 4 ++-- crates/ra_hir_ty/src/lower.rs | 6 +++--- 7 files changed, 27 insertions(+), 20 deletions(-) diff --git a/crates/ra_assists/src/assists/add_import.rs b/crates/ra_assists/src/assists/add_import.rs index ceffee9b87..b8752cbad5 100644 --- a/crates/ra_assists/src/assists/add_import.rs +++ b/crates/ra_assists/src/assists/add_import.rs @@ -590,7 +590,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option> { } ps.push(chain.into()); } - hir::PathKind::Type(_) | hir::PathKind::DollarCrate(_) => return None, + hir::PathKind::DollarCrate(_) => return None, } ps.extend(path.segments().iter().map(|it| it.name.to_string().into())); Some(ps) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 7787cb87ff..d4cab05614 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -15,7 +15,7 @@ use crate::{ db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, nameres::{BuiltinShadowMode, CrateDefMap}, - path::Path, + path::{ModPath, Path}, src::HasSource, DefWithBodyId, HasModule, Lookup, ModuleId, }; @@ -44,7 +44,7 @@ impl Expander { db.ast_id_map(self.current_file_id).ast_id(¯o_call), ); - if let Some(path) = macro_call.path().and_then(|path| self.parse_path(path)) { + if let Some(path) = macro_call.path().and_then(|path| self.parse_mod_path(path)) { if let Some(def) = self.resolve_path_as_macro(db, &path) { let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); let file_id = call_id.as_file(); @@ -81,9 +81,13 @@ impl Expander { Path::from_src(path, &self.hygiene) } - fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &Path) -> Option { + fn parse_mod_path(&mut self, path: ast::Path) -> Option { + ModPath::from_src(path, &self.hygiene) + } + + fn resolve_path_as_macro(&self, db: &impl DefDatabase, path: &ModPath) -> Option { self.crate_def_map - .resolve_path(db, self.module.local_id, path.mod_path(), BuiltinShadowMode::Other) + .resolve_path(db, self.module.local_id, path, BuiltinShadowMode::Other) .0 .take_macros() } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 1dbc4f3715..2dd779b66e 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -145,11 +145,6 @@ impl CrateDefMap { return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude } } - PathKind::Type(_) => { - // This is handled in `infer::infer_path_expr` - // The result returned here does not matter - return ResolvePathResult::empty(ReachedFixedPoint::Yes); - } }; for (i, segment) in segments { diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index e38d924faa..1e2da6b481 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -26,8 +26,6 @@ pub enum PathKind { Crate, /// Absolute path (::foo) Abs, - /// Type based path like `::foo` - Type(Box), /// `$crate` from macro expansion DollarCrate(CrateId), } @@ -84,6 +82,8 @@ impl ModPath { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { + /// Type based path like `::foo` + type_anchor: Option>, mod_path: ModPath, /// Invariant: the same len as self.path.segments generic_args: Vec>>, @@ -126,7 +126,7 @@ impl Path { /// Converts an `ast::NameRef` into a single-identifier `Path`. pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path { - Path { mod_path: name_ref.as_name().into(), generic_args: vec![None] } + Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } } /// `true` if this path is just a standalone `self` @@ -138,6 +138,10 @@ impl Path { &self.mod_path.kind } + pub fn type_anchor(&self) -> Option<&TypeRef> { + self.type_anchor.as_ref().map(|it| &**it) + } + pub fn segments(&self) -> PathSegments<'_> { PathSegments { segments: self.mod_path.segments.as_slice(), @@ -154,6 +158,7 @@ impl Path { return None; } let res = Path { + type_anchor: self.type_anchor.clone(), mod_path: ModPath { kind: self.mod_path.kind.clone(), segments: self.mod_path.segments[..self.mod_path.segments.len() - 1].to_vec(), @@ -226,6 +231,7 @@ impl GenericArgs { impl From for Path { fn from(name: Name) -> Path { Path { + type_anchor: None, mod_path: ModPath::from_simple_segments(PathKind::Plain, iter::once(name)), generic_args: vec![None], } diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs index c71b52d898..62aafd508e 100644 --- a/crates/ra_hir_def/src/path/lower.rs +++ b/crates/ra_hir_def/src/path/lower.rs @@ -22,6 +22,7 @@ pub(super) use lower_use::lower_use_tree; /// It correctly handles `$crate` based path from macro call. pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option { let mut kind = PathKind::Plain; + let mut type_anchor = None; let mut segments = Vec::new(); let mut generic_args = Vec::new(); loop { @@ -63,7 +64,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option match trait_ref { // ::foo None => { - kind = PathKind::Type(Box::new(self_type)); + type_anchor = Some(Box::new(self_type)); + kind = PathKind::Plain; } // >::Foo desugars to Trait::Foo Some(trait_ref) => { @@ -111,7 +113,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option segments.reverse(); generic_args.reverse(); let mod_path = ModPath { kind, segments }; - return Some(Path { mod_path, generic_args }); + return Some(Path { type_anchor, mod_path, generic_args }); fn qualifier(path: &ast::Path) -> Option { if let Some(q) = path.qualifier() { diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 3bae0ca6c2..402a89386b 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -3,7 +3,7 @@ use std::iter; use hir_def::{ - path::{Path, PathKind, PathSegment}, + path::{Path, PathSegment}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, AssocItemId, ContainerId, Lookup, }; @@ -32,7 +32,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { path: &Path, id: ExprOrPatId, ) -> Option { - let (value, self_subst) = if let PathKind::Type(type_ref) = path.kind() { + let (value, self_subst) = if let Some(type_ref) = path.type_anchor() { if path.segments().is_empty() { // This can't actually happen syntax-wise return None; diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index a4ddfc8efb..2b84309d7a 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -11,7 +11,7 @@ use std::sync::Arc; use hir_def::{ builtin_type::BuiltinType, generics::WherePredicate, - path::{GenericArg, Path, PathKind, PathSegment, PathSegments}, + path::{GenericArg, Path, PathSegment, PathSegments}, resolver::{HasResolver, Resolver, TypeNs}, type_ref::{TypeBound, TypeRef}, AdtId, ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, HasModule, ImplId, @@ -101,7 +101,7 @@ impl Ty { TypeRef::Path(path) => path, _ => return None, }; - if let PathKind::Type(_) = path.kind() { + if path.type_anchor().is_some() { return None; } if path.segments().len() > 1 { @@ -202,7 +202,7 @@ impl Ty { pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { // Resolve the path (in type namespace) - if let PathKind::Type(type_ref) = path.kind() { + if let Some(type_ref) = path.type_anchor() { let ty = Ty::from_hir(db, resolver, &type_ref); return Ty::from_type_relative_path(db, resolver, ty, path.segments()); } From d33fc26e05c573f536e02afbffc354fa4f4a35f3 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:42:49 +0100 Subject: [PATCH 214/312] Touch up docs --- crates/ra_hir_def/src/path.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 1e2da6b481..3fb0955d18 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -82,7 +82,8 @@ impl ModPath { #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Path { - /// Type based path like `::foo` + /// Type based path like `::foo`. + /// Note that paths like `::foo` are desugard to `Trait::::foo`. type_anchor: Option>, mod_path: ModPath, /// Invariant: the same len as self.path.segments From afdeacf3c126b3e19bd1e50a912fee2b3f2d4aa9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 18 Dec 2019 17:52:52 +0100 Subject: [PATCH 215/312] Remove dead code --- crates/ra_hir_def/src/path.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3fb0955d18..7302cf0f18 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -130,11 +130,6 @@ impl Path { Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } } - /// `true` if this path is just a standalone `self` - pub fn is_self(&self) -> bool { - self.mod_path.is_self() - } - pub fn kind(&self) -> &PathKind { &self.mod_path.kind } From dddee23f43a0e1939124a607ba534e69a810843a Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 19 Dec 2019 12:45:07 +0800 Subject: [PATCH 216/312] Add std::ops::Index support for infering --- crates/ra_hir_def/src/path.rs | 1 + crates/ra_hir_expand/src/name.rs | 1 + crates/ra_hir_ty/src/infer.rs | 22 ++++++++++++++++++- crates/ra_hir_ty/src/infer/expr.rs | 12 +++++++---- crates/ra_hir_ty/src/tests/traits.rs | 32 ++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 3b26e8337f..9e37ac4166 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -254,6 +254,7 @@ macro_rules! __known_path { (std::ops::Try) => {}; (std::ops::Neg) => {}; (std::ops::Not) => {}; + (std::ops::Index) => {}; ($path:path) => { compile_error!("Please register your known path in the path module") }; diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 59d8214fde..fd02ffa4e1 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -161,6 +161,7 @@ pub mod known { Range, Neg, Not, + Index, // Builtin macros file, column, diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 98ba05fc27..14bfdde3dd 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -363,14 +363,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option) -> Ty { + self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[]) + } + + fn resolve_associated_type_with_params( + &mut self, + inner_ty: Ty, + assoc_ty: Option, + params: &[Ty], + ) -> Ty { match assoc_ty { Some(res_assoc_ty) => { let ty = self.table.new_type_var(); + let mut builder = Substs::builder(1 + params.len()).push(inner_ty); + for ty in params { + builder = builder.push(ty.clone()); + } + let projection = ProjectionPredicate { ty: ty.clone(), projection_ty: ProjectionTy { associated_ty: res_assoc_ty, - parameters: Substs::single(inner_ty), + parameters: builder.build(), }, }; self.obligations.push(Obligation::Projection(projection)); @@ -517,6 +531,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { let struct_ = self.resolver.resolve_known_struct(self.db, &path)?; Some(struct_.into()) } + + fn resolve_ops_index_output(&self) -> Option { + let path = path![std::ops::Index]; + let trait_ = self.resolver.resolve_known_trait(self.db, &path)?; + self.db.trait_data(trait_).associated_type_by_name(&name![Output]) + } } /// The kinds of placeholders we need during type inference. There's separate diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 924ad3e813..011c6c5c6a 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -422,10 +422,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } Expr::Index { base, index } => { - let _base_ty = self.infer_expr_inner(*base, &Expectation::none()); - let _index_ty = self.infer_expr(*index, &Expectation::none()); - // FIXME: use `std::ops::Index::Output` to figure out the real return type - Ty::Unknown + let base_ty = self.infer_expr_inner(*base, &Expectation::none()); + let index_ty = self.infer_expr(*index, &Expectation::none()); + + self.resolve_associated_type_with_params( + base_ty, + self.resolve_ops_index_output(), + &[index_ty], + ) } Expr::Tuple { exprs } => { let mut tys = match &expected.ty { diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 802937cb02..2d92a5eec2 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -426,6 +426,38 @@ fn indexing_arrays() { ) } +#[test] +fn infer_ops_index() { + let (db, pos) = TestDB::with_position( + r#" +//- /main.rs crate:main deps:std + +struct Bar; +struct Foo; + +impl std::ops::Index for Bar { + type Output = Foo; +} + +fn test() { + let a = Bar; + let b = a[1]; + b<|>; +} + +//- /std.rs crate:std + +#[prelude_import] use ops::*; +mod ops { + pub trait Index { + type Output; + } +} +"#, + ); + assert_eq!("Foo", type_at_pos(&db, pos)); +} + #[test] fn deref_trait() { let t = type_at( From 14c167a9f6da07024a5101ffa04bc2f79ce64353 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 8 Dec 2019 00:54:18 +0200 Subject: [PATCH 217/312] Omit default parameter types --- crates/ra_hir/src/lib.rs | 5 +- crates/ra_hir_ty/src/display.rs | 21 +++-- crates/ra_hir_ty/src/lib.rs | 33 ++++++- crates/ra_ide/src/inlay_hints.rs | 90 +++++++++++++++---- crates/ra_ide/src/lib.rs | 7 +- crates/ra_lsp_server/src/config.rs | 2 + crates/ra_lsp_server/src/main_loop.rs | 1 + .../ra_lsp_server/src/main_loop/handlers.rs | 6 +- crates/ra_lsp_server/src/world.rs | 1 + editors/code/package.json | 5 ++ editors/code/src/config.ts | 6 ++ editors/code/src/server.ts | 2 + 12 files changed, 150 insertions(+), 29 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 2e52a1f5c0..e9ca548ca4 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -60,4 +60,7 @@ pub use hir_def::{ pub use hir_expand::{ name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; -pub use hir_ty::{display::HirDisplay, CallableDef}; +pub use hir_ty::{ + display::{HirDisplay, TruncateOptions}, + CallableDef, +}; diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index 9bb3ece6c8..9176c0629a 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs @@ -9,7 +9,7 @@ pub struct HirFormatter<'a, 'b, DB> { fmt: &'a mut fmt::Formatter<'b>, buf: String, curr_size: usize, - max_size: Option, + truncate_options: Option<&'a TruncateOptions>, } pub trait HirDisplay { @@ -25,12 +25,12 @@ pub trait HirDisplay { fn display_truncated<'a, DB>( &'a self, db: &'a DB, - max_size: Option, + truncate_options: &'a TruncateOptions, ) -> HirDisplayWrapper<'a, DB, Self> where Self: Sized, { - HirDisplayWrapper(db, self, max_size) + HirDisplayWrapper(db, self, Some(truncate_options)) } } @@ -66,15 +66,24 @@ where } pub fn should_truncate(&self) -> bool { - if let Some(max_size) = self.max_size { + if let Some(max_size) = self.truncate_options.and_then(|options| options.max_length) { self.curr_size >= max_size } else { false } } + + pub fn should_display_default_types(&self) -> bool { + self.truncate_options.map(|options| options.show_default_types).unwrap_or(true) + } } -pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option); +pub struct TruncateOptions { + pub max_length: Option, + pub show_default_types: bool, +} + +pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<&'a TruncateOptions>); impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> where @@ -87,7 +96,7 @@ where fmt: f, buf: String::with_capacity(20), curr_size: 0, - max_size: self.2, + truncate_options: self.2, }) } } diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 3ad913e55e..7ca9e6b8a7 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -906,7 +906,38 @@ impl HirDisplay for ApplicationTy { write!(f, "{}", name)?; if self.parameters.len() > 0 { write!(f, "<")?; - f.write_joined(&*self.parameters.0, ", ")?; + + let mut non_default_parameters = Vec::with_capacity(self.parameters.len()); + let parameters_to_write = if f.should_display_default_types() { + self.parameters.0.as_ref() + } else { + match self + .ctor + .as_generic_def() + .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) + .filter(|defaults| !defaults.is_empty()) + { + Option::None => self.parameters.0.as_ref(), + Option::Some(default_parameters) => { + for (i, parameter) in self.parameters.into_iter().enumerate() { + match (parameter, default_parameters.get(i)) { + (&Ty::Unknown, _) | (_, None) => { + non_default_parameters.push(parameter.clone()) + } + (_, Some(default_parameter)) + if parameter != default_parameter => + { + non_default_parameters.push(parameter.clone()) + } + _ => (), + } + } + &non_default_parameters + } + } + }; + + f.write_joined(parameters_to_write, ", ")?; write!(f, ">")?; } } diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3730121afe..8674912a62 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use crate::{db::RootDatabase, FileId}; -use hir::{HirDisplay, SourceAnalyzer}; +use hir::{HirDisplay, SourceAnalyzer, TruncateOptions}; use ra_syntax::{ ast::{self, AstNode, TypeAscriptionOwner}, match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, @@ -23,11 +23,11 @@ pub(crate) fn inlay_hints( db: &RootDatabase, file_id: FileId, file: &SourceFile, - max_inlay_hint_length: Option, + truncate_options: &TruncateOptions, ) -> Vec { file.syntax() .descendants() - .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) + .map(|node| get_inlay_hints(db, file_id, &node, truncate_options).unwrap_or_default()) .flatten() .collect() } @@ -36,7 +36,7 @@ fn get_inlay_hints( db: &RootDatabase, file_id: FileId, node: &SyntaxNode, - max_inlay_hint_length: Option, + truncate_options: &TruncateOptions, ) -> Option> { let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None); match_ast! { @@ -46,7 +46,7 @@ fn get_inlay_hints( return None; } let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) + Some(get_pat_type_hints(db, &analyzer, pat, false, truncate_options)) }, ast::LambdaExpr(it) => { it.param_list().map(|param_list| { @@ -54,22 +54,22 @@ fn get_inlay_hints( .params() .filter(|closure_param| closure_param.ascribed_type().is_none()) .filter_map(|closure_param| closure_param.pat()) - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, truncate_options)) .flatten() .collect() }) }, ast::ForExpr(it) => { let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) + Some(get_pat_type_hints(db, &analyzer, pat, false, truncate_options)) }, ast::IfExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) + Some(get_pat_type_hints(db, &analyzer, pat, true, truncate_options)) }, ast::WhileExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) + Some(get_pat_type_hints(db, &analyzer, pat, true, truncate_options)) }, ast::MatchArmList(it) => { Some( @@ -77,7 +77,7 @@ fn get_inlay_hints( .arms() .map(|match_arm| match_arm.pats()) .flatten() - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, truncate_options)) .flatten() .collect(), ) @@ -92,7 +92,7 @@ fn get_pat_type_hints( analyzer: &SourceAnalyzer, root_pat: ast::Pat, skip_root_pat_hint: bool, - max_inlay_hint_length: Option, + truncate_options: &TruncateOptions, ) -> Vec { let original_pat = &root_pat.clone(); @@ -109,7 +109,7 @@ fn get_pat_type_hints( .map(|(range, pat_type)| InlayHint { range, kind: InlayKind::TypeHint, - label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(), + label: pat_type.display_truncated(db, truncate_options).to_string().into(), }) .collect() } @@ -159,6 +159,58 @@ mod tests { use crate::mock_analysis::single_file; + #[test] + fn default_generic_types_disabled() { + let (analysis, file_id) = single_file( + r#" +struct Test { +k: K, + t: T, +} + +fn main() { + let zz = Test { t: 23, k: 33 }; +}"#, + ); + + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, false).unwrap(), @r###" + [ + InlayHint { + range: [65; 67), + kind: TypeHint, + label: "Test", + }, + ] + "### + ); + } + + #[test] + fn default_generic_types_enabled() { + let (analysis, file_id) = single_file( + r#" +struct Test { + k: K, + t: T, +} + +fn main() { + let zz = Test { t: 23, k: 33 }; +}"#, + ); + + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + [ + InlayHint { + range: [69; 71), + kind: TypeHint, + label: "Test", + }, + ] + "### + ); + } + #[test] fn let_statement() { let (analysis, file_id) = single_file( @@ -199,7 +251,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [193; 197), @@ -273,7 +325,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -302,7 +354,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -350,7 +402,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -413,7 +465,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -476,7 +528,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" [ InlayHint { range: [311; 315), @@ -518,7 +570,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8), true).unwrap(), @r###" [ InlayHint { range: [74; 75), diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 779a81b2c0..c3244a8dd5 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -348,9 +348,14 @@ impl Analysis { &self, file_id: FileId, max_inlay_hint_length: Option, + show_default_types_in_inlay_hints: bool, ) -> Cancelable> { + let truncate_options = hir::TruncateOptions { + max_length: max_inlay_hint_length, + show_default_types: show_default_types_in_inlay_hints, + }; self.with_db(|db| { - inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), max_inlay_hint_length) + inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), &truncate_options) }) } diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index 67942aa414..a916c5fd60 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs @@ -31,6 +31,7 @@ pub struct ServerConfig { pub lru_capacity: Option, pub max_inlay_hint_length: Option, + pub show_default_types_in_inlay_hints: bool, /// For internal usage to make integrated tests faster. #[serde(deserialize_with = "nullable_bool_true")] @@ -51,6 +52,7 @@ impl Default for ServerConfig { use_client_watching: false, lru_capacity: None, max_inlay_hint_length: None, + show_default_types_in_inlay_hints: false, with_sysroot: true, feature_flags: FxHashMap::default(), cargo_features: Default::default(), diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 965e7c53c1..01fde3b2d0 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -125,6 +125,7 @@ pub fn main_loop( .and_then(|it| it.line_folding_only) .unwrap_or(false), max_inlay_hint_length: config.max_inlay_hint_length, + show_default_types_in_inlay_hints: config.show_default_types_in_inlay_hints, } }; diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5b64b27cd2..9069d1f1dc 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -895,7 +895,11 @@ pub fn handle_inlay_hints( let analysis = world.analysis(); let line_index = analysis.file_line_index(file_id)?; Ok(analysis - .inlay_hints(file_id, world.options.max_inlay_hint_length)? + .inlay_hints( + file_id, + world.options.max_inlay_hint_length, + world.options.show_default_types_in_inlay_hints, + )? .into_iter() .map(|api_type| InlayHint { label: api_type.label.to_string(), diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 16cc11e8ce..0b6eefcbc7 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -31,6 +31,7 @@ pub struct Options { pub supports_location_link: bool, pub line_folding_only: bool, pub max_inlay_hint_length: Option, + pub show_default_types_in_inlay_hints: bool, } /// `WorldState` is the primary mutable state of the language server diff --git a/editors/code/package.json b/editors/code/package.json index f2e8e647e3..bda0002b76 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -285,6 +285,11 @@ "default": 20, "description": "Maximum length for inlay hints" }, + "rust-analyzer.showDefaultTypesInInlayHints": { + "type": "boolean", + "default": false, + "description": "Display default types in inlay hints" + }, "rust-analyzer.cargoFeatures.noDefaultFeatures": { "type": "boolean", "default": false, diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index e131f09df6..26bf30e7f5 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -30,6 +30,7 @@ export class Config { public lruCapacity: null | number = null; public displayInlayHints = true; public maxInlayHintLength: null | number = null; + public showDefaultTypesInInlayHints = false; public excludeGlobs = []; public useClientWatching = true; public featureFlags = {}; @@ -153,6 +154,11 @@ export class Config { 'maxInlayHintLength', ) as number; } + if (config.has('showDefaultTypesInInlayHints')) { + this.showDefaultTypesInInlayHints = config.get( + 'showDefaultTypesInInlayHints', + ) as boolean; + } if (config.has('excludeGlobs')) { this.excludeGlobs = config.get('excludeGlobs') || []; } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index 5ace1d0fae..e7d1df943f 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -55,6 +55,8 @@ export class Server { publishDecorations: true, lruCapacity: Server.config.lruCapacity, maxInlayHintLength: Server.config.maxInlayHintLength, + showDefaultTypesInInlayHints: + Server.config.showDefaultTypesInInlayHints, excludeGlobs: Server.config.excludeGlobs, useClientWatching: Server.config.useClientWatching, featureFlags: Server.config.featureFlags, From 3969c7c85373554fcd80aee359cd0def14f7a528 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 19 Dec 2019 12:45:00 +0200 Subject: [PATCH 218/312] Ensure hover shows full type declaration --- crates/ra_ide/src/hover.rs | 17 +++++++++++++++++ crates/ra_ide/src/inlay_hints.rs | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 51e3201282..7d2f160e7d 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -424,6 +424,23 @@ mod tests { ); } + #[test] + fn hover_default_generic_type() { + check_hover_result( + r#" +//- /main.rs +struct Test { + k: K, + t: T, +} + +fn main() { + let zz<|> = Test { t: 23, k: 33 }; +}"#, + &["Test"], + ); + } + #[test] fn hover_some() { let (analysis, position) = single_file_with_position( diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 8674912a62..319ac00480 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -164,7 +164,7 @@ mod tests { let (analysis, file_id) = single_file( r#" struct Test { -k: K, + k: K, t: T, } @@ -176,7 +176,7 @@ fn main() { assert_debug_snapshot!(analysis.inlay_hints(file_id, None, false).unwrap(), @r###" [ InlayHint { - range: [65; 67), + range: [69; 71), kind: TypeHint, label: "Test", }, From 5c3c2b869085a26187c0f7c7bcd4ee58bc1075a9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 14:43:19 +0100 Subject: [PATCH 219/312] Fix parsing of interpolated expressions --- crates/ra_mbe/src/tests.rs | 18 ++++++++++++++++++ .../ra_parser/src/grammar/expressions/atom.rs | 1 + 2 files changed, 19 insertions(+) diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index ff225f0db2..b5a10a9d2f 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -1450,6 +1450,24 @@ macro_rules! delegate_impl { ); } +#[test] +fn expr_interpolation() { + let rules = create_rules( + r#" + macro_rules! id { + ($expr:expr) => { + map($expr) + } + } + "#, + ); + + let expanded = expand(&rules, "id!(x + foo);"); + let expanded = + token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node(); + assert_eq!(expanded.to_string(), "map(x+foo)"); +} + pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); let macro_definition = diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 09f0a2d98a..6f5545a83a 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -43,6 +43,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = T!['('], T!['{'], T!['['], + L_DOLLAR, T![|], T![move], T![box], From 4fb25ef43bd96da94467ffa4de8fbf0af82b28d1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 19 Dec 2019 16:18:09 +0200 Subject: [PATCH 220/312] Do not add any new configuration parameters --- crates/ra_ide/src/inlay_hints.rs | 44 ++++--------------- crates/ra_ide/src/lib.rs | 7 +-- crates/ra_lsp_server/src/config.rs | 2 - crates/ra_lsp_server/src/main_loop.rs | 1 - .../ra_lsp_server/src/main_loop/handlers.rs | 6 +-- crates/ra_lsp_server/src/world.rs | 1 - editors/code/src/config.ts | 6 --- editors/code/src/server.ts | 2 - 8 files changed, 12 insertions(+), 57 deletions(-) diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 319ac00480..4c5004f67d 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -160,7 +160,7 @@ mod tests { use crate::mock_analysis::single_file; #[test] - fn default_generic_types_disabled() { + fn default_generic_types_should_not_be_displayed() { let (analysis, file_id) = single_file( r#" struct Test { @@ -173,7 +173,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, false).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [69; 71), @@ -185,32 +185,6 @@ fn main() { ); } - #[test] - fn default_generic_types_enabled() { - let (analysis, file_id) = single_file( - r#" -struct Test { - k: K, - t: T, -} - -fn main() { - let zz = Test { t: 23, k: 33 }; -}"#, - ); - - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" - [ - InlayHint { - range: [69; 71), - kind: TypeHint, - label: "Test", - }, - ] - "### - ); - } - #[test] fn let_statement() { let (analysis, file_id) = single_file( @@ -251,7 +225,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [193; 197), @@ -325,7 +299,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -354,7 +328,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [21; 30), @@ -402,7 +376,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -465,7 +439,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [166; 170), @@ -528,7 +502,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, None, true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###" [ InlayHint { range: [311; 315), @@ -570,7 +544,7 @@ fn main() { }"#, ); - assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8), true).unwrap(), @r###" + assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###" [ InlayHint { range: [74; 75), diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index c3244a8dd5..875919e609 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -348,12 +348,9 @@ impl Analysis { &self, file_id: FileId, max_inlay_hint_length: Option, - show_default_types_in_inlay_hints: bool, ) -> Cancelable> { - let truncate_options = hir::TruncateOptions { - max_length: max_inlay_hint_length, - show_default_types: show_default_types_in_inlay_hints, - }; + let truncate_options = + hir::TruncateOptions { max_length: max_inlay_hint_length, show_default_types: false }; self.with_db(|db| { inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), &truncate_options) }) diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs index a916c5fd60..67942aa414 100644 --- a/crates/ra_lsp_server/src/config.rs +++ b/crates/ra_lsp_server/src/config.rs @@ -31,7 +31,6 @@ pub struct ServerConfig { pub lru_capacity: Option, pub max_inlay_hint_length: Option, - pub show_default_types_in_inlay_hints: bool, /// For internal usage to make integrated tests faster. #[serde(deserialize_with = "nullable_bool_true")] @@ -52,7 +51,6 @@ impl Default for ServerConfig { use_client_watching: false, lru_capacity: None, max_inlay_hint_length: None, - show_default_types_in_inlay_hints: false, with_sysroot: true, feature_flags: FxHashMap::default(), cargo_features: Default::default(), diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 01fde3b2d0..965e7c53c1 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -125,7 +125,6 @@ pub fn main_loop( .and_then(|it| it.line_folding_only) .unwrap_or(false), max_inlay_hint_length: config.max_inlay_hint_length, - show_default_types_in_inlay_hints: config.show_default_types_in_inlay_hints, } }; diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 9069d1f1dc..5b64b27cd2 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -895,11 +895,7 @@ pub fn handle_inlay_hints( let analysis = world.analysis(); let line_index = analysis.file_line_index(file_id)?; Ok(analysis - .inlay_hints( - file_id, - world.options.max_inlay_hint_length, - world.options.show_default_types_in_inlay_hints, - )? + .inlay_hints(file_id, world.options.max_inlay_hint_length)? .into_iter() .map(|api_type| InlayHint { label: api_type.label.to_string(), diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 0b6eefcbc7..16cc11e8ce 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -31,7 +31,6 @@ pub struct Options { pub supports_location_link: bool, pub line_folding_only: bool, pub max_inlay_hint_length: Option, - pub show_default_types_in_inlay_hints: bool, } /// `WorldState` is the primary mutable state of the language server diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts index 26bf30e7f5..e131f09df6 100644 --- a/editors/code/src/config.ts +++ b/editors/code/src/config.ts @@ -30,7 +30,6 @@ export class Config { public lruCapacity: null | number = null; public displayInlayHints = true; public maxInlayHintLength: null | number = null; - public showDefaultTypesInInlayHints = false; public excludeGlobs = []; public useClientWatching = true; public featureFlags = {}; @@ -154,11 +153,6 @@ export class Config { 'maxInlayHintLength', ) as number; } - if (config.has('showDefaultTypesInInlayHints')) { - this.showDefaultTypesInInlayHints = config.get( - 'showDefaultTypesInInlayHints', - ) as boolean; - } if (config.has('excludeGlobs')) { this.excludeGlobs = config.get('excludeGlobs') || []; } diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts index e7d1df943f..5ace1d0fae 100644 --- a/editors/code/src/server.ts +++ b/editors/code/src/server.ts @@ -55,8 +55,6 @@ export class Server { publishDecorations: true, lruCapacity: Server.config.lruCapacity, maxInlayHintLength: Server.config.maxInlayHintLength, - showDefaultTypesInInlayHints: - Server.config.showDefaultTypesInInlayHints, excludeGlobs: Server.config.excludeGlobs, useClientWatching: Server.config.useClientWatching, featureFlags: Server.config.featureFlags, From b61ad6a96430f82e9724c1831d7402705145750e Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Thu, 19 Dec 2019 22:28:52 +0800 Subject: [PATCH 221/312] Use build_for_def --- crates/ra_hir_ty/src/infer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 14bfdde3dd..98baeed6f6 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -375,7 +375,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match assoc_ty { Some(res_assoc_ty) => { let ty = self.table.new_type_var(); - let mut builder = Substs::builder(1 + params.len()).push(inner_ty); + let mut builder = Substs::build_for_def(self.db, res_assoc_ty).push(inner_ty); for ty in params { builder = builder.push(ty.clone()); } From 4ed78f80f4cc3cf32681fce6722293da6c8df76d Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 19 Dec 2019 16:43:41 +0200 Subject: [PATCH 222/312] Remove TruncateOptions struct --- crates/ra_hir/src/lib.rs | 5 +---- crates/ra_hir_ty/src/display.rs | 23 ++++++++++------------- crates/ra_ide/src/inlay_hints.rs | 24 ++++++++++++------------ crates/ra_ide/src/lib.rs | 4 +--- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e9ca548ca4..2e52a1f5c0 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -60,7 +60,4 @@ pub use hir_def::{ pub use hir_expand::{ name::Name, HirFileId, InFile, MacroCallId, MacroCallLoc, MacroDefId, MacroFile, Origin, }; -pub use hir_ty::{ - display::{HirDisplay, TruncateOptions}, - CallableDef, -}; +pub use hir_ty::{display::HirDisplay, CallableDef}; diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs index 9176c0629a..dcca1bace6 100644 --- a/crates/ra_hir_ty/src/display.rs +++ b/crates/ra_hir_ty/src/display.rs @@ -9,7 +9,8 @@ pub struct HirFormatter<'a, 'b, DB> { fmt: &'a mut fmt::Formatter<'b>, buf: String, curr_size: usize, - truncate_options: Option<&'a TruncateOptions>, + max_size: Option, + should_display_default_types: bool, } pub trait HirDisplay { @@ -19,18 +20,18 @@ pub trait HirDisplay { where Self: Sized, { - HirDisplayWrapper(db, self, None) + HirDisplayWrapper(db, self, None, true) } fn display_truncated<'a, DB>( &'a self, db: &'a DB, - truncate_options: &'a TruncateOptions, + max_size: Option, ) -> HirDisplayWrapper<'a, DB, Self> where Self: Sized, { - HirDisplayWrapper(db, self, Some(truncate_options)) + HirDisplayWrapper(db, self, max_size, false) } } @@ -66,7 +67,7 @@ where } pub fn should_truncate(&self) -> bool { - if let Some(max_size) = self.truncate_options.and_then(|options| options.max_length) { + if let Some(max_size) = self.max_size { self.curr_size >= max_size } else { false @@ -74,16 +75,11 @@ where } pub fn should_display_default_types(&self) -> bool { - self.truncate_options.map(|options| options.show_default_types).unwrap_or(true) + self.should_display_default_types } } -pub struct TruncateOptions { - pub max_length: Option, - pub show_default_types: bool, -} - -pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<&'a TruncateOptions>); +pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option, bool); impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> where @@ -96,7 +92,8 @@ where fmt: f, buf: String::with_capacity(20), curr_size: 0, - truncate_options: self.2, + max_size: self.2, + should_display_default_types: self.3, }) } } diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 4c5004f67d..3154df4572 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -1,7 +1,7 @@ //! FIXME: write short doc here use crate::{db::RootDatabase, FileId}; -use hir::{HirDisplay, SourceAnalyzer, TruncateOptions}; +use hir::{HirDisplay, SourceAnalyzer}; use ra_syntax::{ ast::{self, AstNode, TypeAscriptionOwner}, match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, @@ -23,11 +23,11 @@ pub(crate) fn inlay_hints( db: &RootDatabase, file_id: FileId, file: &SourceFile, - truncate_options: &TruncateOptions, + max_inlay_hint_length: Option, ) -> Vec { file.syntax() .descendants() - .map(|node| get_inlay_hints(db, file_id, &node, truncate_options).unwrap_or_default()) + .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) .flatten() .collect() } @@ -36,7 +36,7 @@ fn get_inlay_hints( db: &RootDatabase, file_id: FileId, node: &SyntaxNode, - truncate_options: &TruncateOptions, + max_inlay_hint_length: Option, ) -> Option> { let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None); match_ast! { @@ -46,7 +46,7 @@ fn get_inlay_hints( return None; } let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, truncate_options)) + Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) }, ast::LambdaExpr(it) => { it.param_list().map(|param_list| { @@ -54,22 +54,22 @@ fn get_inlay_hints( .params() .filter(|closure_param| closure_param.ascribed_type().is_none()) .filter_map(|closure_param| closure_param.pat()) - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, truncate_options)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length)) .flatten() .collect() }) }, ast::ForExpr(it) => { let pat = it.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, false, truncate_options)) + Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length)) }, ast::IfExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, truncate_options)) + Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) }, ast::WhileExpr(it) => { let pat = it.condition()?.pat()?; - Some(get_pat_type_hints(db, &analyzer, pat, true, truncate_options)) + Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length)) }, ast::MatchArmList(it) => { Some( @@ -77,7 +77,7 @@ fn get_inlay_hints( .arms() .map(|match_arm| match_arm.pats()) .flatten() - .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, truncate_options)) + .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length)) .flatten() .collect(), ) @@ -92,7 +92,7 @@ fn get_pat_type_hints( analyzer: &SourceAnalyzer, root_pat: ast::Pat, skip_root_pat_hint: bool, - truncate_options: &TruncateOptions, + max_inlay_hint_length: Option, ) -> Vec { let original_pat = &root_pat.clone(); @@ -109,7 +109,7 @@ fn get_pat_type_hints( .map(|(range, pat_type)| InlayHint { range, kind: InlayKind::TypeHint, - label: pat_type.display_truncated(db, truncate_options).to_string().into(), + label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(), }) .collect() } diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 875919e609..779a81b2c0 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs @@ -349,10 +349,8 @@ impl Analysis { file_id: FileId, max_inlay_hint_length: Option, ) -> Cancelable> { - let truncate_options = - hir::TruncateOptions { max_length: max_inlay_hint_length, show_default_types: false }; self.with_db(|db| { - inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), &truncate_options) + inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), max_inlay_hint_length) }) } From f407ac2be332e474b25a10aaf3be145c85f4b60b Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 19 Dec 2019 16:47:09 +0200 Subject: [PATCH 223/312] Omit default types for hover pop-ups --- crates/ra_ide/src/hover.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 7d2f160e7d..a227bf546c 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -250,7 +250,7 @@ pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option { } else { return None; }; - Some(ty.display(db).to_string()) + Some(ty.display_truncated(db, None).to_string()) } #[cfg(test)] @@ -425,7 +425,7 @@ mod tests { } #[test] - fn hover_default_generic_type() { + fn hover_omits_default_generic_types() { check_hover_result( r#" //- /main.rs @@ -437,7 +437,7 @@ struct Test { fn main() { let zz<|> = Test { t: 23, k: 33 }; }"#, - &["Test"], + &["Test"], ); } From 6419d49f1d88600d4a480701285d4e33be5cd3f1 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Thu, 19 Dec 2019 17:11:07 +0200 Subject: [PATCH 224/312] Remove the setting change reminder --- editors/code/package.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/editors/code/package.json b/editors/code/package.json index bda0002b76..f2e8e647e3 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -285,11 +285,6 @@ "default": 20, "description": "Maximum length for inlay hints" }, - "rust-analyzer.showDefaultTypesInInlayHints": { - "type": "boolean", - "default": false, - "description": "Display default types in inlay hints" - }, "rust-analyzer.cargoFeatures.noDefaultFeatures": { "type": "boolean", "default": false, From 6edc54a1e6a48f6fe3191c549befe91674342d9a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 16:17:22 +0100 Subject: [PATCH 225/312] Refactor macro tests --- crates/ra_mbe/src/syntax_bridge.rs | 14 +- crates/ra_mbe/src/tests.rs | 685 ++++++++++++----------------- crates/ra_parser/src/lib.rs | 1 + 3 files changed, 293 insertions(+), 407 deletions(-) diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 2c60430d15..ea2cac069e 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -476,7 +476,7 @@ impl<'a> TreeSink for TtTreeSink<'a> { #[cfg(test)] mod tests { use super::*; - use crate::tests::{create_rules, expand}; + use crate::tests::parse_macro; use ra_parser::TokenSource; use ra_syntax::{ algo::{insert_children, InsertPosition}, @@ -485,7 +485,7 @@ mod tests { #[test] fn convert_tt_token_source() { - let rules = create_rules( + let expansion = parse_macro( r#" macro_rules! literals { ($i:ident) => { @@ -498,8 +498,8 @@ mod tests { } } "#, - ); - let expansion = expand(&rules, "literals!(foo);"); + ) + .expand_tt("literals!(foo);"); let tts = &[expansion.into()]; let buffer = tt::buffer::TokenBuffer::new(tts); let mut tt_src = SubtreeTokenSource::new(&buffer); @@ -527,7 +527,7 @@ mod tests { #[test] fn stmts_token_trees_to_expr_is_err() { - let rules = create_rules( + let expansion = parse_macro( r#" macro_rules! stmts { () => { @@ -538,8 +538,8 @@ mod tests { } } "#, - ); - let expansion = expand(&rules, "stmts!();"); + ) + .expand_tt("stmts!();"); assert!(token_tree_to_syntax_node(&expansion, FragmentKind::Expr).is_err()); } diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index b5a10a9d2f..e640d115b4 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs @@ -1,5 +1,7 @@ +use std::fmt::Write; + use ra_parser::FragmentKind; -use ra_syntax::{ast, AstNode, NodeOrToken, WalkEvent}; +use ra_syntax::{ast, AstNode, NodeOrToken, SyntaxKind::IDENT, SyntaxNode, WalkEvent, T}; use test_utils::assert_eq_text; use super::*; @@ -61,13 +63,14 @@ mod rule_parsing { #[test] fn test_token_id_shift() { - let macro_definition = r#" + let expansion = parse_macro( + r#" macro_rules! foobar { ($e:ident) => { foo bar $e } } -"#; - let rules = create_rules(macro_definition); - let expansion = expand(&rules, "foobar!(baz);"); +"#, + ) + .expand_tt("foobar!(baz);"); fn get_id(t: &tt::TokenTree) -> Option { if let tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) = t { @@ -90,22 +93,23 @@ macro_rules! foobar { #[test] fn test_token_map() { - use ra_parser::SyntaxKind::*; - use ra_syntax::T; - - let macro_definition = r#" + let expanded = parse_macro( + r#" macro_rules! foobar { ($e:ident) => { fn $e() {} } } -"#; - let rules = create_rules(macro_definition); - let (expansion, (token_map, content)) = expand_and_map(&rules, "foobar!(baz);"); +"#, + ) + .expand_tt("foobar!(baz);"); + + let (node, token_map) = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); + let content = node.syntax_node().to_string(); let get_text = |id, kind| -> String { content[token_map.range_by_token(id).unwrap().by_kind(kind).unwrap()].to_string() }; - assert_eq!(expansion.token_trees.len(), 4); + assert_eq!(expanded.token_trees.len(), 4); // {($e:ident) => { fn $e() {} }} // 012345 67 8 9 T12 3 @@ -116,7 +120,7 @@ macro_rules! foobar { #[test] fn test_convert_tt() { - let macro_definition = r#" + parse_macro(r#" macro_rules! impl_froms { ($e:ident: $($v:ident),*) => { $( @@ -128,24 +132,17 @@ macro_rules! impl_froms { )* } } -"#; - - let macro_invocation = r#" -impl_froms!(TokenTree: Leaf, Subtree); -"#; - - let rules = create_rules(macro_definition); - let expansion = expand(&rules, macro_invocation); - assert_eq!( - expansion.to_string(), - "impl From for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \ - impl From for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}" - ) +"#) + .assert_expand_tt( + "impl_froms!(TokenTree: Leaf, Subtree);", + "impl From for TokenTree {fn from (it : Leaf) -> TokenTree {TokenTree ::Leaf (it)}} \ + impl From for TokenTree {fn from (it : Subtree) -> TokenTree {TokenTree ::Subtree (it)}}" + ); } #[test] fn test_expr_order() { - let rules = create_rules( + let expanded = parse_macro( r#" macro_rules! foo { ($ i:expr) => { @@ -153,11 +150,10 @@ fn test_expr_order() { } } "#, - ); - let expanded = expand(&rules, "foo! { 1 + 1}"); - let tree = token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node(); + ) + .expand_items("foo! { 1 + 1}"); - let dump = format!("{:#?}", tree); + let dump = format!("{:#?}", expanded); assert_eq_text!( dump.trim(), r#"MACRO_ITEMS@[0; 15) @@ -189,7 +185,7 @@ fn test_expr_order() { #[test] fn test_fail_match_pattern_by_first_token() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ident) => ( @@ -203,16 +199,15 @@ fn test_fail_match_pattern_by_first_token() { ) } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { = bar }", "fn bar () {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { + Baz }", "struct Baz ;"); + ) + .assert_expand_items("foo! { foo }", "mod foo {}") + .assert_expand_items("foo! { = bar }", "fn bar () {}") + .assert_expand_items("foo! { + Baz }", "struct Baz ;"); } #[test] fn test_fail_match_pattern_by_last_token() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ident) => ( @@ -226,16 +221,15 @@ fn test_fail_match_pattern_by_last_token() { ) } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { bar = }", "fn bar () {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { Baz + }", "struct Baz ;"); + ) + .assert_expand_items("foo! { foo }", "mod foo {}") + .assert_expand_items("foo! { bar = }", "fn bar () {}") + .assert_expand_items("foo! { Baz + }", "struct Baz ;"); } #[test] fn test_fail_match_pattern_by_word_token() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ident) => ( @@ -249,16 +243,15 @@ fn test_fail_match_pattern_by_word_token() { ) } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "mod foo {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { spam bar }", "fn bar () {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { eggs Baz }", "struct Baz ;"); + ) + .assert_expand_items("foo! { foo }", "mod foo {}") + .assert_expand_items("foo! { spam bar }", "fn bar () {}") + .assert_expand_items("foo! { eggs Baz }", "struct Baz ;"); } #[test] fn test_match_group_pattern_by_separator_token() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:ident),*) => ($ ( @@ -273,16 +266,15 @@ fn test_match_group_pattern_by_separator_token() { ) } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "mod foo {} mod bar {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { foo# bar }", "fn foo () {} fn bar () {}"); - assert_expansion(MacroKind::Items, &rules, "foo! { Foo,# Bar }", "struct Foo ; struct Bar ;"); + ) + .assert_expand_items("foo! { foo, bar }", "mod foo {} mod bar {}") + .assert_expand_items("foo! { foo# bar }", "fn foo () {} fn bar () {}") + .assert_expand_items("foo! { Foo,# Bar }", "struct Foo ; struct Bar ;"); } #[test] fn test_match_group_pattern_with_multiple_defs() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:ident),*) => ( struct Bar { $ ( @@ -290,19 +282,13 @@ fn test_match_group_pattern_with_multiple_defs() { )*} ); } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, - "foo! { foo, bar }", - "struct Bar {fn foo {} fn bar {}}", - ); + ) + .assert_expand_items("foo! { foo, bar }", "struct Bar {fn foo {} fn bar {}}"); } #[test] fn test_match_group_pattern_with_multiple_statement() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:ident),*) => ( fn baz { $ ( @@ -310,14 +296,13 @@ fn test_match_group_pattern_with_multiple_statement() { )*} ); } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); + ) + .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); } #[test] fn test_match_group_pattern_with_multiple_statement_without_semi() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:ident),*) => ( fn baz { $ ( @@ -325,14 +310,13 @@ fn test_match_group_pattern_with_multiple_statement_without_semi() { );*} ); } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! { foo, bar }", "fn baz {foo () ;bar ()}"); + ) + .assert_expand_items("foo! { foo, bar }", "fn baz {foo () ;bar ()}"); } #[test] fn test_match_group_empty_fixed_token() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:ident)* #abc) => ( fn baz { $ ( @@ -340,69 +324,59 @@ fn test_match_group_empty_fixed_token() { )*} ); } "#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! {#abc}", "fn baz {}"); + ) + .assert_expand_items("foo! {#abc}", "fn baz {}"); } #[test] fn test_match_group_in_subtree() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { (fn $name:ident {$($i:ident)*} ) => ( fn $name() { $ ( $ i (); )*} ); }"#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}"); + ) + .assert_expand_items("foo! {fn baz {a b} }", "fn baz () {a () ; b () ;}"); } #[test] fn test_match_group_with_multichar_sep() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { (fn $name:ident {$($i:literal)*} ) => ( fn $name() -> bool { $($i)&&*} ); }"#, - ); - - assert_expansion( - MacroKind::Items, - &rules, - "foo! (fn baz {true true} );", - "fn baz () -> bool {true &&true}", - ); + ) + .assert_expand_items("foo! (fn baz {true true} );", "fn baz () -> bool {true &&true}"); } #[test] fn test_match_group_zero_match() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ( $($i:ident)* ) => (); }"#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! ();", ""); + ) + .assert_expand_items("foo! ();", ""); } #[test] fn test_match_group_in_group() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { { $( ( $($i:ident)* ) )* } => ( $( ( $($i)* ) )* ); }"#, - ); - - assert_expansion(MacroKind::Items, &rules, "foo! ( (a b) );", "(a b)"); + ) + .assert_expand_items("foo! ( (a b) );", "(a b)"); } #[test] fn test_expand_to_item_list() { - let rules = create_rules( + let tree = parse_macro( " macro_rules! structs { ($($i:ident),*) => { @@ -410,9 +384,8 @@ fn test_expand_to_item_list() { } } ", - ); - let expansion = expand(&rules, "structs!(Foo, Bar);"); - let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Items).unwrap().0.syntax_node(); + ) + .expand_items("structs!(Foo, Bar);"); assert_eq!( format!("{:#?}", tree).trim(), r#" @@ -469,7 +442,7 @@ fn test_expand_literals_to_token_tree() { unreachable!("It is not a literal"); } - let rules = create_rules( + let expansion = parse_macro( r#" macro_rules! literals { ($i:ident) => { @@ -482,8 +455,8 @@ fn test_expand_literals_to_token_tree() { } } "#, - ); - let expansion = expand(&rules, "literals!(foo);"); + ) + .expand_tt("literals!(foo);"); let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees; // [let] [a] [=] ['c'] [;] @@ -498,7 +471,7 @@ fn test_expand_literals_to_token_tree() { #[test] fn test_two_idents() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ident, $ j:ident) => { @@ -506,18 +479,13 @@ fn test_two_idents() { } } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, - "foo! { foo, bar }", - "fn foo () {let a = foo ; let b = bar ;}", - ); + ) + .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); } #[test] fn test_tt_to_stmts() { - let rules = create_rules( + let stmts = parse_macro( r#" macro_rules! foo { () => { @@ -527,11 +495,8 @@ fn test_tt_to_stmts() { } } "#, - ); - - let expanded = expand(&rules, "foo!{}"); - let stmts = - token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node(); + ) + .expand_statements("foo!{}"); assert_eq!( format!("{:#?}", stmts).trim(), @@ -571,7 +536,7 @@ fn test_tt_to_stmts() { #[test] fn test_match_literal() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ('(') => { @@ -579,8 +544,8 @@ fn test_match_literal() { } } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! ['('];", "fn foo () {}"); + ) + .assert_expand_items("foo! ['('];", "fn foo () {}"); } // The following tests are port from intellij-rust directly @@ -588,7 +553,7 @@ fn test_match_literal() { #[test] fn test_path() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:path) => { @@ -596,11 +561,9 @@ fn test_path() { } } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo ;}"); - assert_expansion( - MacroKind::Items, - &rules, + ) + .assert_expand_items("foo! { foo }", "fn foo () {let a = foo ;}") + .assert_expand_items( "foo! { bar::::baz:: }", "fn foo () {let a = bar ::< u8 >:: baz ::< u8 > ;}", ); @@ -608,7 +571,7 @@ fn test_path() { #[test] fn test_two_paths() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:path, $ j:path) => { @@ -616,18 +579,13 @@ fn test_two_paths() { } } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, - "foo! { foo, bar }", - "fn foo () {let a = foo ; let b = bar ;}", - ); + ) + .assert_expand_items("foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); } #[test] fn test_path_with_path() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:path) => { @@ -635,13 +593,13 @@ fn test_path_with_path() { } } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! { foo }", "fn foo () {let a = foo :: bar ;}"); + ) + .assert_expand_items("foo! { foo }", "fn foo () {let a = foo :: bar ;}"); } #[test] fn test_expr() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:expr) => { @@ -649,11 +607,8 @@ fn test_expr() { } } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, + ) + .assert_expand_items( "foo! { 2 + 2 * baz(3).quux() }", "fn bar () {2 + 2 * baz (3) . quux () ;}", ); @@ -661,7 +616,7 @@ fn test_expr() { #[test] fn test_last_expr() { - let rules = create_rules( + parse_macro( r#" macro_rules! vec { ($($item:expr),*) => { @@ -675,10 +630,8 @@ fn test_last_expr() { }; } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, + ) + .assert_expand_items( "vec!(1,2,3);", "{let mut v = Vec :: new () ; v . push (1) ; v . push (2) ; v . push (3) ; v}", ); @@ -686,7 +639,7 @@ fn test_last_expr() { #[test] fn test_ty() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ty) => ( @@ -694,18 +647,13 @@ fn test_ty() { ) } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, - "foo! { Baz }", - "fn bar () -> Baz < u8 > {unimplemented ! ()}", - ); + ) + .assert_expand_items("foo! { Baz }", "fn bar () -> Baz < u8 > {unimplemented ! ()}"); } #[test] fn test_ty_with_complex_type() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:ty) => ( @@ -713,20 +661,14 @@ fn test_ty_with_complex_type() { ) } "#, - ); - + ) // Reference lifetime struct with generic type - assert_expansion( - MacroKind::Items, - &rules, + .assert_expand_items( "foo! { &'a Baz }", "fn bar () -> & 'a Baz < u8 > {unimplemented ! ()}", - ); - + ) // extern "Rust" func type - assert_expansion( - MacroKind::Items, - &rules, + .assert_expand_items( r#"foo! { extern "Rust" fn() -> Ret }"#, r#"fn bar () -> extern "Rust" fn () -> Ret {unimplemented ! ()}"#, ); @@ -734,19 +676,19 @@ fn test_ty_with_complex_type() { #[test] fn test_pat_() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:pat) => { fn foo() { let $ i; } } } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! { (a, b) }", "fn foo () {let (a , b) ;}"); + ) + .assert_expand_items("foo! { (a, b) }", "fn foo () {let (a , b) ;}"); } #[test] fn test_stmt() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:stmt) => ( @@ -754,14 +696,14 @@ fn test_stmt() { ) } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! { 2 }", "fn bar () {2 ;}"); - assert_expansion(MacroKind::Items, &rules, "foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); + ) + .assert_expand_items("foo! { 2 }", "fn bar () {2 ;}") + .assert_expand_items("foo! { let a = 0 }", "fn bar () {let a = 0 ;}"); } #[test] fn test_single_item() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:item) => ( @@ -769,13 +711,13 @@ fn test_single_item() { ) } "#, - ); - assert_expansion(MacroKind::Items, &rules, "foo! {mod c {}}", "mod c {}"); + ) + .assert_expand_items("foo! {mod c {}}", "mod c {}"); } #[test] fn test_all_items() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ ($ i:item)*) => ($ ( @@ -783,10 +725,8 @@ fn test_all_items() { )*) } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, + ). + assert_expand_items( r#" foo! { extern crate a; @@ -810,19 +750,19 @@ fn test_all_items() { #[test] fn test_block() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:block) => { fn foo() $ i } } "#, - ); - assert_expansion(MacroKind::Stmts, &rules, "foo! { { 1; } }", "fn foo () {1 ;}"); + ) + .assert_expand_statements("foo! { { 1; } }", "fn foo () {1 ;}"); } #[test] fn test_meta() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:meta) => ( @@ -831,10 +771,8 @@ fn test_meta() { ) } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, + ) + .assert_expand_items( r#"foo! { cfg(target_os = "windows") }"#, r#"# [cfg (target_os = "windows")] fn bar () {}"#, ); @@ -842,7 +780,7 @@ fn test_meta() { #[test] fn test_meta_doc_comments() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($(#[$ i:meta])+) => ( @@ -851,10 +789,8 @@ fn test_meta_doc_comments() { ) } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, + ). + assert_expand_items( r#"foo! { /// Single Line Doc 1 /** @@ -867,69 +803,68 @@ fn test_meta_doc_comments() { #[test] fn test_tt_block() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ i:tt) => { fn foo() $ i } } "#, - ); - assert_expansion(MacroKind::Items, &rules, r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); + ) + .assert_expand_items(r#"foo! { { 1; } }"#, r#"fn foo () {1 ;}"#); } #[test] fn test_tt_group() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($($ i:tt)*) => { $($ i)* } } "#, - ); - assert_expansion(MacroKind::Items, &rules, r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); + ) + .assert_expand_items(r#"foo! { fn foo() {} }"#, r#"fn foo () {}"#); } #[test] fn test_lifetime() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ lt:lifetime) => { struct Ref<$ lt>{ s: &$ lt str } } } "#, - ); - assert_expansion(MacroKind::Items, &rules, r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); + ) + .assert_expand_items(r#"foo!{'a}"#, r#"struct Ref <'a > {s : &'a str}"#); } #[test] fn test_literal() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ type:ty $ lit:literal) => { const VALUE: $ type = $ lit;}; } "#, - ); - assert_expansion(MacroKind::Items, &rules, r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); + ) + .assert_expand_items(r#"foo!(u8 0);"#, r#"const VALUE : u8 = 0 ;"#); } #[test] fn test_vis() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($ vis:vis $ name:ident) => { $ vis fn $ name() {}}; } "#, - ); - assert_expansion(MacroKind::Items, &rules, r#"foo!(pub foo);"#, r#"pub fn foo () {}"#); - - // test optional casse - assert_expansion(MacroKind::Items, &rules, r#"foo!(foo);"#, r#"fn foo () {}"#); + ) + .assert_expand_items(r#"foo!(pub foo);"#, r#"pub fn foo () {}"#) + // test optional cases + .assert_expand_items(r#"foo!(foo);"#, r#"fn foo () {}"#); } #[test] fn test_inner_macro_rules() { - let rules = create_rules( + parse_macro( r#" macro_rules! foo { ($a:ident, $b:ident, $c:tt) => { @@ -945,10 +880,8 @@ macro_rules! foo { } } "#, - ); - assert_expansion( - MacroKind::Items, - &rules, + ). + assert_expand_items( r#"foo!(x,y, 1);"#, r#"macro_rules ! bar {($ bi : ident) => {fn $ bi () -> u8 {1}}} bar ! (x) ; fn y () -> u8 {1}"#, ); @@ -957,7 +890,7 @@ macro_rules! foo { // The following tests are based on real world situations #[test] fn test_vec() { - let rules = create_rules( + let fixture = parse_macro( r#" macro_rules! vec { ($($item:expr),*) => { @@ -972,16 +905,14 @@ fn test_vec() { } "#, ); - assert_expansion(MacroKind::Items, &rules, r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#); - assert_expansion( - MacroKind::Items, - &rules, - r#"vec![1u32,2];"#, - r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, - ); + fixture + .assert_expand_items(r#"vec!();"#, r#"{let mut v = Vec :: new () ; v}"#) + .assert_expand_items( + r#"vec![1u32,2];"#, + r#"{let mut v = Vec :: new () ; v . push (1u32) ; v . push (2) ; v}"#, + ); - let expansion = expand(&rules, r#"vec![1u32,2];"#); - let tree = token_tree_to_syntax_node(&expansion, FragmentKind::Expr).unwrap().0.syntax_node(); + let tree = fixture.expand_expr(r#"vec![1u32,2];"#); assert_eq!( format!("{:#?}", tree).trim(), @@ -1055,7 +986,7 @@ fn test_vec() { fn test_winapi_struct() { // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/macros.rs#L366 - let rules = create_rules( + parse_macro( r#" macro_rules! STRUCT { ($(#[$attrs:meta])* struct $name:ident { @@ -1077,17 +1008,19 @@ macro_rules! STRUCT { ); } "#, - ); + ). // from https://github.com/retep998/winapi-rs/blob/a7ef2bca086aae76cf6c4ce4c2552988ed9798ad/src/shared/d3d9caps.rs - assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, - "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); - assert_expansion(MacroKind::Items, &rules, r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, - "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}"); + assert_expand_items(r#"STRUCT!{struct D3DVSHADERCAPS2_0 {Caps: u8,}}"#, + "# [repr (C)] # [derive (Copy)] pub struct D3DVSHADERCAPS2_0 {pub Caps : u8 ,} impl Clone for D3DVSHADERCAPS2_0 {# [inline] fn clone (& self) -> D3DVSHADERCAPS2_0 {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DVSHADERCAPS2_0 {# [inline] fn default () -> D3DVSHADERCAPS2_0 {unsafe {$crate :: _core :: mem :: zeroed ()}}}" + ) + .assert_expand_items(r#"STRUCT!{#[cfg_attr(target_arch = "x86", repr(packed))] struct D3DCONTENTPROTECTIONCAPS {Caps : u8 ,}}"#, + "# [repr (C)] # [derive (Copy)] # [cfg_attr (target_arch = \"x86\" , repr (packed))] pub struct D3DCONTENTPROTECTIONCAPS {pub Caps : u8 ,} impl Clone for D3DCONTENTPROTECTIONCAPS {# [inline] fn clone (& self) -> D3DCONTENTPROTECTIONCAPS {* self}} # [cfg (feature = \"impl-default\")] impl Default for D3DCONTENTPROTECTIONCAPS {# [inline] fn default () -> D3DCONTENTPROTECTIONCAPS {unsafe {$crate :: _core :: mem :: zeroed ()}}}" + ); } #[test] fn test_int_base() { - let rules = create_rules( + parse_macro( r#" macro_rules! int_base { ($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => { @@ -1100,17 +1033,15 @@ macro_rules! int_base { } } "#, - ); - - assert_expansion(MacroKind::Items, &rules, r#" int_base!{Binary for isize as usize -> Binary}"#, + ).assert_expand_items(r#" int_base!{Binary for isize as usize -> Binary}"#, "# [stable (feature = \"rust1\" , since = \"1.0.0\")] impl fmt ::Binary for isize {fn fmt (& self , f : & mut fmt :: Formatter < \'_ >) -> fmt :: Result {Binary . fmt_int (* self as usize , f)}}" - ); + ); } #[test] fn test_generate_pattern_iterators() { // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/str/mod.rs - let rules = create_rules( + parse_macro( r#" macro_rules! generate_pattern_iterators { { double ended; with $(#[$common_stability_attribute:meta])*, @@ -1121,11 +1052,7 @@ macro_rules! generate_pattern_iterators { } } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, + ).assert_expand_items( r#"generate_pattern_iterators ! ( double ended ; with # [ stable ( feature = "rust1" , since = "1.0.0" ) ] , Split , RSplit , & 'a str );"#, "fn foo () {}", ); @@ -1134,7 +1061,7 @@ macro_rules! generate_pattern_iterators { #[test] fn test_impl_fn_for_zst() { // from https://github.com/rust-lang/rust/blob/5d20ff4d2718c820632b38c1e49d4de648a9810b/src/libcore/internal_macros.rs - let rules = create_rules( + parse_macro( r#" macro_rules! impl_fn_for_zst { { $( $( #[$attr: meta] )* @@ -1175,9 +1102,7 @@ $body: block; )+ } } "#, - ); - - assert_expansion(MacroKind::Items, &rules, r#" + ).assert_expand_items(r#" impl_fn_for_zst ! { # [ derive ( Clone ) ] struct CharEscapeDebugContinue impl Fn = | c : char | -> char :: EscapeDebug { @@ -1194,13 +1119,14 @@ impl_fn_for_zst ! { } ; } "#, - "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}"); + "# [derive (Clone)] struct CharEscapeDebugContinue ; impl Fn < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDebug {{c . escape_debug_ext (false)}}} impl FnMut < (char ,) > for CharEscapeDebugContinue {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDebugContinue {type Output = char :: EscapeDebug ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDebug {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeUnicode ; impl Fn < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeUnicode {{c . escape_unicode ()}}} impl FnMut < (char ,) > for CharEscapeUnicode {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeUnicode {type Output = char :: EscapeUnicode ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeUnicode {Fn :: call (& self , (c ,))}} # [derive (Clone)] struct CharEscapeDefault ; impl Fn < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call (& self , (c ,) : (char ,)) -> char :: EscapeDefault {{c . escape_default ()}}} impl FnMut < (char ,) > for CharEscapeDefault {# [inline] extern \"rust-call\" fn call_mut (& mut self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (&* self , (c ,))}} impl FnOnce < (char ,) > for CharEscapeDefault {type Output = char :: EscapeDefault ; # [inline] extern \"rust-call\" fn call_once (self , (c ,) : (char ,)) -> char :: EscapeDefault {Fn :: call (& self , (c ,))}}" + ); } #[test] fn test_impl_nonzero_fmt() { // from https://github.com/rust-lang/rust/blob/316a391dcb7d66dc25f1f9a4ec9d368ef7615005/src/libcore/num/mod.rs#L12 - let rules = create_rules( + parse_macro( r#" macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { @@ -1208,11 +1134,7 @@ fn test_impl_nonzero_fmt() { } } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, + ).assert_expand_items( r#"impl_nonzero_fmt! { # [stable(feature= "nonzero",since="1.28.0")] (Debug,Display,Binary,Octal,LowerHex,UpperHex) for NonZeroU8}"#, "fn foo () {}", ); @@ -1221,7 +1143,7 @@ fn test_impl_nonzero_fmt() { #[test] fn test_cfg_if_items() { // from https://github.com/rust-lang/rust/blob/33fe1131cadba69d317156847be9a402b89f11bb/src/libstd/macros.rs#L986 - let rules = create_rules( + parse_macro( r#" macro_rules! __cfg_if_items { (($($not:meta,)*) ; ) => {}; @@ -1230,11 +1152,7 @@ fn test_cfg_if_items() { } } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, + ).assert_expand_items( r#"__cfg_if_items ! { ( rustdoc , ) ; ( ( ) ( # [ cfg ( any ( target_os = "redox" , unix ) ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as unix ; # [ cfg ( windows ) ] # [ stable ( feature = "rust1" , since = "1.0.0" ) ] pub use sys :: ext as windows ; # [ cfg ( any ( target_os = "linux" , target_os = "l4re" ) ) ] pub mod linux ; ) ) , }"#, "__cfg_if_items ! {(rustdoc ,) ;}", ); @@ -1243,7 +1161,7 @@ fn test_cfg_if_items() { #[test] fn test_cfg_if_main() { // from https://github.com/rust-lang/rust/blob/3d211248393686e0f73851fc7548f6605220fbe1/src/libpanic_unwind/macros.rs#L9 - let rules = create_rules( + parse_macro( r#" macro_rules! cfg_if { ($( @@ -1264,9 +1182,7 @@ fn test_cfg_if_main() { }; } "#, - ); - - assert_expansion(MacroKind::Items, &rules, r#" + ).assert_expand_items(r#" cfg_if ! { if # [ cfg ( target_env = "msvc" ) ] { // no extra unwinder support needed @@ -1278,11 +1194,8 @@ cfg_if ! { } } "#, - "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}"); - - assert_expansion( - MacroKind::Items, - &rules, + "__cfg_if_items ! {() ; ((target_env = \"msvc\") ()) , ((all (target_arch = \"wasm32\" , not (target_os = \"emscripten\"))) ()) , (() (mod libunwind ; pub use libunwind :: * ;)) ,}" + ).assert_expand_items( r#" cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , target_os = "illumos" ) ) ) ) ) ) , } "#, @@ -1293,7 +1206,7 @@ cfg_if ! { @ __apply cfg ( all ( not ( any ( not ( any ( target_os = "solaris" , #[test] fn test_proptest_arbitrary() { // from https://github.com/AltSysrq/proptest/blob/d1c4b049337d2f75dd6f49a095115f7c532e5129/proptest/src/arbitrary/macros.rs#L16 - let rules = create_rules( + parse_macro( r#" macro_rules! arbitrary { ([$($bounds : tt)*] $typ: ty, $strat: ty, $params: ty; @@ -1308,22 +1221,21 @@ macro_rules! arbitrary { }; }"#, - ); - - assert_expansion(MacroKind::Items, &rules, r#"arbitrary ! ( [ A : Arbitrary ] + ).assert_expand_items(r#"arbitrary ! ( [ A : Arbitrary ] Vec < A > , VecStrategy < A :: Strategy > , RangedParams1 < A :: Parameters > ; args => { let product_unpack ! [ range , a ] = args ; vec ( any_with :: < A > ( a ) , range ) } ) ;"#, - "impl
$crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}"); + "impl $crate :: arbitrary :: Arbitrary for Vec < A > {type Parameters = RangedParams1 < A :: Parameters > ; type Strategy = VecStrategy < A :: Strategy > ; fn arbitrary_with (args : Self :: Parameters) -> Self :: Strategy {{let product_unpack ! [range , a] = args ; vec (any_with :: < A > (a) , range)}}}" + ); } #[test] fn test_old_ridl() { // This is from winapi 2.8, which do not have a link from github // - let rules = create_rules( + let expanded = parse_macro( r#" #[macro_export] macro_rules! RIDL { @@ -1339,21 +1251,17 @@ macro_rules! RIDL { } }; }"#, - ); + ).expand_tt(r#" + RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { + fn GetDataSize(&mut self) -> UINT + }}"#); - let expanded = expand( - &rules, - r#" -RIDL!{interface ID3D11Asynchronous(ID3D11AsynchronousVtbl): ID3D11DeviceChild(ID3D11DeviceChildVtbl) { - fn GetDataSize(&mut self) -> UINT -}}"#, - ); assert_eq!(expanded.to_string(), "impl ID3D11Asynchronous {pub unsafe fn GetDataSize (& mut self) -> UINT {((* self . lpVtbl) .GetDataSize) (self)}}"); } #[test] fn test_quick_error() { - let rules = create_rules( + let expanded = parse_macro( r#" macro_rules! quick_error { @@ -1376,10 +1284,8 @@ macro_rules! quick_error { } "#, - ); - - let expanded = expand( - &rules, + ) + .expand_tt( r#" quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ => One : UNIT [] {} @@ -1393,7 +1299,7 @@ quick_error ! (SORT [enum Wrapped # [derive (Debug)]] items [ #[test] fn test_empty_repeat_vars_in_empty_repeat_vars() { - let rules = create_rules( + parse_macro( r#" macro_rules! delegate_impl { ([$self_type:ident, $self_wrap:ty, $self_map:ident] @@ -1440,11 +1346,7 @@ macro_rules! delegate_impl { } } "#, - ); - - assert_expansion( - MacroKind::Items, - &rules, + ).assert_expand_items( r#"delegate_impl ! {[G , & 'a mut G , deref] pub trait Data : GraphBase {@ section type type NodeWeight ;}}"#, "impl <> Data for & \'a mut G where G : Data {}", ); @@ -1452,7 +1354,7 @@ macro_rules! delegate_impl { #[test] fn expr_interpolation() { - let rules = create_rules( + let expanded = parse_macro( r#" macro_rules! id { ($expr:expr) => { @@ -1460,118 +1362,101 @@ fn expr_interpolation() { } } "#, - ); + ) + .expand_expr("id!(x + foo);"); - let expanded = expand(&rules, "id!(x + foo);"); - let expanded = - token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node(); assert_eq!(expanded.to_string(), "map(x+foo)"); } -pub(crate) fn create_rules(macro_definition: &str) -> MacroRules { +pub(crate) struct MacroFixture { + rules: MacroRules, +} + +impl MacroFixture { + pub(crate) fn expand_tt(&self, invocation: &str) -> tt::Subtree { + let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); + let macro_invocation = + source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); + + let (invocation_tt, _) = + ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); + + self.rules.expand(&invocation_tt).unwrap() + } + + fn expand_items(&self, invocation: &str) -> SyntaxNode { + let expanded = self.expand_tt(invocation); + token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node() + } + + fn expand_statements(&self, invocation: &str) -> SyntaxNode { + let expanded = self.expand_tt(invocation); + token_tree_to_syntax_node(&expanded, FragmentKind::Statements).unwrap().0.syntax_node() + } + + fn expand_expr(&self, invocation: &str) -> SyntaxNode { + let expanded = self.expand_tt(invocation); + token_tree_to_syntax_node(&expanded, FragmentKind::Expr).unwrap().0.syntax_node() + } + + fn assert_expand_tt(&self, invocation: &str, expected: &str) { + let expansion = self.expand_tt(invocation); + assert_eq!(expansion.to_string(), expected); + } + + fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { + self.assert_expansion(FragmentKind::Items, invocation, expected); + self + } + + fn assert_expand_statements(&self, invocation: &str, expected: &str) -> &MacroFixture { + self.assert_expansion(FragmentKind::Statements, invocation, expected); + self + } + + fn assert_expansion(&self, kind: FragmentKind, invocation: &str, expected: &str) { + let expanded = self.expand_tt(invocation); + assert_eq!(expanded.to_string(), expected); + + let expected = expected.replace("$crate", "C_C__C"); + + // wrap the given text to a macro call + let expected = { + let wrapped = format!("wrap_macro!( {} )", expected); + let wrapped = ast::SourceFile::parse(&wrapped); + let wrapped = + wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); + let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; + wrapped.delimiter = None; + wrapped + }; + + let expanded_tree = token_tree_to_syntax_node(&expanded, kind).unwrap().0.syntax_node(); + let expanded_tree = debug_dump_ignore_spaces(&expanded_tree).trim().to_string(); + + let expected_tree = token_tree_to_syntax_node(&expected, kind).unwrap().0.syntax_node(); + let expected_tree = debug_dump_ignore_spaces(&expected_tree).trim().to_string(); + + let expected_tree = expected_tree.replace("C_C__C", "$crate"); + assert_eq!( + expanded_tree, expected_tree, + "\nleft:\n{}\nright:\n{}", + expanded_tree, expected_tree, + ); + } +} + +pub(crate) fn parse_macro(macro_definition: &str) -> MacroFixture { let source_file = ast::SourceFile::parse(macro_definition).ok().unwrap(); let macro_definition = source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); - crate::MacroRules::parse(&definition_tt).unwrap() + let rules = MacroRules::parse(&definition_tt).unwrap(); + MacroFixture { rules } } -pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree { - let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); - let macro_invocation = - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); - - let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); - - rules.expand(&invocation_tt).unwrap() -} - -pub(crate) fn expand_and_map( - rules: &MacroRules, - invocation: &str, -) -> (tt::Subtree, (TokenMap, String)) { - let source_file = ast::SourceFile::parse(invocation).ok().unwrap(); - let macro_invocation = - source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); - - let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); - let expanded = rules.expand(&invocation_tt).unwrap(); - - let (node, expanded_token_tree) = - token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap(); - - (expanded, (expanded_token_tree, node.syntax_node().to_string())) -} - -pub(crate) enum MacroKind { - Items, - Stmts, -} - -pub(crate) fn assert_expansion( - kind: MacroKind, - rules: &MacroRules, - invocation: &str, - expected: &str, -) -> tt::Subtree { - let expanded = expand(rules, invocation); - assert_eq!(expanded.to_string(), expected); - - let expected = expected.replace("$crate", "C_C__C"); - - // wrap the given text to a macro call - let expected = { - let wrapped = format!("wrap_macro!( {} )", expected); - let wrapped = ast::SourceFile::parse(&wrapped); - let wrapped = wrapped.tree().syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); - let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; - wrapped.delimiter = None; - wrapped - }; - let (expanded_tree, expected_tree) = match kind { - MacroKind::Items => { - let expanded_tree = - token_tree_to_syntax_node(&expanded, FragmentKind::Items).unwrap().0.syntax_node(); - let expected_tree = - token_tree_to_syntax_node(&expected, FragmentKind::Items).unwrap().0.syntax_node(); - - ( - debug_dump_ignore_spaces(&expanded_tree).trim().to_string(), - debug_dump_ignore_spaces(&expected_tree).trim().to_string(), - ) - } - - MacroKind::Stmts => { - let expanded_tree = token_tree_to_syntax_node(&expanded, FragmentKind::Statements) - .unwrap() - .0 - .syntax_node(); - let expected_tree = token_tree_to_syntax_node(&expected, FragmentKind::Statements) - .unwrap() - .0 - .syntax_node(); - - ( - debug_dump_ignore_spaces(&expanded_tree).trim().to_string(), - debug_dump_ignore_spaces(&expected_tree).trim().to_string(), - ) - } - }; - - let expected_tree = expected_tree.replace("C_C__C", "$crate"); - assert_eq!( - expanded_tree, expected_tree, - "\nleft:\n{}\nright:\n{}", - expanded_tree, expected_tree, - ); - - expanded -} - -pub fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { - use std::fmt::Write; - +fn debug_dump_ignore_spaces(node: &ra_syntax::SyntaxNode) -> String { let mut level = 0; let mut buf = String::new(); macro_rules! indent { diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 45241e5664..65134277e1 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs @@ -83,6 +83,7 @@ pub fn parse(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { parse_from_tokens(token_source, tree_sink, grammar::root); } +#[derive(Clone, Copy)] pub enum FragmentKind { Path, Expr, From 43ed3d1196164c96d025745c42f261930b832911 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 16:57:22 +0100 Subject: [PATCH 226/312] Handle start imports in import groups --- crates/ra_hir_def/src/marks.rs | 1 + crates/ra_hir_def/src/nameres/tests/globs.rs | 21 +++++++++++++++++++ crates/ra_hir_def/src/path/lower/lower_use.rs | 12 ++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_def/src/marks.rs b/crates/ra_hir_def/src/marks.rs index 65239ca0a4..457ba4abec 100644 --- a/crates/ra_hir_def/src/marks.rs +++ b/crates/ra_hir_def/src/marks.rs @@ -5,6 +5,7 @@ test_utils::marks!( name_res_works_for_broken_modules can_import_enum_variant glob_enum + glob_enum_group glob_across_crates std_prelude macro_rules_from_other_crates_are_visible_with_macro_use diff --git a/crates/ra_hir_def/src/nameres/tests/globs.rs b/crates/ra_hir_def/src/nameres/tests/globs.rs index 5b03fe3650..5e24cb94d6 100644 --- a/crates/ra_hir_def/src/nameres/tests/globs.rs +++ b/crates/ra_hir_def/src/nameres/tests/globs.rs @@ -112,3 +112,24 @@ fn glob_enum() { "### ); } + +#[test] +fn glob_enum_group() { + covers!(glob_enum_group); + let map = def_map( + " + //- /lib.rs + enum Foo { + Bar, Baz + } + use self::Foo::{*}; + ", + ); + assert_snapshot!(map, @r###" + â‹®crate + â‹®Bar: t v + â‹®Baz: t v + â‹®Foo: t + "### + ); +} diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs index 062c02063e..3218eaf0a2 100644 --- a/crates/ra_hir_def/src/path/lower/lower_use.rs +++ b/crates/ra_hir_def/src/path/lower/lower_use.rs @@ -9,6 +9,7 @@ use hir_expand::{ name::{AsName, Name}, }; use ra_syntax::ast::{self, NameOwner}; +use test_utils::tested_by; use crate::path::{ModPath, PathKind}; @@ -34,6 +35,7 @@ pub(crate) fn lower_use_tree( } } else { let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); + let is_glob = tree.has_star(); if let Some(ast_path) = tree.path() { // Handle self in a path. // E.g. `use something::{self, <...>}` @@ -48,11 +50,15 @@ pub(crate) fn lower_use_tree( } } if let Some(path) = convert_path(prefix, ast_path, hygiene) { - let is_glob = tree.has_star(); cb(path, &tree, is_glob, alias) } - // FIXME: report errors somewhere - // We get here if we do + // FIXME: report errors somewhere + // We get here if we do + } else if is_glob { + tested_by!(glob_enum_group); + if let Some(prefix) = prefix { + cb(prefix, &tree, is_glob, None) + } } } } From 0ed8ce096d3ae9ee4027ab4723958a021ef24194 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 17:13:08 +0100 Subject: [PATCH 227/312] Touch up TokenSet a bit --- crates/ra_parser/src/grammar.rs | 2 +- crates/ra_parser/src/grammar/expressions/atom.rs | 2 +- crates/ra_parser/src/parser.rs | 2 +- crates/ra_parser/src/token_set.rs | 8 +++----- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index 6e9e212b76..22f64a9f4a 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs @@ -264,7 +264,7 @@ fn name_r(p: &mut Parser, recovery: TokenSet) { } fn name(p: &mut Parser) { - name_r(p, TokenSet::empty()) + name_r(p, TokenSet::EMPTY) } fn name_ref(p: &mut Parser) { diff --git a/crates/ra_parser/src/grammar/expressions/atom.rs b/crates/ra_parser/src/grammar/expressions/atom.rs index 6f5545a83a..4ac1d6334a 100644 --- a/crates/ra_parser/src/grammar/expressions/atom.rs +++ b/crates/ra_parser/src/grammar/expressions/atom.rs @@ -444,7 +444,7 @@ fn match_arm(p: &mut Parser) -> BlockLike { // } attributes::outer_attributes(p); - patterns::pattern_list_r(p, TokenSet::empty()); + patterns::pattern_list_r(p, TokenSet::EMPTY); if p.at(T![if]) { match_guard(p); } diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index dafd5247bf..1071c46dc8 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs @@ -208,7 +208,7 @@ impl<'t> Parser<'t> { /// Create an error node and consume the next token. pub(crate) fn err_and_bump(&mut self, message: &str) { - self.err_recover(message, TokenSet::empty()); + self.err_recover(message, TokenSet::EMPTY); } /// Create an error node and consume the next token. diff --git a/crates/ra_parser/src/token_set.rs b/crates/ra_parser/src/token_set.rs index 2a6952c013..994017acfd 100644 --- a/crates/ra_parser/src/token_set.rs +++ b/crates/ra_parser/src/token_set.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! A bit-set of `SyntaxKind`s. use crate::SyntaxKind; @@ -7,9 +7,7 @@ use crate::SyntaxKind; pub(crate) struct TokenSet(u128); impl TokenSet { - pub(crate) const fn empty() -> TokenSet { - TokenSet(0) - } + pub(crate) const EMPTY: TokenSet = TokenSet(0); pub(crate) const fn singleton(kind: SyntaxKind) -> TokenSet { TokenSet(mask(kind)) @@ -30,7 +28,7 @@ const fn mask(kind: SyntaxKind) -> u128 { #[macro_export] macro_rules! token_set { - ($($t:expr),*) => { TokenSet::empty()$(.union(TokenSet::singleton($t)))* }; + ($($t:expr),*) => { TokenSet::EMPTY$(.union(TokenSet::singleton($t)))* }; ($($t:expr),* ,) => { token_set!($($t),*) }; } From b2731ab78acc7a2d38e02cd477f4a5132c1ac98b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 18:07:39 +0100 Subject: [PATCH 228/312] Drop dead code --- crates/ra_hir/src/code_model.rs | 62 ++------------------------------- crates/ra_hir/src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 60 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 7850ea9a71..8dbc0d6678 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -11,9 +11,9 @@ use hir_def::{ per_ns::PerNs, resolver::HasResolver, type_ref::{Mutability, TypeRef}, - AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, - LocalEnumVariantId, LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, - StaticId, StructId, TraitId, TypeAliasId, TypeParamId, UnionId, + AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, + LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, + TraitId, TypeAliasId, TypeParamId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -529,30 +529,6 @@ impl Const { pub fn name(self, db: &impl HirDatabase) -> Option { db.const_data(self.id).name.clone() } - - /// The containing impl block, if this is a type alias. - pub fn impl_block(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::ImplBlock(it)) => Some(it), - _ => None, - } - } - - /// The containing trait, if this is a trait type alias definition. - pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::Trait(it)) => Some(it), - _ => None, - } - } - - pub fn container(self, db: &impl DefDatabase) -> Option { - match self.id.lookup(db).container { - ContainerId::TraitId(it) => Some(Container::Trait(it.into())), - ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - ContainerId::ModuleId(_) => None, - } - } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -612,30 +588,6 @@ impl TypeAlias { Some(self.module(db).krate()) } - /// The containing impl block, if this is a type alias. - pub fn impl_block(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::ImplBlock(it)) => Some(it), - _ => None, - } - } - - /// The containing trait, if this is a trait type alias definition. - pub fn parent_trait(self, db: &impl DefDatabase) -> Option { - match self.container(db) { - Some(Container::Trait(it)) => Some(it), - _ => None, - } - } - - pub fn container(self, db: &impl DefDatabase) -> Option { - match self.id.lookup(db).container { - ContainerId::TraitId(it) => Some(Container::Trait(it.into())), - ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())), - ContainerId::ModuleId(_) => None, - } - } - pub fn type_ref(self, db: &impl DefDatabase) -> Option { db.type_alias_data(self.id).type_ref.clone() } @@ -654,14 +606,6 @@ pub struct MacroDef { pub(crate) id: MacroDefId, } -impl MacroDef {} - -pub enum Container { - Trait(Trait), - ImplBlock(ImplBlock), -} -impl_froms!(Container: Trait, ImplBlock); - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum AssocItem { Function(Function), diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 2e52a1f5c0..7f9aef7707 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -39,7 +39,7 @@ mod from_source; pub use crate::{ code_model::{ - Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Docs, Enum, + Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, From 5bd8de3f5e11732d67d0cc9bacda7d3a1b7cf13a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 17:30:28 +0100 Subject: [PATCH 229/312] Allow storing defs in bodies --- crates/ra_hir_def/src/body.rs | 3 ++- crates/ra_hir_def/src/body/lower.rs | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index d4cab05614..332c509e17 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,7 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{ModPath, Path}, src::HasSource, - DefWithBodyId, HasModule, Lookup, ModuleId, + DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, }; struct Expander { @@ -119,6 +119,7 @@ pub struct Body { pub params: Vec, /// The `ExprId` of the actual body expression. pub body_expr: ExprId, + pub defs: Vec, } pub type ExprPtr = Either, AstPtr>; diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 61193b4d80..86960186f1 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -41,6 +41,7 @@ pub(super) fn lower( pats: Arena::default(), params: Vec::new(), body_expr: ExprId::dummy(), + defs: Vec::new(), }, } .collect(params, body) From ba12e83c26b24358e1bfbae0f913f8dfa13fc68f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 18:12:46 +0100 Subject: [PATCH 230/312] Add body as a possible container for items --- crates/ra_hir_def/src/lib.rs | 24 +++++++++++------------ crates/ra_hir_def/src/resolver.rs | 1 + crates/ra_hir_ty/src/infer/path.rs | 2 +- crates/ra_hir_ty/src/method_resolution.rs | 10 +++++----- crates/ra_hir_ty/src/utils.rs | 2 +- 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index f085bbe872..4fc3127c41 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -335,6 +335,7 @@ pub enum ContainerId { ModuleId(ModuleId), ImplId(ImplId), TraitId(TraitId), + DefWithBodyId(DefWithBodyId), } /// A Data Type @@ -478,33 +479,32 @@ pub trait HasModule { fn module(&self, db: &impl db::DefDatabase) -> ModuleId; } -impl HasModule for FunctionLoc { +impl HasModule for ContainerId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { - match self.container { + match *self { ContainerId::ModuleId(it) => it, ContainerId::ImplId(it) => it.lookup(db).container, ContainerId::TraitId(it) => it.lookup(db).container, + ContainerId::DefWithBodyId(it) => it.module(db), } } } +impl HasModule for FunctionLoc { + fn module(&self, db: &impl db::DefDatabase) -> ModuleId { + self.container.module(db) + } +} + impl HasModule for TypeAliasLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { - match self.container { - ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.lookup(db).container, - } + self.container.module(db) } } impl HasModule for ConstLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { - match self.container { - ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.lookup(db).container, - } + self.container.module(db) } } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 2694c0438b..2503292715 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -586,6 +586,7 @@ impl HasResolver for ContainerId { ContainerId::TraitId(it) => it.resolver(db), ContainerId::ImplId(it) => it.resolver(db), ContainerId::ModuleId(it) => it.resolver(db), + ContainerId::DefWithBodyId(it) => it.resolver(db), } } } diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 402a89386b..31c90ea1ef 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -237,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { })); Some(substs) } - ContainerId::ModuleId(_) => None, + ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => None, }; self.write_assoc_resolution(id, item.into()); diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 848e306e9e..d0b2b016d5 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use arrayvec::ArrayVec; use hir_def::{ - lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, FunctionId, - HasModule, ImplId, Lookup, TraitId, + lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, ContainerId, + FunctionId, HasModule, ImplId, Lookup, TraitId, }; use hir_expand::name::Name; use ra_db::CrateId; @@ -451,12 +451,12 @@ fn transform_receiver_ty( self_ty: &Canonical, ) -> Option { let substs = match function_id.lookup(db).container { - hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, function_id) + ContainerId::TraitId(_) => Substs::build_for_def(db, function_id) .push(self_ty.value.clone()) .fill_with_unknown() .build(), - hir_def::ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, - hir_def::ContainerId::ModuleId(_) => unreachable!(), + ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, + ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => unreachable!(), }; let sig = db.callable_item_signature(function_id.into()); Some(sig.params()[0].clone().subst(&substs)) diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 29799a8cbd..34defc1a20 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -157,6 +157,6 @@ fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option Some(it.into()), ContainerId::TraitId(it) => Some(it.into()), - ContainerId::ModuleId(_) => None, + ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => None, } } From 9ccad60acca0d359f1fd9046c99952d0c1adc763 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 18:21:26 +0100 Subject: [PATCH 231/312] Implement ChildBySource for DefWithBody --- crates/ra_hir_def/src/child_by_source.rs | 97 ++++++++++++++---------- 1 file changed, 55 insertions(+), 42 deletions(-) diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 3c9379b151..f5a65ad409 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -11,8 +11,8 @@ use crate::{ dyn_map::DynMap, keys, src::{HasChildSource, HasSource}, - AdtId, AssocItemId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, ModuleId, - StructFieldId, TraitId, VariantId, + AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, + ModuleId, StructFieldId, TraitId, VariantId, }; pub trait ChildBySource { @@ -76,47 +76,11 @@ impl ChildBySource for ModuleId { let mut res = DynMap::default(); let crate_def_map = db.crate_def_map(self.krate); - for item in crate_def_map[self.local_id].scope.declarations() { - match item { - ModuleDefId::FunctionId(func) => { - let src = func.lookup(db).source(db); - res[keys::FUNCTION].insert(src, func) - } - ModuleDefId::ConstId(konst) => { - let src = konst.lookup(db).source(db); - res[keys::CONST].insert(src, konst) - } - ModuleDefId::StaticId(statik) => { - let src = statik.lookup(db).source(db); - res[keys::STATIC].insert(src, statik) - } - ModuleDefId::TypeAliasId(ty) => { - let src = ty.lookup(db).source(db); - res[keys::TYPE_ALIAS].insert(src, ty) - } - ModuleDefId::TraitId(trait_) => { - let src = trait_.lookup(db).source(db); - res[keys::TRAIT].insert(src, trait_) - } - ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(strukt) => { - let src = strukt.lookup(db).source(db); - res[keys::STRUCT].insert(src, strukt) - } - AdtId::UnionId(union_) => { - let src = union_.lookup(db).source(db); - res[keys::UNION].insert(src, union_) - } - AdtId::EnumId(enum_) => { - let src = enum_.lookup(db).source(db); - res[keys::ENUM].insert(src, enum_) - } - }, - _ => (), - } - } + let module_data = &crate_def_map[self.local_id]; - for &impl_ in crate_def_map[self.local_id].impls.iter() { + module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); + + for &impl_ in module_data.impls.iter() { let src = impl_.lookup(db).source(db); res[keys::IMPL].insert(src, impl_) } @@ -125,6 +89,46 @@ impl ChildBySource for ModuleId { } } +fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) { + match item { + ModuleDefId::FunctionId(func) => { + let src = func.lookup(db).source(db); + map[keys::FUNCTION].insert(src, func) + } + ModuleDefId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + map[keys::CONST].insert(src, konst) + } + ModuleDefId::StaticId(statik) => { + let src = statik.lookup(db).source(db); + map[keys::STATIC].insert(src, statik) + } + ModuleDefId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + map[keys::TYPE_ALIAS].insert(src, ty) + } + ModuleDefId::TraitId(trait_) => { + let src = trait_.lookup(db).source(db); + map[keys::TRAIT].insert(src, trait_) + } + ModuleDefId::AdtId(adt) => match adt { + AdtId::StructId(strukt) => { + let src = strukt.lookup(db).source(db); + map[keys::STRUCT].insert(src, strukt) + } + AdtId::UnionId(union_) => { + let src = union_.lookup(db).source(db); + map[keys::UNION].insert(src, union_) + } + AdtId::EnumId(enum_) => { + let src = enum_.lookup(db).source(db); + map[keys::ENUM].insert(src, enum_) + } + }, + _ => (), + } +} + impl ChildBySource for VariantId { fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { let mut res = DynMap::default(); @@ -160,3 +164,12 @@ impl ChildBySource for EnumId { res } } + +impl ChildBySource for DefWithBodyId { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + let body = db.body(*self); + body.defs.iter().copied().for_each(|item| add_module_def(db, &mut res, item)); + res + } +} From c7291386d31c1991aac917c5580f1c3ebfa48aed Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 18:27:44 +0100 Subject: [PATCH 232/312] :arrow_up: Rust --- xtask/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c52902bb56..4201c6a6a7 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -20,7 +20,7 @@ use xtask::{ }; // Latest stable, feel free to send a PR if this lags behind. -const REQUIRED_RUST_VERSION: u32 = 39; +const REQUIRED_RUST_VERSION: u32 = 40; struct InstallOpt { client: Option, From 932d8050625359f6ac03bcbf2cd49aae728b520b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 19 Dec 2019 18:28:57 +0100 Subject: [PATCH 233/312] :arrow_up: deps --- Cargo.lock | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af874945c1..b7a5108a49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,8 +110,8 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -433,7 +433,7 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", @@ -491,7 +491,7 @@ dependencies = [ "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -614,7 +614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -624,7 +624,7 @@ version = "0.63.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -729,7 +729,7 @@ name = "num_cpus" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1059,7 +1059,7 @@ dependencies = [ "ra_vfs_glob 0.1.0", "relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", @@ -1107,7 +1107,7 @@ dependencies = [ "ra_cfg 0.1.0", "ra_db 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1123,7 +1123,7 @@ dependencies = [ "rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1381,7 +1381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1474,7 +1474,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1484,15 +1484,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1507,7 +1507,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1527,7 +1527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1546,7 +1546,7 @@ name = "smol_str" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1662,7 +1662,7 @@ dependencies = [ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1671,7 +1671,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1749,7 +1749,7 @@ dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1816,7 +1816,7 @@ dependencies = [ "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" @@ -1903,8 +1903,8 @@ dependencies = [ "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" -"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" From 76d688a328ab53b6264f9e489b88524377a7271d Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 20 Dec 2019 03:04:55 +0800 Subject: [PATCH 234/312] Use fill instread of for loop --- crates/ra_hir_ty/src/infer.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 98baeed6f6..bbbc391c4f 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -375,11 +375,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { match assoc_ty { Some(res_assoc_ty) => { let ty = self.table.new_type_var(); - let mut builder = Substs::build_for_def(self.db, res_assoc_ty).push(inner_ty); - for ty in params { - builder = builder.push(ty.clone()); - } - + let builder = Substs::build_for_def(self.db, res_assoc_ty) + .push(inner_ty) + .fill(params.iter().cloned()); let projection = ProjectionPredicate { ty: ty.clone(), projection_ty: ProjectionTy { From a04177f135be89ddbf1788c6f747c26812e90438 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:19:09 +0100 Subject: [PATCH 235/312] Add local functions to bodies --- Cargo.lock | 1 + crates/ra_hir/src/from_source.rs | 11 +++++-- crates/ra_hir_def/Cargo.toml | 1 + crates/ra_hir_def/src/body.rs | 43 +++++++++++++++++----------- crates/ra_hir_def/src/body/lower.rs | 24 ++++++++++++++-- crates/ra_ide/src/goto_definition.rs | 17 +++++++++++ 6 files changed, 76 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7a5108a49..3f2cbc8ab0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -957,6 +957,7 @@ name = "ra_hir_def" version = "0.1.0" dependencies = [ "anymap 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 7abb4bd75a..b3ed88b6b6 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,8 +1,8 @@ //! FIXME: write short doc here use hir_def::{ child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, - ConstId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, UnionId, VariantId, + ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; use ra_syntax::{ @@ -227,7 +227,12 @@ fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option ast::ImplBlock(it) => { let c = ImplBlock::from_source(db, src.with_value(it))?; c.id.child_by_source(db) - }, + }, + ast::FnDef(it) => { + let f = Function::from_source(db, src.with_value(it))?; + DefWithBodyId::from(f.id) + .child_by_source(db) + }, _ => { continue }, } }; diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml index b1923bbf2e..2c368f690b 100644 --- a/crates/ra_hir_def/Cargo.toml +++ b/crates/ra_hir_def/Cargo.toml @@ -13,6 +13,7 @@ once_cell = "1.0.1" rustc-hash = "1.0" either = "1.5" anymap = "0.12" +drop_bomb = "0.1.4" ra_arena = { path = "../ra_arena" } ra_db = { path = "../ra_db" } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 332c509e17..92c32b080c 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -3,10 +3,13 @@ mod lower; pub mod scope; -use std::{ops::Index, sync::Arc}; +use std::{mem, ops::Index, sync::Arc}; +use drop_bomb::DropBomb; use either::Either; -use hir_expand::{hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId}; +use hir_expand::{ + ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, +}; use ra_arena::{map::ArenaMap, Arena}; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -24,6 +27,7 @@ struct Expander { crate_def_map: Arc, current_file_id: HirFileId, hygiene: Hygiene, + ast_id_map: Arc, module: ModuleId, } @@ -31,7 +35,8 @@ impl Expander { fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { let crate_def_map = db.crate_def_map(module.krate); let hygiene = Hygiene::new(db, current_file_id); - Expander { crate_def_map, current_file_id, hygiene, module } + let ast_id_map = db.ast_id_map(current_file_id); + Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } } fn enter_expand( @@ -52,9 +57,14 @@ impl Expander { if let Some(expr) = ast::Expr::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); - let mark = Mark { file_id: self.current_file_id }; + let mark = Mark { + file_id: self.current_file_id, + ast_id_map: mem::take(&mut self.ast_id_map), + bomb: DropBomb::new("expansion mark dropped"), + }; self.hygiene = Hygiene::new(db, file_id); self.current_file_id = file_id; + self.ast_id_map = db.ast_id_map(file_id); return Some((mark, expr)); } @@ -67,10 +77,11 @@ impl Expander { None } - fn exit(&mut self, db: &impl DefDatabase, mark: Mark) { + fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { self.hygiene = Hygiene::new(db, mark.file_id); self.current_file_id = mark.file_id; - std::mem::forget(mark); + self.ast_id_map = mem::take(&mut mark.ast_id_map); + mark.bomb.defuse(); } fn to_source(&self, value: T) -> InFile { @@ -91,18 +102,17 @@ impl Expander { .0 .take_macros() } + + fn ast_id(&self, item: &N) -> AstId { + let file_local_id = self.ast_id_map.ast_id(item); + AstId::new(self.current_file_id, file_local_id) + } } struct Mark { file_id: HirFileId, -} - -impl Drop for Mark { - fn drop(&mut self) { - if !std::thread::panicking() { - panic!("dropped mark") - } - } + ast_id_map: Arc, + bomb: DropBomb, } /// The body of an item (function, const etc.). @@ -174,7 +184,7 @@ impl Body { } }; let expander = Expander::new(db, file_id, module); - let (body, source_map) = Body::new(db, expander, params, body); + let (body, source_map) = Body::new(db, def, expander, params, body); (Arc::new(body), Arc::new(source_map)) } @@ -184,11 +194,12 @@ impl Body { fn new( db: &impl DefDatabase, + def: DefWithBodyId, expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { - lower::lower(db, expander, params, body) + lower::lower(db, def, expander, params, body) } } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 86960186f1..17efa10e29 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -2,11 +2,12 @@ //! representation. use either::Either; + use hir_expand::name::{name, AsName, Name}; use ra_arena::Arena; use ra_syntax::{ ast::{ - self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, NameOwner, + self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner, TypeAscriptionOwner, }, AstNode, AstPtr, @@ -24,17 +25,20 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, + ContainerId, DefWithBodyId, FunctionLoc, Intern, }; pub(super) fn lower( db: &impl DefDatabase, + def: DefWithBodyId, expander: Expander, params: Option, body: Option, ) -> (Body, BodySourceMap) { ExprCollector { - expander, db, + def, + expander, source_map: BodySourceMap::default(), body: Body { exprs: Arena::default(), @@ -49,6 +53,7 @@ pub(super) fn lower( struct ExprCollector { db: DB, + def: DefWithBodyId, expander: Expander, body: Body, @@ -467,6 +472,7 @@ where Some(block) => block, None => return self.alloc_expr(Expr::Missing, syntax_node_ptr), }; + self.collect_block_items(&block); let statements = block .statements() .map(|s| match s { @@ -483,6 +489,20 @@ where self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) } + fn collect_block_items(&mut self, block: &ast::Block) { + let container = ContainerId::DefWithBodyId(self.def); + for item in block.items() { + match item { + ast::ModuleItem::FnDef(def) => { + let ast_id = self.expander.ast_id(&def); + self.body.defs.push(FunctionLoc { container, ast_id }.intern(self.db).into()) + } + // FIXME: handle other items + _ => (), + } + } + } + fn collect_block_opt(&mut self, expr: Option) -> ExprId { if let Some(block) = expr { self.collect_block(block) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 184555792c..ee4ae3e037 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -858,4 +858,21 @@ mod tests { "y", ); } + + #[test] + fn goto_def_in_local_fn() { + check_goto( + " + //- /lib.rs + fn main() { + fn foo() { + let x = 92; + <|>x; + } + } + ", + "x BIND_PAT FileId(1) [39; 40)", + "x", + ); + } } From d316ba9a136833c64ba066feb62cf553dd4b3a58 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:24:23 +0100 Subject: [PATCH 236/312] Handle nested declrations in from_source --- crates/ra_hir/src/from_source.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index b3ed88b6b6..4fd7c75736 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -216,21 +216,30 @@ fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap } fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { - // FIXME: this doesn't try to handle nested declarations for container in src.value.ancestors().skip(1) { let res = match_ast! { match container { ast::TraitDef(it) => { - let c = Trait::from_source(db, src.with_value(it))?; - c.id.child_by_source(db) + let def = Trait::from_source(db, src.with_value(it))?; + def.id.child_by_source(db) }, ast::ImplBlock(it) => { - let c = ImplBlock::from_source(db, src.with_value(it))?; - c.id.child_by_source(db) + let def = ImplBlock::from_source(db, src.with_value(it))?; + def.id.child_by_source(db) }, ast::FnDef(it) => { - let f = Function::from_source(db, src.with_value(it))?; - DefWithBodyId::from(f.id) + let def = Function::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) + .child_by_source(db) + }, + ast::StaticDef(it) => { + let def = Static::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) + .child_by_source(db) + }, + ast::ConstDef(it) => { + let def = Const::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) .child_by_source(db) }, _ => { continue }, From 67c2aea182c375108ebb8b923f5679e4f7fef1df Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:30:22 +0100 Subject: [PATCH 237/312] Rebuild ra_lsp_server and nest helper function. Completion now works again, so there's no need not to nest --- crates/ra_hir/src/from_source.rs | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 4fd7c75736..3b6454a1d8 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -212,43 +212,43 @@ impl Module { } fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { - _analyze_container(db, src).unwrap_or_default() -} + return child_by_source(db, src).unwrap_or_default(); -fn _analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { - for container in src.value.ancestors().skip(1) { - let res = match_ast! { - match container { - ast::TraitDef(it) => { - let def = Trait::from_source(db, src.with_value(it))?; - def.id.child_by_source(db) - }, - ast::ImplBlock(it) => { - let def = ImplBlock::from_source(db, src.with_value(it))?; - def.id.child_by_source(db) - }, - ast::FnDef(it) => { - let def = Function::from_source(db, src.with_value(it))?; - DefWithBodyId::from(def.id) - .child_by_source(db) - }, - ast::StaticDef(it) => { - let def = Static::from_source(db, src.with_value(it))?; - DefWithBodyId::from(def.id) - .child_by_source(db) - }, - ast::ConstDef(it) => { - let def = Const::from_source(db, src.with_value(it))?; - DefWithBodyId::from(def.id) - .child_by_source(db) - }, - _ => { continue }, - } - }; - return Some(res); + fn child_by_source(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { + for container in src.value.ancestors().skip(1) { + let res = match_ast! { + match container { + ast::TraitDef(it) => { + let def = Trait::from_source(db, src.with_value(it))?; + def.id.child_by_source(db) + }, + ast::ImplBlock(it) => { + let def = ImplBlock::from_source(db, src.with_value(it))?; + def.id.child_by_source(db) + }, + ast::FnDef(it) => { + let def = Function::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) + .child_by_source(db) + }, + ast::StaticDef(it) => { + let def = Static::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) + .child_by_source(db) + }, + ast::ConstDef(it) => { + let def = Const::from_source(db, src.with_value(it))?; + DefWithBodyId::from(def.id) + .child_by_source(db) + }, + _ => { continue }, + } + }; + return Some(res); + } + + let module_source = ModuleSource::from_child_node(db, src); + let c = Module::from_definition(db, src.with_value(module_source))?; + Some(c.id.child_by_source(db)) } - - let module_source = ModuleSource::from_child_node(db, src); - let c = Module::from_definition(db, src.with_value(module_source))?; - Some(c.id.child_by_source(db)) } From 8fc20b65035d93bcc1b3a89127916bd165a8d938 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 11:59:50 +0100 Subject: [PATCH 238/312] Rename ContainerId -> AssocContainerId --- crates/ra_hir_def/src/body/lower.rs | 4 ++-- crates/ra_hir_def/src/data.rs | 12 ++++++------ crates/ra_hir_def/src/lib.rs | 18 +++++++++--------- crates/ra_hir_def/src/nameres/collector.rs | 8 ++++---- crates/ra_hir_def/src/resolver.rs | 16 ++++++++-------- crates/ra_hir_ty/src/infer/expr.rs | 4 ++-- crates/ra_hir_ty/src/infer/path.rs | 8 ++++---- crates/ra_hir_ty/src/lib.rs | 8 ++++---- crates/ra_hir_ty/src/method_resolution.rs | 10 +++++----- crates/ra_hir_ty/src/traits/chalk.rs | 6 +++--- crates/ra_hir_ty/src/utils.rs | 8 ++++---- 11 files changed, 51 insertions(+), 51 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 17efa10e29..afd5231cc1 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -25,7 +25,7 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, - ContainerId, DefWithBodyId, FunctionLoc, Intern, + AssocContainerId, DefWithBodyId, FunctionLoc, Intern, }; pub(super) fn lower( @@ -490,7 +490,7 @@ where } fn collect_block_items(&mut self, block: &ast::Block) { - let container = ContainerId::DefWithBodyId(self.def); + let container = AssocContainerId::DefWithBodyId(self.def); for item in block.items() { match item { ast::ModuleItem::FnDef(def) => { diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 4f4ef57cc0..14e86936bc 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -12,8 +12,8 @@ use crate::{ db::DefDatabase, src::HasSource, type_ref::{Mutability, TypeRef}, - AssocItemId, ConstId, ConstLoc, ContainerId, FunctionId, FunctionLoc, ImplId, Intern, Lookup, - StaticId, TraitId, TypeAliasId, TypeAliasLoc, + AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern, + Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -99,7 +99,7 @@ impl TraitData { let auto = src.value.is_auto(); let ast_id_map = db.ast_id_map(src.file_id); - let container = ContainerId::TraitId(tr); + let container = AssocContainerId::TraitId(tr); let items = if let Some(item_list) = src.value.item_list() { item_list .impl_items() @@ -180,7 +180,7 @@ impl ImplData { .map(|item_node| match item_node { ast::ImplItem::FnDef(it) => { let def = FunctionLoc { - container: ContainerId::ImplId(id), + container: AssocContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); @@ -188,7 +188,7 @@ impl ImplData { } ast::ImplItem::ConstDef(it) => { let def = ConstLoc { - container: ContainerId::ImplId(id), + container: AssocContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); @@ -196,7 +196,7 @@ impl ImplData { } ast::ImplItem::TypeAliasDef(it) => { let def = TypeAliasLoc { - container: ContainerId::ImplId(id), + container: AssocContainerId::ImplId(id), ast_id: AstId::new(src.file_id, items.ast_id(&it)), } .intern(db); diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 4fc3127c41..3d42762aef 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -71,7 +71,7 @@ impl_intern_key!(FunctionId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct FunctionLoc { - pub container: ContainerId, + pub container: AssocContainerId, pub ast_id: AstId, } @@ -187,7 +187,7 @@ pub struct ConstId(salsa::InternId); impl_intern_key!(ConstId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ConstLoc { - pub container: ContainerId, + pub container: AssocContainerId, pub ast_id: AstId, } @@ -259,7 +259,7 @@ impl_intern_key!(TypeAliasId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TypeAliasLoc { - pub container: ContainerId, + pub container: AssocContainerId, pub ast_id: AstId, } @@ -331,7 +331,7 @@ pub struct LocalTypeParamId(RawId); impl_arena_id!(LocalTypeParamId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum ContainerId { +pub enum AssocContainerId { ModuleId(ModuleId), ImplId(ImplId), TraitId(TraitId), @@ -479,13 +479,13 @@ pub trait HasModule { fn module(&self, db: &impl db::DefDatabase) -> ModuleId; } -impl HasModule for ContainerId { +impl HasModule for AssocContainerId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match *self { - ContainerId::ModuleId(it) => it, - ContainerId::ImplId(it) => it.lookup(db).container, - ContainerId::TraitId(it) => it.lookup(db).container, - ContainerId::DefWithBodyId(it) => it.module(db), + AssocContainerId::ModuleId(it) => it, + AssocContainerId::ImplId(it) => it.lookup(db).container, + AssocContainerId::TraitId(it) => it.lookup(db).container, + AssocContainerId::DefWithBodyId(it) => it.module(db), } } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 8bbf7ffa27..848959f7c4 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -24,7 +24,7 @@ use crate::{ }, path::{ModPath, PathKind}, per_ns::PerNs, - AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, + AdtId, AssocContainerId, AstId, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, }; @@ -763,7 +763,7 @@ where let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { let def = FunctionLoc { - container: ContainerId::ModuleId(module), + container: AssocContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); @@ -787,7 +787,7 @@ where } raw::DefKind::Const(ast_id) => { let def = ConstLoc { - container: ContainerId::ModuleId(module), + container: AssocContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); @@ -808,7 +808,7 @@ where } raw::DefKind::TypeAlias(ast_id) => { let def = TypeAliasLoc { - container: ContainerId::ModuleId(module), + container: AssocContainerId::ModuleId(module), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 2503292715..d79c9813b7 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -17,9 +17,9 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{ModPath, PathKind}, per_ns::PerNs, - AdtId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, - HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, StructId, TraitId, - TypeAliasId, TypeParamId, VariantId, + AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, + GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, + StructId, TraitId, TypeAliasId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -580,13 +580,13 @@ impl HasResolver for DefWithBodyId { } } -impl HasResolver for ContainerId { +impl HasResolver for AssocContainerId { fn resolver(self, db: &impl DefDatabase) -> Resolver { match self { - ContainerId::TraitId(it) => it.resolver(db), - ContainerId::ImplId(it) => it.resolver(db), - ContainerId::ModuleId(it) => it.resolver(db), - ContainerId::DefWithBodyId(it) => it.resolver(db), + AssocContainerId::TraitId(it) => it.resolver(db), + AssocContainerId::ImplId(it) => it.resolver(db), + AssocContainerId::ModuleId(it) => it.resolver(db), + AssocContainerId::DefWithBodyId(it) => it.resolver(db), } } } diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 924ad3e813..6917c183b3 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -8,7 +8,7 @@ use hir_def::{ expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, path::{GenericArg, GenericArgs}, resolver::resolver_for_expr, - AdtId, ContainerId, Lookup, StructFieldId, + AdtId, AssocContainerId, Lookup, StructFieldId, }; use hir_expand::name::{name, Name}; use ra_syntax::ast::RangeOp; @@ -672,7 +672,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // add obligation for trait implementation, if this is a trait method match def { CallableDef::FunctionId(f) => { - if let ContainerId::TraitId(trait_) = f.lookup(self.db).container { + if let AssocContainerId::TraitId(trait_) = f.lookup(self.db).container { // construct a TraitDef let substs = a_ty.parameters.prefix(generics(self.db, trait_.into()).len()); diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index 31c90ea1ef..a96ab75d1f 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -5,7 +5,7 @@ use std::iter; use hir_def::{ path::{Path, PathSegment}, resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, - AssocItemId, ContainerId, Lookup, + AssocContainerId, AssocItemId, Lookup, }; use hir_expand::name::Name; @@ -209,7 +209,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { AssocItemId::TypeAliasId(_) => unreachable!(), }; let substs = match container { - ContainerId::ImplId(impl_id) => { + AssocContainerId::ImplId(impl_id) => { let impl_substs = Substs::build_for_def(self.db, impl_id) .fill(iter::repeat_with(|| self.table.new_type_var())) .build(); @@ -221,7 +221,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.unify(&impl_self_ty, &ty); Some(substs) } - ContainerId::TraitId(trait_) => { + AssocContainerId::TraitId(trait_) => { // we're picking this method let trait_substs = Substs::build_for_def(self.db, trait_) .push(ty.clone()) @@ -237,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { })); Some(substs) } - ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => None, + AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => None, }; self.write_assoc_resolution(id, item.into()); diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 7ca9e6b8a7..7310ef10d9 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -44,8 +44,8 @@ use std::sync::Arc; use std::{fmt, iter, mem}; use hir_def::{ - expr::ExprId, type_ref::Mutability, AdtId, ContainerId, DefWithBodyId, GenericDefId, HasModule, - Lookup, TraitId, TypeAliasId, + expr::ExprId, type_ref::Mutability, AdtId, AssocContainerId, DefWithBodyId, GenericDefId, + HasModule, Lookup, TraitId, TypeAliasId, }; use hir_expand::name::Name; use ra_db::{impl_intern_key, salsa, CrateId}; @@ -251,7 +251,7 @@ impl ProjectionTy { fn trait_(&self, db: &impl HirDatabase) -> TraitId { match self.associated_ty.lookup(db).container { - ContainerId::TraitId(it) => it, + AssocContainerId::TraitId(it) => it, _ => panic!("projection ty without parent trait"), } } @@ -943,7 +943,7 @@ impl HirDisplay for ApplicationTy { } TypeCtor::AssociatedType(type_alias) => { let trait_ = match type_alias.lookup(f.db).container { - ContainerId::TraitId(it) => it, + AssocContainerId::TraitId(it) => it, _ => panic!("not an associated type"), }; let trait_name = f.db.trait_data(trait_).name.clone(); diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index d0b2b016d5..1c2e7b934d 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -6,8 +6,8 @@ use std::sync::Arc; use arrayvec::ArrayVec; use hir_def::{ - lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, ContainerId, - FunctionId, HasModule, ImplId, Lookup, TraitId, + lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId, + AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, }; use hir_expand::name::Name; use ra_db::CrateId; @@ -451,12 +451,12 @@ fn transform_receiver_ty( self_ty: &Canonical, ) -> Option { let substs = match function_id.lookup(db).container { - ContainerId::TraitId(_) => Substs::build_for_def(db, function_id) + AssocContainerId::TraitId(_) => Substs::build_for_def(db, function_id) .push(self_ty.value.clone()) .fill_with_unknown() .build(), - ContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, - ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => unreachable!(), + AssocContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, + AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => unreachable!(), }; let sig = db.callable_item_signature(function_id.into()); Some(sig.params()[0].clone().subst(&substs)) diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index fc21872b2b..6a31014d8b 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,7 +9,7 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{AssocItemId, ContainerId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; +use hir_def::{AssocContainerId, AssocItemId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -542,7 +542,7 @@ pub(crate) fn associated_ty_data_query( debug!("associated_ty_data {:?}", id); let type_alias: TypeAliasId = from_chalk(db, id); let trait_ = match type_alias.lookup(db).container { - ContainerId::TraitId(t) => t, + AssocContainerId::TraitId(t) => t, _ => panic!("associated type not in trait"), }; let generic_params = generics(db, type_alias.into()); @@ -755,7 +755,7 @@ fn type_alias_associated_ty_value( ) -> Arc> { let type_alias_data = db.type_alias_data(type_alias); let impl_id = match type_alias.lookup(db).container { - ContainerId::ImplId(it) => it, + AssocContainerId::ImplId(it) => it, _ => panic!("assoc ty value should be in impl"), }; diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 34defc1a20..8b5b611ecc 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -9,7 +9,7 @@ use hir_def::{ path::Path, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, - ContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, + AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, }; use hir_expand::name::{name, Name}; @@ -155,8 +155,8 @@ fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option Some(it.into()), - ContainerId::TraitId(it) => Some(it.into()), - ContainerId::ModuleId(_) | ContainerId::DefWithBodyId(_) => None, + AssocContainerId::ImplId(it) => Some(it.into()), + AssocContainerId::TraitId(it) => Some(it.into()), + AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => None, } } From 94ad07af4bef6a70602e315bf315c6fce95618dd Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 12:07:23 +0100 Subject: [PATCH 239/312] Introduce `ContainerId` --- crates/ra_hir_def/src/body/lower.rs | 4 ++-- crates/ra_hir_def/src/lib.rs | 24 +++++++++++++++++----- crates/ra_hir_def/src/nameres/collector.rs | 9 ++++---- crates/ra_hir_def/src/resolver.rs | 18 +++++++++++----- crates/ra_hir_ty/src/infer/path.rs | 2 +- crates/ra_hir_ty/src/method_resolution.rs | 2 +- crates/ra_hir_ty/src/utils.rs | 2 +- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index afd5231cc1..0103a1aabe 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -25,7 +25,7 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, - AssocContainerId, DefWithBodyId, FunctionLoc, Intern, + ContainerId, DefWithBodyId, FunctionLoc, Intern, }; pub(super) fn lower( @@ -490,7 +490,7 @@ where } fn collect_block_items(&mut self, block: &ast::Block) { - let container = AssocContainerId::DefWithBodyId(self.def); + let container = ContainerId::DefWithBodyId(self.def).into(); for item in block.items() { match item { ast::ModuleItem::FnDef(def) => { diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 3d42762aef..5e46db1aab 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -331,13 +331,19 @@ pub struct LocalTypeParamId(RawId); impl_arena_id!(LocalTypeParamId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum AssocContainerId { +pub enum ContainerId { ModuleId(ModuleId), - ImplId(ImplId), - TraitId(TraitId), DefWithBodyId(DefWithBodyId), } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum AssocContainerId { + ContainerId(ContainerId), + ImplId(ImplId), + TraitId(TraitId), +} +impl_froms!(AssocContainerId: ContainerId); + /// A Data Type #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum AdtId { @@ -479,13 +485,21 @@ pub trait HasModule { fn module(&self, db: &impl db::DefDatabase) -> ModuleId; } +impl HasModule for ContainerId { + fn module(&self, db: &impl db::DefDatabase) -> ModuleId { + match *self { + ContainerId::ModuleId(it) => it, + ContainerId::DefWithBodyId(it) => it.module(db), + } + } +} + impl HasModule for AssocContainerId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match *self { - AssocContainerId::ModuleId(it) => it, + AssocContainerId::ContainerId(it) => it.module(db), AssocContainerId::ImplId(it) => it.lookup(db).container, AssocContainerId::TraitId(it) => it.lookup(db).container, - AssocContainerId::DefWithBodyId(it) => it.module(db), } } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 848959f7c4..0f3319f302 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -24,7 +24,7 @@ use crate::{ }, path::{ModPath, PathKind}, per_ns::PerNs, - AdtId, AssocContainerId, AstId, ConstLoc, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, + AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, }; @@ -760,10 +760,11 @@ where self.collect_derives(attrs, def); let name = def.name.clone(); + let container = ContainerId::ModuleId(module); let def: PerNs = match def.kind { raw::DefKind::Function(ast_id) => { let def = FunctionLoc { - container: AssocContainerId::ModuleId(module), + container: container.into(), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); @@ -787,7 +788,7 @@ where } raw::DefKind::Const(ast_id) => { let def = ConstLoc { - container: AssocContainerId::ModuleId(module), + container: container.into(), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); @@ -808,7 +809,7 @@ where } raw::DefKind::TypeAlias(ast_id) => { let def = TypeAliasLoc { - container: AssocContainerId::ModuleId(module), + container: container.into(), ast_id: AstId::new(self.file_id, ast_id), } .intern(self.def_collector.db); diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index d79c9813b7..af9d194f8a 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -17,9 +17,9 @@ use crate::{ nameres::{BuiltinShadowMode, CrateDefMap}, path::{ModPath, PathKind}, per_ns::PerNs, - AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, - GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, StaticId, - StructId, TraitId, TypeAliasId, TypeParamId, VariantId, + AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, + FunctionId, GenericDefId, HasModule, ImplId, LocalModuleId, Lookup, ModuleDefId, ModuleId, + StaticId, StructId, TraitId, TypeAliasId, TypeParamId, VariantId, }; #[derive(Debug, Clone, Default)] @@ -580,13 +580,21 @@ impl HasResolver for DefWithBodyId { } } +impl HasResolver for ContainerId { + fn resolver(self, db: &impl DefDatabase) -> Resolver { + match self { + ContainerId::ModuleId(it) => it.resolver(db), + ContainerId::DefWithBodyId(it) => it.resolver(db), + } + } +} + impl HasResolver for AssocContainerId { fn resolver(self, db: &impl DefDatabase) -> Resolver { match self { + AssocContainerId::ContainerId(it) => it.resolver(db), AssocContainerId::TraitId(it) => it.resolver(db), AssocContainerId::ImplId(it) => it.resolver(db), - AssocContainerId::ModuleId(it) => it.resolver(db), - AssocContainerId::DefWithBodyId(it) => it.resolver(db), } } } diff --git a/crates/ra_hir_ty/src/infer/path.rs b/crates/ra_hir_ty/src/infer/path.rs index a96ab75d1f..ffd3583675 100644 --- a/crates/ra_hir_ty/src/infer/path.rs +++ b/crates/ra_hir_ty/src/infer/path.rs @@ -237,7 +237,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { })); Some(substs) } - AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => None, + AssocContainerId::ContainerId(_) => None, }; self.write_assoc_resolution(id, item.into()); diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 1c2e7b934d..1b2f4014c6 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -456,7 +456,7 @@ fn transform_receiver_ty( .fill_with_unknown() .build(), AssocContainerId::ImplId(impl_id) => inherent_impl_substs(db, impl_id, &self_ty)?, - AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => unreachable!(), + AssocContainerId::ContainerId(_) => unreachable!(), }; let sig = db.callable_item_signature(function_id.into()); Some(sig.params()[0].clone().subst(&substs)) diff --git a/crates/ra_hir_ty/src/utils.rs b/crates/ra_hir_ty/src/utils.rs index 8b5b611ecc..0b1806a84f 100644 --- a/crates/ra_hir_ty/src/utils.rs +++ b/crates/ra_hir_ty/src/utils.rs @@ -157,6 +157,6 @@ fn parent_generic_def(db: &impl DefDatabase, def: GenericDefId) -> Option Some(it.into()), AssocContainerId::TraitId(it) => Some(it.into()), - AssocContainerId::ModuleId(_) | AssocContainerId::DefWithBodyId(_) => None, + AssocContainerId::ContainerId(_) => None, } } From ac5a3f611b05dbedd286169539335ae9f0fbb7b0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 12:20:49 +0100 Subject: [PATCH 240/312] Support for nested ADT --- crates/ra_hir/src/code_model.rs | 12 +++++----- crates/ra_hir_def/src/body/lower.rs | 26 ++++++++++++++++------ crates/ra_hir_def/src/lib.rs | 9 ++++---- crates/ra_hir_def/src/nameres/collector.rs | 6 ++--- crates/ra_hir_ty/src/lower.rs | 4 ++-- 5 files changed, 35 insertions(+), 22 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 8dbc0d6678..d20e9de632 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -269,7 +269,7 @@ pub struct Struct { impl Struct { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.lookup(db).container } + Module { id: self.id.lookup(db).container.module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -290,7 +290,7 @@ impl Struct { } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.lookup(db).container.krate, self.id) + Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id) } fn variant_data(self, db: &impl DefDatabase) -> Arc { @@ -309,11 +309,11 @@ impl Union { } pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.lookup(db).container } + Module { id: self.id.lookup(db).container.module(db) } } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.lookup(db).container.krate, self.id) + Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id) } pub fn fields(self, db: &impl HirDatabase) -> Vec { @@ -337,7 +337,7 @@ pub struct Enum { impl Enum { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.lookup(db).container } + Module { id: self.id.lookup(db).container.module(db) } } pub fn krate(self, db: &impl DefDatabase) -> Option { @@ -357,7 +357,7 @@ impl Enum { } pub fn ty(self, db: &impl HirDatabase) -> Type { - Type::from_def(db, self.id.lookup(db).container.krate, self.id) + Type::from_def(db, self.id.lookup(db).container.module(db).krate, self.id) } } diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 0103a1aabe..0d3f946df6 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -25,7 +25,7 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, - ContainerId, DefWithBodyId, FunctionLoc, Intern, + ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StructLoc, UnionLoc, }; pub(super) fn lower( @@ -490,16 +490,28 @@ where } fn collect_block_items(&mut self, block: &ast::Block) { - let container = ContainerId::DefWithBodyId(self.def).into(); + let container = ContainerId::DefWithBodyId(self.def); for item in block.items() { - match item { + let def: ModuleDefId = match item { ast::ModuleItem::FnDef(def) => { let ast_id = self.expander.ast_id(&def); - self.body.defs.push(FunctionLoc { container, ast_id }.intern(self.db).into()) + FunctionLoc { container: container.into(), ast_id }.intern(self.db).into() } - // FIXME: handle other items - _ => (), - } + ast::ModuleItem::StructDef(def) => { + let ast_id = self.expander.ast_id(&def); + StructLoc { container, ast_id }.intern(self.db).into() + } + ast::ModuleItem::EnumDef(def) => { + let ast_id = self.expander.ast_id(&def); + EnumLoc { container, ast_id }.intern(self.db).into() + } + ast::ModuleItem::UnionDef(def) => { + let ast_id = self.expander.ast_id(&def); + UnionLoc { container, ast_id }.intern(self.db).into() + } + _ => continue, + }; + self.body.defs.push(def) } } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 5e46db1aab..a82de7dec3 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -95,7 +95,7 @@ impl_intern_key!(StructId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StructLoc { - pub container: ModuleId, + pub container: ContainerId, pub ast_id: AstId, } @@ -119,7 +119,7 @@ impl_intern_key!(UnionId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct UnionLoc { - pub container: ModuleId, + pub container: ContainerId, pub ast_id: AstId, } @@ -143,7 +143,7 @@ impl_intern_key!(EnumId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct EnumLoc { - pub container: ModuleId, + pub container: ContainerId, pub ast_id: AstId, } @@ -529,6 +529,7 @@ impl HasModule for AdtId { AdtId::UnionId(it) => it.lookup(db).container, AdtId::EnumId(it) => it.lookup(db).container, } + .module(db) } } @@ -550,7 +551,7 @@ impl HasModule for GenericDefId { GenericDefId::TraitId(it) => it.lookup(db).container, GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, - GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container, + GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), GenericDefId::ConstId(it) => it.lookup(db).module(db), } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 0f3319f302..1b39af61e4 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -772,17 +772,17 @@ where PerNs::values(def.into()) } raw::DefKind::Struct(ast_id) => { - let def = StructLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); PerNs::both(def.into(), def.into()) } raw::DefKind::Union(ast_id) => { - let def = UnionLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); PerNs::both(def.into(), def.into()) } raw::DefKind::Enum(ast_id) => { - let def = EnumLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); PerNs::types(def.into()) } diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 2b84309d7a..af3db2e1d7 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs @@ -697,8 +697,8 @@ impl CallableDef { pub fn krate(self, db: &impl HirDatabase) -> CrateId { match self { CallableDef::FunctionId(f) => f.lookup(db).module(db), - CallableDef::StructId(s) => s.lookup(db).container, - CallableDef::EnumVariantId(e) => e.parent.lookup(db).container, + CallableDef::StructId(s) => s.lookup(db).container.module(db), + CallableDef::EnumVariantId(e) => e.parent.lookup(db).container.module(db), } .krate } From fe1b160dcfdeb3f582ccae1440c9580ade0beb39 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 12:22:55 +0100 Subject: [PATCH 241/312] Support for nested statics, consts and type aliases --- crates/ra_hir_def/src/body/lower.rs | 15 ++++++++++++++- crates/ra_hir_def/src/lib.rs | 6 +++--- crates/ra_hir_def/src/nameres/collector.rs | 2 +- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 0d3f946df6..b61f924b77 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -25,7 +25,8 @@ use crate::{ path::GenericArgs, path::Path, type_ref::{Mutability, TypeRef}, - ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StructLoc, UnionLoc, + ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc, + StructLoc, TypeAliasLoc, UnionLoc, }; pub(super) fn lower( @@ -497,6 +498,18 @@ where let ast_id = self.expander.ast_id(&def); FunctionLoc { container: container.into(), ast_id }.intern(self.db).into() } + ast::ModuleItem::TypeAliasDef(def) => { + let ast_id = self.expander.ast_id(&def); + TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into() + } + ast::ModuleItem::ConstDef(def) => { + let ast_id = self.expander.ast_id(&def); + ConstLoc { container: container.into(), ast_id }.intern(self.db).into() + } + ast::ModuleItem::StaticDef(def) => { + let ast_id = self.expander.ast_id(&def); + StaticLoc { container, ast_id }.intern(self.db).into() + } ast::ModuleItem::StructDef(def) => { let ast_id = self.expander.ast_id(&def); StructLoc { container, ast_id }.intern(self.db).into() diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index a82de7dec3..9b192b597a 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -211,7 +211,7 @@ impl_intern_key!(StaticId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct StaticLoc { - pub container: ModuleId, + pub container: ContainerId, pub ast_id: AstId, } @@ -558,7 +558,7 @@ impl HasModule for GenericDefId { } impl HasModule for StaticLoc { - fn module(&self, _db: &impl db::DefDatabase) -> ModuleId { - self.container + fn module(&self, db: &impl db::DefDatabase) -> ModuleId { + self.container.module(db) } } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 1b39af61e4..74c3d4670d 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -796,7 +796,7 @@ where PerNs::values(def.into()) } raw::DefKind::Static(ast_id) => { - let def = StaticLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); PerNs::values(def.into()) From f42697e54b9d0a040011cb04c266d51710e249f1 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 12:29:25 +0100 Subject: [PATCH 242/312] Support for nested traits --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir_def/src/body/lower.rs | 11 +++++++++-- crates/ra_hir_def/src/lib.rs | 6 +++--- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_ty/src/traits/chalk.rs | 6 ++++-- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index d20e9de632..35e1f752be 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -553,7 +553,7 @@ pub struct Trait { impl Trait { pub fn module(self, db: &impl DefDatabase) -> Module { - Module { id: self.id.lookup(db).container } + Module { id: self.id.lookup(db).container.module(db) } } pub fn name(self, db: &impl DefDatabase) -> Name { diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index b61f924b77..853e17bae7 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -26,7 +26,7 @@ use crate::{ path::Path, type_ref::{Mutability, TypeRef}, ConstLoc, ContainerId, DefWithBodyId, EnumLoc, FunctionLoc, Intern, ModuleDefId, StaticLoc, - StructLoc, TypeAliasLoc, UnionLoc, + StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, }; pub(super) fn lower( @@ -522,7 +522,14 @@ where let ast_id = self.expander.ast_id(&def); UnionLoc { container, ast_id }.intern(self.db).into() } - _ => continue, + ast::ModuleItem::TraitDef(def) => { + let ast_id = self.expander.ast_id(&def); + TraitLoc { container, ast_id }.intern(self.db).into() + } + ast::ModuleItem::ImplBlock(_) + | ast::ModuleItem::UseItem(_) + | ast::ModuleItem::ExternCrateItem(_) + | ast::ModuleItem::Module(_) => continue, }; self.body.defs.push(def) } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 9b192b597a..140eccf267 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -235,7 +235,7 @@ impl_intern_key!(TraitId); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct TraitLoc { - pub container: ModuleId, + pub container: ContainerId, pub ast_id: AstId, } @@ -499,7 +499,7 @@ impl HasModule for AssocContainerId { match *self { AssocContainerId::ContainerId(it) => it.module(db), AssocContainerId::ImplId(it) => it.lookup(db).container, - AssocContainerId::TraitId(it) => it.lookup(db).container, + AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), } } } @@ -548,7 +548,7 @@ impl HasModule for GenericDefId { match self { GenericDefId::FunctionId(it) => it.lookup(db).module(db), GenericDefId::AdtId(it) => it.module(db), - GenericDefId::TraitId(it) => it.lookup(db).container, + GenericDefId::TraitId(it) => it.lookup(db).container.module(db), GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), GenericDefId::ImplId(it) => it.lookup(db).container, GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 74c3d4670d..a1ea130e08 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -802,7 +802,7 @@ where PerNs::values(def.into()) } raw::DefKind::Trait(ast_id) => { - let def = TraitLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); PerNs::types(def.into()) diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 6a31014d8b..dd4fa9664a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -9,7 +9,9 @@ use chalk_ir::{ }; use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; -use hir_def::{AssocContainerId, AssocItemId, GenericDefId, ImplId, Lookup, TraitId, TypeAliasId}; +use hir_def::{ + AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId, +}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -591,7 +593,7 @@ pub(crate) fn trait_datum_query( let bound_vars = Substs::bound_vars(&generic_params); let flags = chalk_rust_ir::TraitFlags { auto: trait_data.auto, - upstream: trait_.lookup(db).container.krate != krate, + upstream: trait_.lookup(db).container.module(db).krate != krate, non_enumerable: true, coinductive: false, // only relevant for Chalk testing // FIXME set these flags correctly From 957c0171e63631f67d732f4ce53dc8bfe2602e71 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 13:11:01 +0100 Subject: [PATCH 243/312] Remove more copy-paste --- crates/ra_hir_def/src/lib.rs | 89 +++++++++++++----------------------- 1 file changed, 31 insertions(+), 58 deletions(-) diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 140eccf267..042fd3f8ba 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -45,7 +45,7 @@ use std::hash::Hash; use hir_expand::{ast_id_map::FileAstId, AstId, HirFileId, InFile, MacroDefId}; use ra_arena::{impl_arena_id, RawId}; use ra_db::{impl_intern_key, salsa, CrateId}; -use ra_syntax::ast; +use ra_syntax::{ast, AstNode}; use crate::builtin_type::BuiltinType; @@ -65,15 +65,22 @@ pub struct ModuleId { pub struct LocalModuleId(RawId); impl_arena_id!(LocalModuleId); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ItemLoc { + pub container: ContainerId, + pub ast_id: AstId, +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct AssocItemLoc { + pub container: AssocContainerId, + pub ast_id: AstId, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(salsa::InternId); impl_intern_key!(FunctionId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FunctionLoc { - pub container: AssocContainerId, - pub ast_id: AstId, -} +type FunctionLoc = AssocItemLoc; impl Intern for FunctionLoc { type ID = FunctionId; @@ -92,12 +99,7 @@ impl Lookup for FunctionId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructId(salsa::InternId); impl_intern_key!(StructId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StructLoc { - pub container: ContainerId, - pub ast_id: AstId, -} +pub type StructLoc = ItemLoc; impl Intern for StructLoc { type ID = StructId; @@ -116,12 +118,7 @@ impl Lookup for StructId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UnionId(salsa::InternId); impl_intern_key!(UnionId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UnionLoc { - pub container: ContainerId, - pub ast_id: AstId, -} +pub type UnionLoc = ItemLoc; impl Intern for UnionLoc { type ID = UnionId; @@ -140,12 +137,7 @@ impl Lookup for UnionId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumId(salsa::InternId); impl_intern_key!(EnumId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct EnumLoc { - pub container: ContainerId, - pub ast_id: AstId, -} +pub type EnumLoc = ItemLoc; impl Intern for EnumLoc { type ID = EnumId; @@ -185,11 +177,7 @@ impl_arena_id!(LocalStructFieldId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); impl_intern_key!(ConstId); -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ConstLoc { - pub container: AssocContainerId, - pub ast_id: AstId, -} +type ConstLoc = AssocItemLoc; impl Intern for ConstLoc { type ID = ConstId; @@ -208,12 +196,7 @@ impl Lookup for ConstId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaticId(salsa::InternId); impl_intern_key!(StaticId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct StaticLoc { - pub container: ContainerId, - pub ast_id: AstId, -} +pub type StaticLoc = ItemLoc; impl Intern for StaticLoc { type ID = StaticId; @@ -232,12 +215,7 @@ impl Lookup for StaticId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TraitId(salsa::InternId); impl_intern_key!(TraitId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TraitLoc { - pub container: ContainerId, - pub ast_id: AstId, -} +pub type TraitLoc = ItemLoc; impl Intern for TraitLoc { type ID = TraitId; @@ -256,12 +234,7 @@ impl Lookup for TraitId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); impl_intern_key!(TypeAliasId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct TypeAliasLoc { - pub container: AssocContainerId, - pub ast_id: AstId, -} +type TypeAliasLoc = AssocItemLoc; impl Intern for TypeAliasLoc { type ID = TypeAliasId; @@ -301,6 +274,16 @@ impl Lookup for ImplId { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct TypeParamId { + pub parent: GenericDefId, + pub local_id: LocalTypeParamId, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocalTypeParamId(RawId); +impl_arena_id!(LocalTypeParamId); + macro_rules! impl_froms { ($e:ident: $($v:ident $(($($sv:ident),*))?),*) => { $( @@ -320,16 +303,6 @@ macro_rules! impl_froms { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct TypeParamId { - pub parent: GenericDefId, - pub local_id: LocalTypeParamId, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalTypeParamId(RawId); -impl_arena_id!(LocalTypeParamId); - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum ContainerId { ModuleId(ModuleId), From d137df0137dab36819efada901e92cd2733f292b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 13:19:41 +0100 Subject: [PATCH 244/312] Remove more copy-paste --- crates/ra_hir_def/src/lib.rs | 150 +++++++---------------------------- 1 file changed, 29 insertions(+), 121 deletions(-) diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 042fd3f8ba..faeb2fc8ac 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -77,81 +77,45 @@ pub struct AssocItemLoc { pub ast_id: AstId, } +macro_rules! impl_intern { + ($id:ident, $loc:ident, $intern:ident, $lookup:ident) => { + impl_intern_key!($id); + + impl Intern for $loc { + type ID = $id; + fn intern(self, db: &impl db::DefDatabase) -> $id { + db.$intern(self) + } + } + + impl Lookup for $id { + type Data = $loc; + fn lookup(&self, db: &impl db::DefDatabase) -> $loc { + db.$lookup(*self) + } + } + }; +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct FunctionId(salsa::InternId); -impl_intern_key!(FunctionId); type FunctionLoc = AssocItemLoc; - -impl Intern for FunctionLoc { - type ID = FunctionId; - fn intern(self, db: &impl db::DefDatabase) -> FunctionId { - db.intern_function(self) - } -} - -impl Lookup for FunctionId { - type Data = FunctionLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> FunctionLoc { - db.lookup_intern_function(*self) - } -} +impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructId(salsa::InternId); -impl_intern_key!(StructId); -pub type StructLoc = ItemLoc; - -impl Intern for StructLoc { - type ID = StructId; - fn intern(self, db: &impl db::DefDatabase) -> StructId { - db.intern_struct(self) - } -} - -impl Lookup for StructId { - type Data = StructLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> StructLoc { - db.lookup_intern_struct(*self) - } -} +type StructLoc = ItemLoc; +impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct UnionId(salsa::InternId); -impl_intern_key!(UnionId); pub type UnionLoc = ItemLoc; - -impl Intern for UnionLoc { - type ID = UnionId; - fn intern(self, db: &impl db::DefDatabase) -> UnionId { - db.intern_union(self) - } -} - -impl Lookup for UnionId { - type Data = UnionLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> UnionLoc { - db.lookup_intern_union(*self) - } -} +impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct EnumId(salsa::InternId); -impl_intern_key!(EnumId); pub type EnumLoc = ItemLoc; - -impl Intern for EnumLoc { - type ID = EnumId; - fn intern(self, db: &impl db::DefDatabase) -> EnumId { - db.intern_enum(self) - } -} - -impl Lookup for EnumId { - type Data = EnumLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> EnumLoc { - db.lookup_intern_enum(*self) - } -} +impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum); // FIXME: rename to `VariantId`, only enums can ave variants #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -176,79 +140,23 @@ impl_arena_id!(LocalStructFieldId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ConstId(salsa::InternId); -impl_intern_key!(ConstId); type ConstLoc = AssocItemLoc; - -impl Intern for ConstLoc { - type ID = ConstId; - fn intern(self, db: &impl db::DefDatabase) -> ConstId { - db.intern_const(self) - } -} - -impl Lookup for ConstId { - type Data = ConstLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> ConstLoc { - db.lookup_intern_const(*self) - } -} +impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StaticId(salsa::InternId); -impl_intern_key!(StaticId); pub type StaticLoc = ItemLoc; - -impl Intern for StaticLoc { - type ID = StaticId; - fn intern(self, db: &impl db::DefDatabase) -> StaticId { - db.intern_static(self) - } -} - -impl Lookup for StaticId { - type Data = StaticLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> StaticLoc { - db.lookup_intern_static(*self) - } -} +impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TraitId(salsa::InternId); -impl_intern_key!(TraitId); pub type TraitLoc = ItemLoc; - -impl Intern for TraitLoc { - type ID = TraitId; - fn intern(self, db: &impl db::DefDatabase) -> TraitId { - db.intern_trait(self) - } -} - -impl Lookup for TraitId { - type Data = TraitLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> TraitLoc { - db.lookup_intern_trait(*self) - } -} +impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeAliasId(salsa::InternId); -impl_intern_key!(TypeAliasId); type TypeAliasLoc = AssocItemLoc; - -impl Intern for TypeAliasLoc { - type ID = TypeAliasId; - fn intern(self, db: &impl db::DefDatabase) -> TypeAliasId { - db.intern_type_alias(self) - } -} - -impl Lookup for TypeAliasId { - type Data = TypeAliasLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> TypeAliasLoc { - db.lookup_intern_type_alias(*self) - } -} +impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplId(salsa::InternId); From 1234dda9ee60a19a83a9664c2e1208247566b49b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 13:47:44 +0100 Subject: [PATCH 245/312] Use generic ItemLoc for impls --- crates/ra_hir/src/code_model.rs | 4 ++-- crates/ra_hir_def/src/lib.rs | 27 ++++------------------ crates/ra_hir_def/src/nameres/collector.rs | 3 ++- crates/ra_hir_ty/src/method_resolution.rs | 2 +- crates/ra_hir_ty/src/traits/chalk.rs | 2 +- 5 files changed, 10 insertions(+), 28 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 35e1f752be..ecf883272d 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -754,7 +754,7 @@ impl ImplBlock { let environment = TraitEnvironment::lower(db, &resolver); let ty = Ty::from_hir(db, &resolver, &impl_data.target_type); Type { - krate: self.id.lookup(db).container.krate, + krate: self.id.lookup(db).container.module(db).krate, ty: InEnvironment { value: ty, environment }, } } @@ -768,7 +768,7 @@ impl ImplBlock { } pub fn module(&self, db: &impl DefDatabase) -> Module { - self.id.lookup(db).container.into() + self.id.lookup(db).container.module(db).into() } pub fn krate(&self, db: &impl DefDatabase) -> Crate { diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index faeb2fc8ac..d11b573e5f 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -160,27 +160,8 @@ impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_al #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ImplId(salsa::InternId); -impl_intern_key!(ImplId); - -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct ImplLoc { - pub container: ModuleId, - pub ast_id: AstId, -} - -impl Intern for ImplLoc { - type ID = ImplId; - fn intern(self, db: &impl db::DefDatabase) -> ImplId { - db.intern_impl(self) - } -} - -impl Lookup for ImplId { - type Data = ImplLoc; - fn lookup(&self, db: &impl db::DefDatabase) -> ImplLoc { - db.lookup_intern_impl(*self) - } -} +type ImplLoc = ItemLoc; +impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TypeParamId { @@ -379,7 +360,7 @@ impl HasModule for AssocContainerId { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { match *self { AssocContainerId::ContainerId(it) => it.module(db), - AssocContainerId::ImplId(it) => it.lookup(db).container, + AssocContainerId::ImplId(it) => it.lookup(db).container.module(db), AssocContainerId::TraitId(it) => it.lookup(db).container.module(db), } } @@ -431,7 +412,7 @@ impl HasModule for GenericDefId { GenericDefId::AdtId(it) => it.module(db), GenericDefId::TraitId(it) => it.lookup(db).container.module(db), GenericDefId::TypeAliasId(it) => it.lookup(db).module(db), - GenericDefId::ImplId(it) => it.lookup(db).container, + GenericDefId::ImplId(it) => it.lookup(db).container.module(db), GenericDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db), GenericDefId::ConstId(it) => it.lookup(db).module(db), } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index a1ea130e08..e68bf48688 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -661,9 +661,10 @@ where krate: self.def_collector.def_map.krate, local_id: self.module_id, }; + let container = ContainerId::ModuleId(module); let ast_id = self.raw_items[imp].ast_id; let impl_id = - ImplLoc { container: module, ast_id: AstId::new(self.file_id, ast_id) } + ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); self.def_collector.def_map.modules[self.module_id].impls.push(impl_id) } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 1b2f4014c6..92fb4c0817 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -134,7 +134,7 @@ impl Ty { LangItemTarget::ImplBlockId(it) => Some(it), _ => None, }) - .map(|it| it.lookup(db).container.krate) + .map(|it| it.lookup(db).container.module(db).krate) .collect(); Some(res) } diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index dd4fa9664a..5eb032d86a 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -673,7 +673,7 @@ fn impl_block_datum( let bound_vars = Substs::bound_vars(&generic_params); let trait_ref = trait_ref.subst(&bound_vars); let trait_ = trait_ref.trait_; - let impl_type = if impl_id.lookup(db).container.krate == krate { + let impl_type = if impl_id.lookup(db).container.module(db).krate == krate { chalk_rust_ir::ImplType::Local } else { chalk_rust_ir::ImplType::External From 2d8a001465de8857090807f39fe667d98b05da30 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 13:58:09 +0100 Subject: [PATCH 246/312] Reduce copy-paste some more --- crates/ra_hir_def/src/lib.rs | 14 +----- crates/ra_hir_def/src/src.rs | 82 ++++-------------------------------- 2 files changed, 9 insertions(+), 87 deletions(-) diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index d11b573e5f..8ed1599ffb 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -366,19 +366,7 @@ impl HasModule for AssocContainerId { } } -impl HasModule for FunctionLoc { - fn module(&self, db: &impl db::DefDatabase) -> ModuleId { - self.container.module(db) - } -} - -impl HasModule for TypeAliasLoc { - fn module(&self, db: &impl db::DefDatabase) -> ModuleId { - self.container.module(db) - } -} - -impl HasModule for ConstLoc { +impl HasModule for AssocItemLoc { fn module(&self, db: &impl db::DefDatabase) -> ModuleId { self.container.module(db) } diff --git a/crates/ra_hir_def/src/src.rs b/crates/ra_hir_def/src/src.rs index 20200d1db4..499375b803 100644 --- a/crates/ra_hir_def/src/src.rs +++ b/crates/ra_hir_def/src/src.rs @@ -2,94 +2,28 @@ use hir_expand::InFile; use ra_arena::map::ArenaMap; -use ra_syntax::ast; +use ra_syntax::AstNode; -use crate::{ - db::DefDatabase, ConstLoc, EnumLoc, FunctionLoc, ImplLoc, StaticLoc, StructLoc, TraitLoc, - TypeAliasLoc, UnionLoc, -}; +use crate::{db::DefDatabase, AssocItemLoc, ItemLoc}; pub trait HasSource { type Value; fn source(&self, db: &impl DefDatabase) -> InFile; } -impl HasSource for FunctionLoc { - type Value = ast::FnDef; +impl HasSource for AssocItemLoc { + type Value = N; - fn source(&self, db: &impl DefDatabase) -> InFile { + fn source(&self, db: &impl DefDatabase) -> InFile { let node = self.ast_id.to_node(db); InFile::new(self.ast_id.file_id, node) } } -impl HasSource for TypeAliasLoc { - type Value = ast::TypeAliasDef; +impl HasSource for ItemLoc { + type Value = N; - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for ConstLoc { - type Value = ast::ConstDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for StaticLoc { - type Value = ast::StaticDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for ImplLoc { - type Value = ast::ImplBlock; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for TraitLoc { - type Value = ast::TraitDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for StructLoc { - type Value = ast::StructDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for UnionLoc { - type Value = ast::UnionDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { - let node = self.ast_id.to_node(db); - InFile::new(self.ast_id.file_id, node) - } -} - -impl HasSource for EnumLoc { - type Value = ast::EnumDef; - - fn source(&self, db: &impl DefDatabase) -> InFile { + fn source(&self, db: &impl DefDatabase) -> InFile { let node = self.ast_id.to_node(db); InFile::new(self.ast_id.file_id, node) } From d057afb945b34cbefc1f0722f4dd0ff2758b760b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 14:10:31 +0100 Subject: [PATCH 247/312] Improve highlighting test --- crates/ra_ide/src/snapshots/highlighting.html | 4 +++- crates/ra_ide/src/snapshots/rainbow_highlighting.html | 1 + crates/ra_ide/src/syntax_highlighting.rs | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 2157139f66..748fd95588 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .comment { color: #7F9F7F; } .string { color: #CC9393; } +.field { color: #94BFF3; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } @@ -39,7 +40,8 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd let mut vec = Vec::new(); if true { - vec.push(Foo { x: 0, y: 1 }); + let x = 92; + vec.push(Foo { x, y: 1 }); } unsafe { vec.set_len(0); } diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index 871a52cf62..110556c092 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html @@ -5,6 +5,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .comment { color: #7F9F7F; } .string { color: #CC9393; } +.field { color: #94BFF3; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 15e75709c1..63f5d3cb03 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -282,6 +282,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd .comment { color: #7F9F7F; } .string { color: #CC9393; } +.field { color: #94BFF3; } .function { color: #93E0E3; } .parameter { color: #94BFF3; } .text { color: #DCDCCC; } @@ -327,7 +328,8 @@ fn main() { let mut vec = Vec::new(); if true { - vec.push(Foo { x: 0, y: 1 }); + let x = 92; + vec.push(Foo { x, y: 1 }); } unsafe { vec.set_len(0); } From 77af7b087fd95140c28b30bf7127d7d83fb0dcc6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 14:11:49 +0100 Subject: [PATCH 248/312] Fix highlighting for field init shorthand --- crates/ra_ide/src/snapshots/highlighting.html | 2 +- crates/ra_ide/src/syntax_highlighting.rs | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 748fd95588..a097cf8e84 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html @@ -41,7 +41,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd let mut vec = Vec::new(); if true { let x = 92; - vec.push(Foo { x, y: 1 }); + vec.push(Foo { x, y: 1 }); } unsafe { vec.set_len(0); } diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 63f5d3cb03..657c7b21a5 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -102,11 +102,10 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec tags::LITERAL_COMMENT, STRING | RAW_STRING | RAW_BYTE_STRING | BYTE_STRING => tags::LITERAL_STRING, ATTR => tags::LITERAL_ATTRIBUTE, + // Special-case field init shorthand + NAME_REF if node.parent().and_then(ast::RecordField::cast).is_some() => tags::FIELD, + NAME_REF if node.ancestors().any(|it| it.kind() == ATTR) => continue, NAME_REF => { - if node.ancestors().any(|it| it.kind() == ATTR) { - continue; - } - let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); let name_kind = classify_name_ref(db, InFile::new(file_id.into(), &name_ref)).map(|d| d.kind); From 3d4b48e481da35f19366514c0e22ed42fef037a0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 14:47:01 +0100 Subject: [PATCH 249/312] Fix resolve for field init shorthand --- crates/ra_hir/src/from_source.rs | 16 ++++--- crates/ra_hir/src/source_binder.rs | 8 +++- crates/ra_hir_def/src/body.rs | 5 +++ crates/ra_ide/src/goto_definition.rs | 57 +++++++++++++++--------- crates/ra_ide/src/marks.rs | 9 ++-- crates/ra_ide/src/references/classify.rs | 9 ++-- 6 files changed, 68 insertions(+), 36 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 3b6454a1d8..42ca55fe72 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -1,4 +1,6 @@ -//! FIXME: write short doc here +//! Finds a corresponding hir data structure for a syntax node in a specific +//! file. + use hir_def::{ child_by_source::ChildBySource, dyn_map::DynMap, keys, keys::Key, nameres::ModuleSource, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, ImplId, ModuleId, @@ -11,14 +13,14 @@ use ra_syntax::{ }; use crate::{ - db::{AstDatabase, DefDatabase, HirDatabase}, + db::{DefDatabase, HirDatabase}, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, ImplBlock, InFile, Local, MacroDef, Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub trait FromSource: Sized { type Ast; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option; + fn from_source(db: &impl DefDatabase, src: InFile) -> Option; } pub trait FromSourceByContainer: Sized { @@ -32,7 +34,7 @@ where T: From<::Id>, { type Ast = ::Ast; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { analyze_container(db, src.as_ref().map(|it| it.syntax()))[T::KEY] .get(&src) .copied() @@ -64,7 +66,7 @@ from_source_by_container_impls![ impl FromSource for MacroDef { type Ast = ast::MacroCall; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let kind = MacroDefKind::Declarative; let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); @@ -80,7 +82,7 @@ impl FromSource for MacroDef { impl FromSource for EnumVariant { type Ast = ast::EnumVariant; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let parent_enum = src.value.parent_enum(); let src_enum = InFile { file_id: src.file_id, value: parent_enum }; let parent_enum = Enum::from_source(db, src_enum)?; @@ -93,7 +95,7 @@ impl FromSource for EnumVariant { impl FromSource for StructField { type Ast = FieldSource; - fn from_source(db: &(impl DefDatabase + AstDatabase), src: InFile) -> Option { + fn from_source(db: &impl DefDatabase, src: InFile) -> Option { let src = src.as_ref(); // FIXME this is buggy diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index d326169b33..b60a6b87e4 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -237,7 +237,13 @@ impl SourceAnalyzer { } pub fn resolve_record_field(&self, field: &ast::RecordField) -> Option { - let expr_id = self.expr_id(&field.expr()?)?; + let expr_id = match field.expr() { + Some(it) => self.expr_id(&it)?, + None => { + let src = InFile { file_id: self.file_id, value: field }; + self.body_source_map.as_ref()?.field_init_shorthand_expr(src)? + } + }; self.infer.as_ref()?.record_field_resolution(expr_id).map(|it| it.into()) } diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 92c32b080c..401fe0b9b5 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -229,6 +229,11 @@ impl BodySourceMap { self.expr_map.get(&src).cloned() } + pub fn field_init_shorthand_expr(&self, node: InFile<&ast::RecordField>) -> Option { + let src = node.map(|it| Either::Right(AstPtr::new(it))); + self.expr_map.get(&src).cloned() + } + pub fn pat_syntax(&self, pat: PatId) -> Option { self.pat_map_back.get(pat).copied() } diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index ee4ae3e037..9b57447897 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -258,7 +258,7 @@ mod tests { } #[test] - fn goto_definition_works_in_items() { + fn goto_def_in_items() { check_goto( " //- /lib.rs @@ -271,7 +271,7 @@ mod tests { } #[test] - fn goto_definition_works_at_start_of_item() { + fn goto_def_at_start_of_item() { check_goto( " //- /lib.rs @@ -305,7 +305,7 @@ mod tests { } #[test] - fn goto_definition_works_for_module_declaration() { + fn goto_def_for_module_declaration() { check_goto( " //- /lib.rs @@ -332,8 +332,8 @@ mod tests { } #[test] - fn goto_definition_works_for_macros() { - covers!(goto_definition_works_for_macros); + fn goto_def_for_macros() { + covers!(goto_def_for_macros); check_goto( " //- /lib.rs @@ -349,8 +349,8 @@ mod tests { } #[test] - fn goto_definition_works_for_macros_from_other_crates() { - covers!(goto_definition_works_for_macros); + fn goto_def_for_macros_from_other_crates() { + covers!(goto_def_for_macros); check_goto( " //- /lib.rs @@ -369,7 +369,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macros_in_use_tree() { + fn goto_def_for_macros_in_use_tree() { check_goto( " //- /lib.rs @@ -385,7 +385,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macro_defined_fn_with_arg() { + fn goto_def_for_macro_defined_fn_with_arg() { check_goto( " //- /lib.rs @@ -405,7 +405,7 @@ mod tests { } #[test] - fn goto_definition_works_for_macro_defined_fn_no_arg() { + fn goto_def_for_macro_defined_fn_no_arg() { check_goto( " //- /lib.rs @@ -425,8 +425,8 @@ mod tests { } #[test] - fn goto_definition_works_for_methods() { - covers!(goto_definition_works_for_methods); + fn goto_def_for_methods() { + covers!(goto_def_for_methods); check_goto( " //- /lib.rs @@ -445,8 +445,8 @@ mod tests { } #[test] - fn goto_definition_works_for_fields() { - covers!(goto_definition_works_for_fields); + fn goto_def_for_fields() { + covers!(goto_def_for_fields); check_goto( " //- /lib.rs @@ -464,8 +464,8 @@ mod tests { } #[test] - fn goto_definition_works_for_record_fields() { - covers!(goto_definition_works_for_record_fields); + fn goto_def_for_record_fields() { + covers!(goto_def_for_record_fields); check_goto( " //- /lib.rs @@ -502,7 +502,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_inherent_methods() { + fn goto_def_for_ufcs_inherent_methods() { check_goto( " //- /lib.rs @@ -521,7 +521,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_trait_methods_through_traits() { + fn goto_def_for_ufcs_trait_methods_through_traits() { check_goto( " //- /lib.rs @@ -539,7 +539,7 @@ mod tests { } #[test] - fn goto_definition_works_for_ufcs_trait_methods_through_self() { + fn goto_def_for_ufcs_trait_methods_through_self() { check_goto( " //- /lib.rs @@ -654,7 +654,7 @@ mod tests { } #[test] - fn goto_definition_works_when_used_on_definition_name_itself() { + fn goto_def_when_used_on_definition_name_itself() { check_goto( " //- /lib.rs @@ -875,4 +875,21 @@ mod tests { "x", ); } + + #[test] + fn goto_def_for_field_init_shorthand() { + covers!(goto_def_for_field_init_shorthand); + check_goto( + " + //- /lib.rs + struct Foo { x: i32 } + fn main() { + let x = 92; + Foo { x<|> }; + } + ", + "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", + "x: i32|x", + ) + } } diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs index 848ae4dc74..077a44473b 100644 --- a/crates/ra_ide/src/marks.rs +++ b/crates/ra_ide/src/marks.rs @@ -3,10 +3,11 @@ test_utils::marks!( inserts_angle_brackets_for_generics inserts_parens_for_function_calls - goto_definition_works_for_macros - goto_definition_works_for_methods - goto_definition_works_for_fields - goto_definition_works_for_record_fields + goto_def_for_macros + goto_def_for_methods + goto_def_for_fields + goto_def_for_record_fields + goto_def_for_field_init_shorthand call_info_bad_offset dont_complete_current_use dont_complete_primitive_in_use diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index c1f091ec08..3483a7176c 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs @@ -134,21 +134,22 @@ pub(crate) fn classify_name_ref( let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { - tested_by!(goto_definition_works_for_methods); + tested_by!(goto_def_for_methods); if let Some(func) = analyzer.resolve_method_call(&method_call) { return Some(from_assoc_item(db, func.into())); } } if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { - tested_by!(goto_definition_works_for_fields); + tested_by!(goto_def_for_fields); if let Some(field) = analyzer.resolve_field(&field_expr) { return Some(from_struct_field(db, field)); } } if let Some(record_field) = ast::RecordField::cast(parent.clone()) { - tested_by!(goto_definition_works_for_record_fields); + tested_by!(goto_def_for_record_fields); + tested_by!(goto_def_for_field_init_shorthand); if let Some(field_def) = analyzer.resolve_record_field(&record_field) { return Some(from_struct_field(db, field_def)); } @@ -160,7 +161,7 @@ pub(crate) fn classify_name_ref( let visibility = None; if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { - tested_by!(goto_definition_works_for_macros); + tested_by!(goto_def_for_macros); if let Some(macro_def) = analyzer.resolve_macro_call(db, name_ref.with_value(¯o_call)) { let kind = NameKind::Macro(macro_def); return Some(NameDefinition { kind, container, visibility }); From 794bbab70dfd009178adf03bd82a30dc569ecde6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:26:19 +0100 Subject: [PATCH 250/312] Remove code that never was alive? --- crates/ra_hir_def/src/nameres.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 9aae7e48e2..af52fa36ee 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -57,9 +57,7 @@ mod tests; use std::sync::Arc; -use hir_expand::{ - ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId, -}; +use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; use once_cell::sync::Lazy; use ra_arena::Arena; use ra_db::{CrateId, Edition, FileId, FilePosition}; @@ -76,7 +74,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - AstId, FunctionId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, + AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, }; /// Contains all top-level defs from a macro-expanded crate @@ -176,11 +174,6 @@ pub struct ModuleData { pub impls: Vec, } -#[derive(Default, Debug, PartialEq, Eq)] -pub(crate) struct Declarations { - fns: FxHashMap, FunctionId>, -} - #[derive(Debug, Default, PartialEq, Eq)] pub struct ModuleScope { items: FxHashMap, From 133b4063a696ab9fbf350b2235c006bdd623b136 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 09:43:01 -0500 Subject: [PATCH 251/312] Remove useless clone --- crates/ra_hir_expand/src/builtin_macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index d2b3d769e8..1749b491b9 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -108,7 +108,7 @@ fn stringify_expand( let macro_content = { let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; - let macro_args = arg.clone(); + let macro_args = arg; let text = macro_args.text(); let without_parens = TextUnit::of_char('(')..text.len() - TextUnit::of_char(')'); text.slice(without_parens).to_string() From f22aabc1360eb7e900a4495bc68f3302c7c49a7c Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 09:43:30 -0500 Subject: [PATCH 252/312] Use unwrap_or_default --- crates/ra_syntax/src/ast/edit.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 95bf9db147..ae5d639276 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs @@ -104,7 +104,7 @@ impl ast::ItemList { } }; - let indent = leading_indent(self.syntax()).unwrap_or("".into()); + let indent = leading_indent(self.syntax()).unwrap_or_default(); let ws = tokens::WsBuilder::new(&format!("\n{}", indent)); let to_insert = iter::once(ws.ws().into()); match existing_ws { @@ -133,7 +133,7 @@ impl ast::RecordFieldList { let space = if is_multiline { ws = tokens::WsBuilder::new(&format!( "\n{} ", - leading_indent(self.syntax()).unwrap_or("".into()) + leading_indent(self.syntax()).unwrap_or_default() )); ws.ws() } else { From 4a7e19946a60b4cba6ef9d9916ae0fbec65c74da Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Fri, 20 Dec 2019 23:11:07 +0800 Subject: [PATCH 253/312] Fix parser for macro call in pattern position --- crates/ra_ide/src/goto_definition.rs | 36 +++++++++++++++++++ crates/ra_parser/src/grammar/patterns.rs | 2 +- .../parser/inline/ok/0129_marco_pat.txt | 9 +++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 9b57447897..79d332e8ce 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs @@ -424,6 +424,42 @@ mod tests { ); } + #[test] + fn goto_definition_works_for_macro_inside_pattern() { + check_goto( + " + //- /lib.rs + macro_rules! foo {() => {0}} + + fn bar() { + match (0,1) { + (<|>foo!(), _) => {} + } + } + ", + "foo MACRO_CALL FileId(1) [0; 28) [13; 16)", + "macro_rules! foo {() => {0}}|foo", + ); + } + + #[test] + fn goto_definition_works_for_macro_inside_match_arm_lhs() { + check_goto( + " + //- /lib.rs + macro_rules! foo {() => {0}} + + fn bar() { + match 0 { + <|>foo!() => {} + } + } + ", + "foo MACRO_CALL FileId(1) [0; 28) [13; 16)", + "macro_rules! foo {() => {0}}|foo", + ); + } + #[test] fn goto_def_for_methods() { covers!(goto_def_for_methods); diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index f5d12278c8..422a4e3dc1 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs @@ -50,7 +50,7 @@ pub(super) fn pattern_r(p: &mut Parser, recovery_set: TokenSet) { // let m!(x) = 0; // } if lhs.kind() == PATH_PAT && p.at(T![!]) { - let m = lhs.precede(p); + let m = lhs.undo_completion(p); items::macro_call_after_excl(p); m.complete(p, MACRO_CALL); } diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt index 4a714ad6b1..b05ccc0ed5 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0129_marco_pat.txt @@ -16,11 +16,10 @@ SOURCE_FILE@[0; 33) LET_KW@[16; 19) "let" WHITESPACE@[19; 20) " " MACRO_CALL@[20; 25) - PATH_PAT@[20; 21) - PATH@[20; 21) - PATH_SEGMENT@[20; 21) - NAME_REF@[20; 21) - IDENT@[20; 21) "m" + PATH@[20; 21) + PATH_SEGMENT@[20; 21) + NAME_REF@[20; 21) + IDENT@[20; 21) "m" EXCL@[21; 22) "!" TOKEN_TREE@[22; 25) L_PAREN@[22; 23) "(" From 49aac9ef63bf11827fca48c16b820ee1c3fe327f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:38:17 +0100 Subject: [PATCH 254/312] Add item_scope module --- crates/ra_hir_def/src/item_scope.rs | 1 + crates/ra_hir_def/src/lib.rs | 1 + 2 files changed, 2 insertions(+) create mode 100644 crates/ra_hir_def/src/item_scope.rs diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/crates/ra_hir_def/src/item_scope.rs @@ -0,0 +1 @@ + diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 8ed1599ffb..bf8d6d1d46 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -15,6 +15,7 @@ pub mod type_ref; pub mod builtin_type; pub mod diagnostics; pub mod per_ns; +pub mod item_scope; pub mod dyn_map; pub mod keys; From 0f212b379811dcb26cde3eba160e07a11182fc5a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:43:45 +0100 Subject: [PATCH 255/312] Move ModuleScope to a new module --- crates/ra_hir_def/src/body.rs | 3 +- crates/ra_hir_def/src/item_scope.rs | 105 ++++++++++++++++++++ crates/ra_hir_def/src/nameres.rs | 108 +-------------------- crates/ra_hir_def/src/nameres/collector.rs | 3 +- crates/ra_hir_def/src/resolver.rs | 3 +- 5 files changed, 114 insertions(+), 108 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 401fe0b9b5..d9ce6bcff6 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -17,7 +17,8 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, - nameres::{BuiltinShadowMode, CrateDefMap}, + item_scope::BuiltinShadowMode, + nameres::CrateDefMap, path::{ModPath, Path}, src::HasSource, DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 8b13789179..62e7a02cb4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -1 +1,106 @@ +use hir_expand::name::Name; +use once_cell::sync::Lazy; +use rustc_hash::FxHashMap; +use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; + +#[derive(Debug, Default, PartialEq, Eq)] +pub struct ModuleScope { + pub(crate) items: FxHashMap, + /// Macros visable in current module in legacy textual scope + /// + /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. + /// If it yields no result, then it turns to module scoped `macros`. + /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, + /// and only normal scoped `macros` will be searched in. + /// + /// Note that this automatically inherit macros defined textually before the definition of module itself. + /// + /// Module scoped macros will be inserted into `items` instead of here. + // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will + // be all resolved to the last one defined if shadowing happens. + pub(crate) legacy_macros: FxHashMap, +} + +static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { + BuiltinType::ALL + .iter() + .map(|(name, ty)| { + (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) + }) + .collect() +}); + +/// Shadow mode for builtin type which can be shadowed by module. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum BuiltinShadowMode { + // Prefer Module + Module, + // Prefer Other Types + Other, +} + +/// Legacy macros can only be accessed through special methods like `get_legacy_macros`. +/// Other methods will only resolve values, types and module scoped macros only. +impl ModuleScope { + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { + //FIXME: shadowing + self.items.iter().chain(BUILTIN_SCOPE.iter()) + } + + pub fn declarations(&self) -> impl Iterator + '_ { + self.entries() + .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) + .flat_map(|per_ns| { + per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) + }) + } + + /// Iterate over all module scoped macros + pub fn macros<'a>(&'a self) -> impl Iterator + 'a { + self.items + .iter() + .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) + } + + /// Iterate over all legacy textual scoped macros visable at the end of the module + pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { + self.legacy_macros.iter().map(|(name, def)| (name, *def)) + } + + /// Get a name from current module scope, legacy macros are not included + pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + match shadow { + BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Other => { + let item = self.items.get(name); + if let Some(res) = item { + if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { + return BUILTIN_SCOPE.get(name).or(item); + } + } + + item.or_else(|| BUILTIN_SCOPE.get(name)) + } + } + } + + pub fn traits<'a>(&'a self) -> impl Iterator + 'a { + self.items.values().filter_map(|r| match r.def.take_types() { + Some(ModuleDefId::TraitId(t)) => Some(t), + _ => None, + }) + } + + pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { + self.legacy_macros.get(name).copied() + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Default)] +pub struct Resolution { + /// None for unresolved + pub def: PerNs, + /// ident by which this is imported into local scope. + pub import: Option, +} diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index af52fa36ee..0b486ce163 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -57,8 +57,7 @@ mod tests; use std::sync::Arc; -use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile, MacroDefId}; -use once_cell::sync::Lazy; +use hir_expand::{diagnostics::DiagnosticSink, name::Name, InFile}; use ra_arena::Arena; use ra_db::{CrateId, Edition, FileId, FilePosition}; use ra_prof::profile; @@ -69,12 +68,12 @@ use ra_syntax::{ use rustc_hash::FxHashMap; use crate::{ - builtin_type::BuiltinType, db::DefDatabase, + item_scope::{BuiltinShadowMode, ModuleScope}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - AstId, ImplId, LocalImportId, LocalModuleId, ModuleDefId, ModuleId, TraitId, + AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId, }; /// Contains all top-level defs from a macro-expanded crate @@ -174,107 +173,6 @@ pub struct ModuleData { pub impls: Vec, } -#[derive(Debug, Default, PartialEq, Eq)] -pub struct ModuleScope { - items: FxHashMap, - /// Macros visable in current module in legacy textual scope - /// - /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. - /// If it yields no result, then it turns to module scoped `macros`. - /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, - /// and only normal scoped `macros` will be searched in. - /// - /// Note that this automatically inherit macros defined textually before the definition of module itself. - /// - /// Module scoped macros will be inserted into `items` instead of here. - // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will - // be all resolved to the last one defined if shadowing happens. - legacy_macros: FxHashMap, -} - -static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { - BuiltinType::ALL - .iter() - .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) - }) - .collect() -}); - -/// Shadow mode for builtin type which can be shadowed by module. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum BuiltinShadowMode { - // Prefer Module - Module, - // Prefer Other Types - Other, -} - -/// Legacy macros can only be accessed through special methods like `get_legacy_macros`. -/// Other methods will only resolve values, types and module scoped macros only. -impl ModuleScope { - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { - //FIXME: shadowing - self.items.iter().chain(BUILTIN_SCOPE.iter()) - } - - pub fn declarations(&self) -> impl Iterator + '_ { - self.entries() - .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) - .flat_map(|per_ns| { - per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) - }) - } - - /// Iterate over all module scoped macros - pub fn macros<'a>(&'a self) -> impl Iterator + 'a { - self.items - .iter() - .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) - } - - /// Iterate over all legacy textual scoped macros visable at the end of the module - pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { - self.legacy_macros.iter().map(|(name, def)| (name, *def)) - } - - /// Get a name from current module scope, legacy macros are not included - pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { - match shadow { - BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), - BuiltinShadowMode::Other => { - let item = self.items.get(name); - if let Some(res) = item { - if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { - return BUILTIN_SCOPE.get(name).or(item); - } - } - - item.or_else(|| BUILTIN_SCOPE.get(name)) - } - } - } - - pub fn traits<'a>(&'a self) -> impl Iterator + 'a { - self.items.values().filter_map(|r| match r.def.take_types() { - Some(ModuleDefId::TraitId(t)) => Some(t), - _ => None, - }) - } - - fn get_legacy_macro(&self, name: &Name) -> Option { - self.legacy_macros.get(name).copied() - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct Resolution { - /// None for unresolved - pub def: PerNs, - /// ident by which this is imported into local scope. - pub import: Option, -} - impl CrateDefMap { pub(crate) fn crate_def_map_query( // Note that this doesn't have `+ AstDatabase`! diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e68bf48688..ea6ce5f97b 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -18,9 +18,10 @@ use test_utils::tested_by; use crate::{ attr::Attrs, db::DefDatabase, + item_scope::Resolution, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, - raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, Resolution, ResolveMode, + raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, }, path::{ModPath, PathKind}, per_ns::PerNs, diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index af9d194f8a..83013fed3d 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -14,7 +14,8 @@ use crate::{ db::DefDatabase, expr::{ExprId, PatId}, generics::GenericParams, - nameres::{BuiltinShadowMode, CrateDefMap}, + item_scope::BuiltinShadowMode, + nameres::CrateDefMap, path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AssocContainerId, ConstId, ContainerId, DefWithBodyId, EnumId, EnumVariantId, From 16ac792f483035f9d9bf6a61b0aefccbdf002188 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:44:40 +0100 Subject: [PATCH 256/312] Docs --- crates/ra_hir_def/src/item_scope.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 62e7a02cb4..3c042a94e0 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -1,3 +1,6 @@ +//! Describes items defined or visible (ie, imported) in a certain scope. +//! This is shared between modules and blocks. + use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; @@ -7,11 +10,11 @@ use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, #[derive(Debug, Default, PartialEq, Eq)] pub struct ModuleScope { pub(crate) items: FxHashMap, - /// Macros visable in current module in legacy textual scope + /// Macros visible in current module in legacy textual scope /// - /// For macros invoked by an unquatified identifier like `bar!()`, `legacy_macros` will be searched in first. + /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. /// If it yields no result, then it turns to module scoped `macros`. - /// It macros with name quatified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, + /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped, /// and only normal scoped `macros` will be searched in. /// /// Note that this automatically inherit macros defined textually before the definition of module itself. From 2ce1aa32c40e68ea905c83c315bddfcdd1b7ae26 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:45:12 +0100 Subject: [PATCH 257/312] Rename ModuleScope -> ItemScope --- crates/ra_hir_def/src/item_scope.rs | 4 ++-- crates/ra_hir_def/src/nameres.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 3c042a94e0..62c878313b 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -8,7 +8,7 @@ use rustc_hash::FxHashMap; use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] -pub struct ModuleScope { +pub struct ItemScope { pub(crate) items: FxHashMap, /// Macros visible in current module in legacy textual scope /// @@ -45,7 +45,7 @@ pub enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. -impl ModuleScope { +impl ItemScope { pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 0b486ce163..3b318719ee 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -69,7 +69,7 @@ use rustc_hash::FxHashMap; use crate::{ db::DefDatabase, - item_scope::{BuiltinShadowMode, ModuleScope}, + item_scope::{BuiltinShadowMode, ItemScope}, nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, @@ -165,7 +165,7 @@ impl ModuleOrigin { pub struct ModuleData { pub parent: Option, pub children: FxHashMap, - pub scope: ModuleScope, + pub scope: ItemScope, /// Where does this module come from? pub origin: ModuleOrigin, From 030e540ad19046e2037981ec8e15a6800b86bbe9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:51:43 +0100 Subject: [PATCH 258/312] Reduce visibility --- crates/ra_hir_def/src/item_scope.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 62c878313b..996d06db61 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -36,7 +36,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { /// Shadow mode for builtin type which can be shadowed by module. #[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum BuiltinShadowMode { +pub(crate) enum BuiltinShadowMode { // Prefer Module Module, // Prefer Other Types @@ -60,19 +60,19 @@ impl ItemScope { } /// Iterate over all module scoped macros - pub fn macros<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { self.items .iter() .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) } - /// Iterate over all legacy textual scoped macros visable at the end of the module - pub fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { + /// Iterate over all legacy textual scoped macros visible at the end of the module + pub(crate) fn legacy_macros<'a>(&'a self) -> impl Iterator + 'a { self.legacy_macros.iter().map(|(name, def)| (name, *def)) } /// Get a name from current module scope, legacy macros are not included - pub fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { match shadow { BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), BuiltinShadowMode::Other => { @@ -88,7 +88,7 @@ impl ItemScope { } } - pub fn traits<'a>(&'a self) -> impl Iterator + 'a { + pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { self.items.values().filter_map(|r| match r.def.take_types() { Some(ModuleDefId::TraitId(t)) => Some(t), _ => None, From 1b8ce5b37b597679796b3ebc57afd55af49449b0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 15:58:20 +0100 Subject: [PATCH 259/312] Move impls to ItemScope --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir_def/src/child_by_source.rs | 2 +- crates/ra_hir_def/src/item_scope.rs | 7 ++++++- crates/ra_hir_def/src/lang_item.rs | 2 +- crates/ra_hir_def/src/nameres.rs | 4 +--- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_def/src/nameres/tests/macros.rs | 4 ++-- crates/ra_hir_ty/src/method_resolution.rs | 2 +- crates/ra_hir_ty/src/test_db.rs | 2 +- crates/ra_hir_ty/src/tests.rs | 2 +- 10 files changed, 16 insertions(+), 13 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index ecf883272d..fca3a29509 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -221,7 +221,7 @@ impl Module { pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec { let def_map = db.crate_def_map(self.id.krate); - def_map[self.id.local_id].impls.iter().copied().map(ImplBlock::from).collect() + def_map[self.id.local_id].scope.impls().map(ImplBlock::from).collect() } pub(crate) fn with_module_id(self, module_id: LocalModuleId) -> Module { diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index f5a65ad409..403ba8b578 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -80,7 +80,7 @@ impl ChildBySource for ModuleId { module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); - for &impl_ in module_data.impls.iter() { + for &impl_ in module_data.scope.impls.iter() { let src = impl_.lookup(db).source(db); res[keys::IMPL].insert(src, impl_) } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 996d06db61..93e579bb0c 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,11 +5,12 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, LocalImportId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { pub(crate) items: FxHashMap, + pub(crate) impls: Vec, /// Macros visible in current module in legacy textual scope /// /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. @@ -59,6 +60,10 @@ impl ItemScope { }) } + pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { + self.impls.iter().copied() + } + /// Iterate over all module scoped macros pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { self.items diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index f4fdbdcfc7..61b2488158 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs @@ -81,7 +81,7 @@ impl LangItems { // Look for impl targets let def_map = db.crate_def_map(module.krate); let module_data = &def_map[module.local_id]; - for &impl_block in module_data.impls.iter() { + for &impl_block in module_data.scope.impls.iter() { self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) } diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index 3b318719ee..5d4ca73a39 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -73,7 +73,7 @@ use crate::{ nameres::{diagnostics::DefDiagnostic, path_resolution::ResolveMode}, path::ModPath, per_ns::PerNs, - AstId, ImplId, LocalModuleId, ModuleDefId, ModuleId, + AstId, LocalModuleId, ModuleDefId, ModuleId, }; /// Contains all top-level defs from a macro-expanded crate @@ -169,8 +169,6 @@ pub struct ModuleData { /// Where does this module come from? pub origin: ModuleOrigin, - - pub impls: Vec, } impl CrateDefMap { diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index ea6ce5f97b..c4f6bcd95e 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -667,7 +667,7 @@ where let impl_id = ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); - self.def_collector.def_map.modules[self.module_id].impls.push(impl_id) + self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id) } } } diff --git a/crates/ra_hir_def/src/nameres/tests/macros.rs b/crates/ra_hir_def/src/nameres/tests/macros.rs index cfa4ecb1af..d104f5993f 100644 --- a/crates/ra_hir_def/src/nameres/tests/macros.rs +++ b/crates/ra_hir_def/src/nameres/tests/macros.rs @@ -610,7 +610,7 @@ fn expand_derive() { struct Foo; ", ); - assert_eq!(map.modules[map.root].impls.len(), 1); + assert_eq!(map.modules[map.root].scope.impls().len(), 1); } #[test] @@ -622,5 +622,5 @@ fn expand_multiple_derive() { struct Foo; ", ); - assert_eq!(map.modules[map.root].impls.len(), 2); + assert_eq!(map.modules[map.root].scope.impls().len(), 2); } diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index 92fb4c0817..888dc31166 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs @@ -58,7 +58,7 @@ impl CrateImplBlocks { let crate_def_map = db.crate_def_map(krate); for (_module_id, module_data) in crate_def_map.modules.iter() { - for &impl_id in module_data.impls.iter() { + for impl_id in module_data.scope.impls() { match db.impl_trait(impl_id) { Some(tr) => { res.impls_by_trait.entry(tr.trait_).or_default().push(impl_id); diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 476f6df52a..1a31b587bb 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs @@ -98,7 +98,7 @@ impl TestDB { } } - for &impl_id in crate_def_map[module_id].impls.iter() { + for impl_id in crate_def_map[module_id].scope.impls() { let impl_data = self.impl_data(impl_id); for item in impl_data.items.iter() { if let AssocItemId::FunctionId(f) = item { diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index d724ee1223..d447b45718 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs @@ -182,7 +182,7 @@ fn visit_module( _ => (), } } - for &impl_id in crate_def_map[module_id].impls.iter() { + for impl_id in crate_def_map[module_id].scope.impls() { let impl_data = db.impl_data(impl_id); for &item in impl_data.items.iter() { match item { From 4f9e3f3632f3c03d44a23daf0d9ce4966816af86 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:19:28 +0100 Subject: [PATCH 260/312] Fix typos --- crates/ra_hir_def/src/nameres/collector.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index c4f6bcd95e..17c7e691e2 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -226,10 +226,10 @@ where /// Define a legacy textual scoped macro in module /// - /// We use a map `legacy_macros` to store all legacy textual scoped macros visable per module. + /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module. /// It will clone all macros from parent legacy scope, whose definition is prior to /// the definition of current module. - /// And also, `macro_use` on a module will import all legacy macros visable inside to + /// And also, `macro_use` on a module will import all legacy macros visible inside to /// current legacy scope, with possible shadowing. fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) { // Always shadowing From e6b1194f2f33722f0cfed32465f778b256162626 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:26:49 +0100 Subject: [PATCH 261/312] Move some code to scope --- crates/ra_hir_def/src/item_scope.rs | 35 ++++++++++++++++++++++ crates/ra_hir_def/src/nameres/collector.rs | 28 ++--------------- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 93e579bb0c..f4fb768cd3 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -47,6 +47,41 @@ pub(crate) enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ItemScope { + pub fn push_res( + &mut self, + name: Name, + res: &Resolution, + import: Option, + ) -> bool { + let mut changed = false; + let existing = self.items.entry(name.clone()).or_default(); + + if existing.def.types.is_none() && res.def.types.is_some() { + existing.def.types = res.def.types; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.values.is_none() && res.def.values.is_some() { + existing.def.values = res.def.values; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.macros.is_none() && res.def.macros.is_some() { + existing.def.macros = res.def.macros; + existing.import = import.or(res.import); + changed = true; + } + + if existing.def.is_none() + && res.def.is_none() + && existing.import.is_none() + && res.import.is_some() + { + existing.import = res.import; + } + changed + } + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 17c7e691e2..95c499ec9f 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -467,34 +467,10 @@ where // prevent stack overflows (but this shouldn't be possible) panic!("infinite recursion in glob imports!"); } - let module_items = &mut self.def_map.modules[module_id].scope; + let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - let existing = module_items.items.entry(name.clone()).or_default(); - - if existing.def.types.is_none() && res.def.types.is_some() { - existing.def.types = res.def.types; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.values.is_none() && res.def.values.is_some() { - existing.def.values = res.def.values; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.macros.is_none() && res.def.macros.is_some() { - existing.def.macros = res.def.macros; - existing.import = import.or(res.import); - changed = true; - } - - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { - existing.import = res.import; - } + changed |= scope.push_res(name.clone(), res, import); } if !changed { From 7adb53319d963d0a40906a6847124974da1d5183 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:47:22 +0100 Subject: [PATCH 262/312] Make items private --- crates/ra_hir_def/src/item_scope.rs | 76 ++++++++++++---------- crates/ra_hir_def/src/nameres/collector.rs | 12 +--- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f4fb768cd3..ac56986cd4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -9,7 +9,7 @@ use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, Modul #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { - pub(crate) items: FxHashMap, + items: FxHashMap, pub(crate) impls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -47,41 +47,6 @@ pub(crate) enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ItemScope { - pub fn push_res( - &mut self, - name: Name, - res: &Resolution, - import: Option, - ) -> bool { - let mut changed = false; - let existing = self.items.entry(name.clone()).or_default(); - - if existing.def.types.is_none() && res.def.types.is_some() { - existing.def.types = res.def.types; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.values.is_none() && res.def.values.is_some() { - existing.def.values = res.def.values; - existing.import = import.or(res.import); - changed = true; - } - if existing.def.macros.is_none() && res.def.macros.is_some() { - existing.def.macros = res.def.macros; - existing.import = import.or(res.import); - changed = true; - } - - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { - existing.import = res.import; - } - changed - } - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing self.items.iter().chain(BUILTIN_SCOPE.iter()) @@ -138,6 +103,45 @@ impl ItemScope { pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { self.legacy_macros.get(name).copied() } + + pub(crate) fn push_res( + &mut self, + name: Name, + res: &Resolution, + import: Option, + ) -> bool { + let mut changed = false; + let existing = self.items.entry(name.clone()).or_default(); + + if existing.def.types.is_none() && res.def.types.is_some() { + existing.def.types = res.def.types; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.values.is_none() && res.def.values.is_some() { + existing.def.values = res.def.values; + existing.import = import.or(res.import); + changed = true; + } + if existing.def.macros.is_none() && res.def.macros.is_some() { + existing.def.macros = res.def.macros; + existing.import = import.or(res.import); + changed = true; + } + + if existing.def.is_none() + && res.def.is_none() + && existing.import.is_none() + && res.import.is_some() + { + existing.import = res.import; + } + changed + } + + pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { + self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect() + } } #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 95c499ec9f..d62fae8a64 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -372,11 +372,7 @@ where let scope = &item_map[m.local_id].scope; // Module scoped macros is included - let items = scope - .items - .iter() - .map(|(name, res)| (name.clone(), res.clone())) - .collect::>(); + let items = scope.collect_resolutions(); self.update(module_id, Some(import_id), &items); } else { @@ -386,11 +382,7 @@ where let scope = &self.def_map[m.local_id].scope; // Module scoped macros is included - let items = scope - .items - .iter() - .map(|(name, res)| (name.clone(), res.clone())) - .collect::>(); + let items = scope.collect_resolutions(); self.update(module_id, Some(import_id), &items); // record the glob import in case we add further items From af42cb5981a1f94116b1da8cfeedb6efdd5aeb01 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 16:55:38 +0100 Subject: [PATCH 263/312] Privitize impls --- crates/ra_hir_def/src/child_by_source.rs | 6 +++--- crates/ra_hir_def/src/item_scope.rs | 6 +++++- crates/ra_hir_def/src/lang_item.rs | 2 +- crates/ra_hir_def/src/nameres/collector.rs | 4 +++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 403ba8b578..4488e85020 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -80,9 +80,9 @@ impl ChildBySource for ModuleId { module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); - for &impl_ in module_data.scope.impls.iter() { - let src = impl_.lookup(db).source(db); - res[keys::IMPL].insert(src, impl_) + for imp in module_data.scope.impls() { + let src = imp.lookup(db).source(db); + res[keys::IMPL].insert(src, imp) } res diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index ac56986cd4..f51e97ef9d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -10,7 +10,7 @@ use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, Modul #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { items: FxHashMap, - pub(crate) impls: Vec, + impls: Vec, /// Macros visible in current module in legacy textual scope /// /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first. @@ -104,6 +104,10 @@ impl ItemScope { self.legacy_macros.get(name).copied() } + pub(crate) fn define_impl(&mut self, imp: ImplId) { + self.impls.push(imp) + } + pub(crate) fn push_res( &mut self, name: Name, diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index 61b2488158..cef061837b 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs @@ -81,7 +81,7 @@ impl LangItems { // Look for impl targets let def_map = db.crate_def_map(module.krate); let module_data = &def_map[module.local_id]; - for &impl_block in module_data.scope.impls.iter() { + for impl_block in module_data.scope.impls() { self.collect_lang_item(db, impl_block, LangItemTarget::ImplBlockId) } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d62fae8a64..b064ccc9c9 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -635,7 +635,9 @@ where let impl_id = ImplLoc { container, ast_id: AstId::new(self.file_id, ast_id) } .intern(self.def_collector.db); - self.def_collector.def_map.modules[self.module_id].scope.impls.push(impl_id) + self.def_collector.def_map.modules[self.module_id] + .scope + .define_impl(impl_id) } } } From 7a862f0d47e8ae018d449a04c918ea3705785552 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 17:09:13 +0100 Subject: [PATCH 264/312] Make legacy macros private --- crates/ra_hir_def/src/item_scope.rs | 10 +++++++++- crates/ra_hir_def/src/nameres/collector.rs | 10 ++++++---- crates/ra_hir_def/src/nameres/tests.rs | 19 +++++++------------ .../src/nameres/tests/incremental.rs | 4 ++-- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f51e97ef9d..6b9be8325d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -23,7 +23,7 @@ pub struct ItemScope { /// Module scoped macros will be inserted into `items` instead of here. // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will // be all resolved to the last one defined if shadowing happens. - pub(crate) legacy_macros: FxHashMap, + legacy_macros: FxHashMap, } static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { @@ -108,6 +108,10 @@ impl ItemScope { self.impls.push(imp) } + pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroDefId) { + self.legacy_macros.insert(name, mac); + } + pub(crate) fn push_res( &mut self, name: Name, @@ -146,6 +150,10 @@ impl ItemScope { pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect() } + + pub(crate) fn collect_legacy_macros(&self) -> FxHashMap { + self.legacy_macros.clone() + } } #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b064ccc9c9..8b641d8b56 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -231,9 +231,9 @@ where /// the definition of current module. /// And also, `macro_use` on a module will import all legacy macros visible inside to /// current legacy scope, with possible shadowing. - fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, macro_: MacroDefId) { + fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroDefId) { // Always shadowing - self.def_map.modules[module_id].scope.legacy_macros.insert(name, macro_); + self.def_map.modules[module_id].scope.define_legacy_macro(name, mac); } /// Import macros from `#[macro_use] extern crate`. @@ -711,7 +711,9 @@ where let res = modules.alloc(ModuleData::default()); modules[res].parent = Some(self.module_id); modules[res].origin = ModuleOrigin::not_sure_file(definition, declaration); - modules[res].scope.legacy_macros = modules[self.module_id].scope.legacy_macros.clone(); + for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() { + modules[res].scope.define_legacy_macro(name, mac) + } modules[self.module_id].children.insert(name.clone(), res); let resolution = Resolution { def: PerNs::types( @@ -875,7 +877,7 @@ where } fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) { - let macros = self.def_collector.def_map[module_id].scope.legacy_macros.clone(); + let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros(); for (name, macro_) in macros { self.def_collector.define_legacy_macro(self.module_id, name.clone(), macro_); } diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 61cdd768e8..4e968bcc84 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -32,27 +32,22 @@ fn render_crate_def_map(map: &CrateDefMap) -> String { *buf += path; *buf += "\n"; - let mut entries = map.modules[module] - .scope - .items - .iter() - .map(|(name, res)| (name, res.def)) - .collect::>(); - entries.sort_by_key(|(name, _)| *name); + let mut entries = map.modules[module].scope.collect_resolutions(); + entries.sort_by_key(|(name, _)| name.clone()); for (name, res) in entries { *buf += &format!("{}:", name); - if res.types.is_some() { + if res.def.types.is_some() { *buf += " t"; } - if res.values.is_some() { + if res.def.values.is_some() { *buf += " v"; } - if res.macros.is_some() { + if res.def.macros.is_some() { *buf += " m"; } - if res.is_none() { + if res.def.is_none() { *buf += " _"; } @@ -587,6 +582,6 @@ mod b { â‹®T: v â‹® â‹®crate::a - â‹®T: t v + â‹®T: t v "###); } diff --git a/crates/ra_hir_def/src/nameres/tests/incremental.rs b/crates/ra_hir_def/src/nameres/tests/incremental.rs index 903a227719..ef2e9435cf 100644 --- a/crates/ra_hir_def/src/nameres/tests/incremental.rs +++ b/crates/ra_hir_def/src/nameres/tests/incremental.rs @@ -116,7 +116,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let crate_def_map = db.crate_def_map(krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); - assert_eq!(module_data.scope.items.len(), 1); + assert_eq!(module_data.scope.collect_resolutions().len(), 1); }); assert!(format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) } @@ -126,7 +126,7 @@ fn typing_inside_a_macro_should_not_invalidate_def_map() { let events = db.log_executed(|| { let crate_def_map = db.crate_def_map(krate); let (_, module_data) = crate_def_map.modules.iter().last().unwrap(); - assert_eq!(module_data.scope.items.len(), 1); + assert_eq!(module_data.scope.collect_resolutions().len(), 1); }); assert!(!format!("{:?}", events).contains("crate_def_map"), "{:#?}", events) } From 428358925c40fe1e15bf0b67bbf007c54b510920 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 11:12:31 -0500 Subject: [PATCH 265/312] Remove the index resolution from hover We are reasonably precise now to do this. --- crates/ra_ide/src/hover.rs | 80 +++++++++++--------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index a227bf546c..35e39f9652 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -12,10 +12,7 @@ use ra_syntax::{ use crate::{ db::RootDatabase, - display::{ - description_from_symbol, docs_from_symbol, macro_label, rust_code_markup, - rust_code_markup_with_doc, ShortLabel, - }, + display::{macro_label, rust_code_markup, rust_code_markup_with_doc, ShortLabel}, expand::descend_into_macros, references::{classify_name, classify_name_ref, NameKind, NameKind::*}, FilePosition, FileRange, RangeInfo, @@ -95,11 +92,7 @@ fn hover_text(docs: Option, desc: Option) -> Option { } } -fn hover_text_from_name_kind( - db: &RootDatabase, - name_kind: NameKind, - no_fallback: &mut bool, -) -> Option { +fn hover_text_from_name_kind(db: &RootDatabase, name_kind: NameKind) -> Option { return match name_kind { Macro(it) => { let src = it.source(db); @@ -135,11 +128,7 @@ fn hover_text_from_name_kind( hir::ModuleDef::TypeAlias(it) => from_def_source(db, it), hir::ModuleDef::BuiltinType(it) => Some(it.to_string()), }, - Local(_) => { - // Hover for these shows type names - *no_fallback = true; - None - } + Local(_) => None, TypeParam(_) | SelfType(_) => { // FIXME: Hover for generic param None @@ -163,60 +152,35 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option { - let mut no_fallback = false; - if let Some(name_kind) = - classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind) - { - res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) - } - - if res.is_empty() && !no_fallback { - // Fallback index based approach: - let symbols = crate::symbol_index::index_resolve(db, &name_ref); - for sym in symbols { - let docs = docs_from_symbol(db, &sym); - let desc = description_from_symbol(db, &sym); - res.extend(hover_text(docs, desc)); - } - } - - if !res.is_empty() { - Some(name_ref.syntax().text_range()) - } else { - None - } + classify_name_ref(db, token.with_value(&name_ref)).map(|d| (name_ref.syntax().text_range(), d.kind)) }, ast::Name(name) => { - if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) { - res.extend(hover_text_from_name_kind(db, name_kind, &mut true)); - } - - if !res.is_empty() { - Some(name.syntax().text_range()) - } else { - None - } + classify_name(db, token.with_value(&name)).map(|d| (name.syntax().text_range(), d.kind)) }, _ => None, } - }; + } { + res.extend(hover_text_from_name_kind(db, name_kind)); - if range.is_none() { - let node = token.value.ancestors().find(|n| { - ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() - })?; - let frange = FileRange { file_id: position.file_id, range: node.text_range() }; - res.extend(type_of(db, frange).map(rust_code_markup)); - range = Some(node.text_range()); - }; + if !res.is_empty() { + return Some(RangeInfo::new(range, res)); + } + } - let range = range?; + let node = token + .value + .ancestors() + .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?; + let frange = FileRange { file_id: position.file_id, range: node.text_range() }; + res.extend(type_of(db, frange).map(rust_code_markup)); if res.is_empty() { return None; } + let range = node.text_range(); + Some(RangeInfo::new(range, res)) } @@ -314,7 +278,7 @@ mod tests { &["pub fn foo() -> u32"], ); - // Multiple results + // Multiple candidates but results are ambiguous. check_hover_result( r#" //- /a.rs @@ -335,7 +299,7 @@ mod tests { let foo_test = fo<|>o(); } "#, - &["pub fn foo() -> &str", "pub fn foo() -> u32", "pub fn foo(a: u32, b: u32)"], + &["{unknown}"], ); } From 77626d7bdafa26ca539276b975d74348aabe175e Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 11:18:24 -0500 Subject: [PATCH 266/312] Remove unused imports --- crates/ra_ide/src/display.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_ide/src/display.rs b/crates/ra_ide/src/display.rs index 30617412a6..fbe89841b0 100644 --- a/crates/ra_ide/src/display.rs +++ b/crates/ra_ide/src/display.rs @@ -15,7 +15,7 @@ pub use function_signature::FunctionSignature; pub use navigation_target::NavigationTarget; pub use structure::{file_structure, StructureNode}; -pub(crate) use navigation_target::{description_from_symbol, docs_from_symbol, ToNav}; +pub(crate) use navigation_target::ToNav; pub(crate) use short_label::ShortLabel; pub(crate) fn function_label(node: &ast::FnDef) -> String { From 2a8c9100bfb1294a469bc039a5b9597eabed7073 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 20 Dec 2019 16:41:32 +0100 Subject: [PATCH 267/312] Handle closure return types Fixes #2547. --- crates/ra_hir_def/src/body/lower.rs | 3 +- crates/ra_hir_def/src/expr.rs | 1 + crates/ra_hir_ty/src/infer.rs | 7 +++- crates/ra_hir_ty/src/infer/expr.rs | 17 ++++++-- crates/ra_hir_ty/src/tests/coercion.rs | 31 +++++++++++++++ crates/ra_hir_ty/src/tests/simple.rs | 55 ++++++++++++++++++++++++++ crates/ra_syntax/src/ast/generated.rs | 3 ++ crates/ra_syntax/src/grammar.ron | 2 +- 8 files changed, 113 insertions(+), 6 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 853e17bae7..be5d17d85e 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -372,8 +372,9 @@ where arg_types.push(type_ref); } } + let ret_type = e.ret_type().and_then(|r| r.type_ref()).map(TypeRef::from_ast); let body = self.collect_expr_opt(e.body()); - self.alloc_expr(Expr::Lambda { args, arg_types, body }, syntax_ptr) + self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) } ast::Expr::BinExpr(e) => { let lhs = self.collect_expr_opt(e.lhs()); diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs index 6fad80a8d4..a75ef9970d 100644 --- a/crates/ra_hir_def/src/expr.rs +++ b/crates/ra_hir_def/src/expr.rs @@ -143,6 +143,7 @@ pub enum Expr { Lambda { args: Vec, arg_types: Vec>, + ret_type: Option, body: ExprId, }, Tuple { diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index bbbc391c4f..9f2ed830ed 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -196,7 +196,12 @@ struct InferenceContext<'a, D: HirDatabase> { trait_env: Arc, obligations: Vec, result: InferenceResult, - /// The return type of the function being inferred. + /// The return type of the function being inferred, or the closure if we're + /// currently within one. + /// + /// We might consider using a nested inference context for checking + /// closures, but currently this is the only field that will change there, + /// so it doesn't make sense. return_ty: Ty, /// Impls of `CoerceUnsized` used in coercion. diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 8be5679177..253332c30e 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -102,7 +102,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { self.infer_expr(*body, &Expectation::has_type(Ty::unit())); Ty::unit() } - Expr::Lambda { body, args, arg_types } => { + Expr::Lambda { body, args, ret_type, arg_types } => { assert_eq!(args.len(), arg_types.len()); let mut sig_tys = Vec::new(); @@ -118,7 +118,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } // add return type - let ret_ty = self.table.new_type_var(); + let ret_ty = match ret_type { + Some(type_ref) => self.make_ty(type_ref), + None => self.table.new_type_var(), + }; sig_tys.push(ret_ty.clone()); let sig_ty = Ty::apply( TypeCtor::FnPtr { num_args: sig_tys.len() as u16 - 1 }, @@ -134,7 +137,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { // infer the body. self.coerce(&closure_ty, &expected.ty); - self.infer_expr(*body, &Expectation::has_type(ret_ty)); + let prev_ret_ty = std::mem::replace(&mut self.return_ty, ret_ty.clone()); + + self.infer_expr_coerce(*body, &Expectation::has_type(ret_ty)); + + self.return_ty = prev_ret_ty; + closure_ty } Expr::Call { callee, args } => { @@ -192,6 +200,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { Expr::Return { expr } => { if let Some(expr) = expr { self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); + } else { + let unit = Ty::unit(); + self.coerce(&unit, &self.return_ty.clone()); } Ty::simple(TypeCtor::Never) } diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index ac9e3872a5..33d6ca4034 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs @@ -440,3 +440,34 @@ fn test() { "### ); } + +#[test] +fn closure_return_coerce() { + assert_snapshot!( + infer_with_mismatches(r#" +fn foo() { + let x = || { + if true { + return &1u32; + } + &&1u32 + }; +} +"#, true), + @r###" + [10; 106) '{ ... }; }': () + [20; 21) 'x': || -> &u32 + [24; 103) '|| { ... }': || -> &u32 + [27; 103) '{ ... }': &u32 + [37; 82) 'if tru... }': () + [40; 44) 'true': bool + [45; 82) '{ ... }': ! + [59; 71) 'return &1u32': ! + [66; 71) '&1u32': &u32 + [67; 71) '1u32': u32 + [91; 97) '&&1u32': &&u32 + [92; 97) '&1u32': &u32 + [93; 97) '1u32': u32 + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 18976c9aee..6fe647a5e3 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -1606,3 +1606,58 @@ fn main() { ); assert_eq!(t, "u32"); } + +#[test] +fn closure_return() { + assert_snapshot!( + infer(r#" +fn foo() -> u32 { + let x = || -> usize { return 1; }; +} +"#), + @r###" + [17; 59) '{ ...; }; }': () + [27; 28) 'x': || -> usize + [31; 56) '|| -> ...n 1; }': || -> usize + [43; 56) '{ return 1; }': ! + [45; 53) 'return 1': ! + [52; 53) '1': usize + "### + ); +} + +#[test] +fn closure_return_unit() { + assert_snapshot!( + infer(r#" +fn foo() -> u32 { + let x = || { return; }; +} +"#), + @r###" + [17; 48) '{ ...; }; }': () + [27; 28) 'x': || -> () + [31; 45) '|| { return; }': || -> () + [34; 45) '{ return; }': ! + [36; 42) 'return': ! + "### + ); +} + +#[test] +fn closure_return_inferred() { + assert_snapshot!( + infer(r#" +fn foo() -> u32 { + let x = || { "test" }; +} +"#), + @r###" + [17; 47) '{ ..." }; }': () + [27; 28) 'x': || -> &str + [31; 44) '|| { "test" }': || -> &str + [34; 44) '{ "test" }': &str + [36; 42) '"test"': &str + "### + ); +} diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 9dd6bd3eac..8d65e2e08e 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -1426,6 +1426,9 @@ impl LambdaExpr { pub fn param_list(&self) -> Option { AstChildren::new(&self.syntax).next() } + pub fn ret_type(&self) -> Option { + AstChildren::new(&self.syntax).next() + } pub fn body(&self) -> Option { AstChildren::new(&self.syntax).next() } diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 9ffa9095bc..a228fa9d6e 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -426,7 +426,7 @@ Grammar( "PathExpr": (options: ["Path"]), "LambdaExpr": ( options: [ - "ParamList", + "ParamList", "RetType", ["body", "Expr"], ] ), From 9c3f00a90651998c2cd4151f43f17cd92ef8eef1 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 20 Dec 2019 18:27:51 +0100 Subject: [PATCH 268/312] Fix coercion of last expression in function body --- crates/ra_hir_ty/src/infer.rs | 2 +- crates/ra_hir_ty/src/infer/expr.rs | 2 +- crates/ra_hir_ty/src/tests/coercion.rs | 16 ++++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index 9f2ed830ed..e97b814739 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs @@ -460,7 +460,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } fn infer_body(&mut self) { - self.infer_expr(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); + self.infer_expr_coerce(self.body.body_expr, &Expectation::has_type(self.return_ty.clone())); } fn resolve_into_iter_item(&self) -> Option { diff --git a/crates/ra_hir_ty/src/infer/expr.rs b/crates/ra_hir_ty/src/infer/expr.rs index 253332c30e..3af05394c6 100644 --- a/crates/ra_hir_ty/src/infer/expr.rs +++ b/crates/ra_hir_ty/src/infer/expr.rs @@ -41,7 +41,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { /// Infer type of expression with possibly implicit coerce to the expected type. /// Return the type after possible coercion. - fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { + pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty { let ty = self.infer_expr_inner(expr, &expected); let ty = if !self.coerce(&ty, &expected.ty) { self.result diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 33d6ca4034..793c23e41c 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs @@ -369,6 +369,22 @@ fn test() { ); } +#[test] +fn return_coerce_unknown() { + assert_snapshot!( + infer_with_mismatches(r#" +fn foo() -> u32 { + return unknown; +} +"#, true), + @r###" + [17; 40) '{ ...own; }': ! + [23; 37) 'return unknown': ! + [30; 37) 'unknown': u32 + "### + ); +} + #[test] fn coerce_autoderef() { assert_snapshot!( From 44b00aed4a7d7e329fcbfa95a8685437cfb06e41 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Fri, 20 Dec 2019 18:53:40 +0100 Subject: [PATCH 269/312] Coerce closures to fn pointers E.g. `let x: fn(A) -> B = |x| { y };` --- crates/ra_hir_ty/src/infer/coerce.rs | 4 +++ crates/ra_hir_ty/src/tests/coercion.rs | 39 ++++++++++++++++++++++++++ crates/ra_hir_ty/src/tests/traits.rs | 10 +++---- 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs index 0f4dac45ed..83c0c2c3f3 100644 --- a/crates/ra_hir_ty/src/infer/coerce.rs +++ b/crates/ra_hir_ty/src/infer/coerce.rs @@ -134,6 +134,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { } } + (ty_app!(TypeCtor::Closure { .. }, params), ty_app!(TypeCtor::FnPtr { .. })) => { + from_ty = params[0].clone(); + } + _ => {} } diff --git a/crates/ra_hir_ty/src/tests/coercion.rs b/crates/ra_hir_ty/src/tests/coercion.rs index 793c23e41c..7e99a42edc 100644 --- a/crates/ra_hir_ty/src/tests/coercion.rs +++ b/crates/ra_hir_ty/src/tests/coercion.rs @@ -487,3 +487,42 @@ fn foo() { "### ); } + +#[test] +fn coerce_fn_item_to_fn_ptr() { + assert_snapshot!( + infer_with_mismatches(r#" +fn foo(x: u32) -> isize { 1 } +fn test() { + let f: fn(u32) -> isize = foo; +} +"#, true), + @r###" + [8; 9) 'x': u32 + [25; 30) '{ 1 }': isize + [27; 28) '1': isize + [41; 79) '{ ...foo; }': () + [51; 52) 'f': fn(u32) -> isize + [73; 76) 'foo': fn foo(u32) -> isize + "### + ); +} + +#[test] +fn coerce_closure_to_fn_ptr() { + assert_snapshot!( + infer_with_mismatches(r#" +fn test() { + let f: fn(u32) -> isize = |x| { 1 }; +} +"#, true), + @r###" + [11; 55) '{ ...1 }; }': () + [21; 22) 'f': fn(u32) -> isize + [43; 52) '|x| { 1 }': |u32| -> isize + [44; 45) 'x': u32 + [47; 52) '{ 1 }': isize + [49; 50) '1': isize + "### + ); +} diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 2d92a5eec2..76e2198b66 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -393,11 +393,11 @@ fn test() -> u64 { [54; 55) 'a': S [58; 59) 'S': S(fn(u32) -> u64) -> S [58; 68) 'S(|i| 2*i)': S - [60; 67) '|i| 2*i': |i32| -> i32 - [61; 62) 'i': i32 - [64; 65) '2': i32 - [64; 67) '2*i': i32 - [66; 67) 'i': i32 + [60; 67) '|i| 2*i': |u32| -> u64 + [61; 62) 'i': u32 + [64; 65) '2': u32 + [64; 67) '2*i': u32 + [66; 67) 'i': u32 [78; 79) 'b': u64 [82; 83) 'a': S [82; 85) 'a.0': fn(u32) -> u64 From be78e3c224ffcdfafb5d54f7d12b3c2231e9e13e Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 13:52:11 -0500 Subject: [PATCH 270/312] Update to latest packages --- editors/code/package-lock.json | 50 +++++++++++++++++----------------- editors/code/package.json | 16 +++++------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/editors/code/package-lock.json b/editors/code/package-lock.json index 127cdcfa10..4c5c13646c 100644 --- a/editors/code/package-lock.json +++ b/editors/code/package-lock.json @@ -60,9 +60,9 @@ "dev": true }, "@types/node": { - "version": "10.17.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.6.tgz", - "integrity": "sha512-0a2X6cgN3RdPBL2MIlR6Lt0KlM7fOFsutuXcdglcOq6WvLnYXgPQSh0Mx6tO1KCAE8MxbHSOSTWDoUxRq+l3DA==", + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==", "dev": true }, "@types/resolve": { @@ -81,9 +81,9 @@ "dev": true }, "@types/vscode": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.40.0.tgz", - "integrity": "sha512-5kEIxL3qVRkwhlMerxO7XuMffa+0LBl+iG2TcRa0NsdoeSFLkt/9hJ02jsi/Kvc6y8OVF2N2P2IHP5S4lWf/5w==", + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.41.0.tgz", + "integrity": "sha512-7SfeY5u9jgiELwxyLB3z7l6l/GbN9CqpCQGkcRlB7tKRFBxzbz2PoBfGrLxI1vRfUCIq5+hg5vtDHExwq5j3+A==", "dev": true }, "acorn": { @@ -791,9 +791,9 @@ } }, "lookpath": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.3.tgz", - "integrity": "sha512-XIdgzlX26g10XnzyZdO/4obybEmfGnZyWQZ2DgmmEfVB79X+n3lhUoIzMe501C6s7RmCpAo66OPegWc+CsxYMg==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lookpath/-/lookpath-1.0.4.tgz", + "integrity": "sha512-xVFrWlfo7n8VZs1YjBWKkbSIJU7DKE/0Mep62KeT94V1Ui1IY9w5fXfgiCsDIDZkakIYSXSeaW2FLbCqfw9/Cw==" }, "magic-string": { "version": "0.25.3", @@ -1140,9 +1140,9 @@ } }, "rollup": { - "version": "1.27.9", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.9.tgz", - "integrity": "sha512-8AfW4cJTPZfG6EXWwT/ujL4owUsDI1Xl8J1t+hvK4wDX81F5I4IbwP9gvGbHzxnV19fnU4rRABZQwZSX9J402Q==", + "version": "1.27.13", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.13.tgz", + "integrity": "sha512-hDi7M07MpmNSDE8YVwGVFA8L7n8jTLJ4lG65nMAijAyqBe//rtu4JdxjUBE7JqXfdpqxqDTbCDys9WcqdpsQvw==", "dev": true, "requires": { "@types/estree": "*", @@ -1514,9 +1514,9 @@ "dev": true }, "vsce": { - "version": "1.70.0", - "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.70.0.tgz", - "integrity": "sha512-mBTbVrWL348jODwfmaR+yXrlzb8EABGCT067C4shKOXriWiuMQi4/uCbFm6TUBcfnzTYLJv+DKa0VnKU8yEAjA==", + "version": "1.71.0", + "resolved": "https://registry.npmjs.org/vsce/-/vsce-1.71.0.tgz", + "integrity": "sha512-7k+LPC4oJYPyyxs0a5nh4A8CleQ6+2EMPiAiX/bDyN+PmwJFm2FFPqLRxdIsIWfFnkW4ZMQBf10+W62dCRd9kQ==", "dev": true, "requires": { "azure-devops-node-api": "^7.2.0", @@ -1547,12 +1547,12 @@ "integrity": "sha512-k9akfglxWgr0dtLNscq2uBq48XJwnhf4EaDxn05KQowRwR0DkNML0zeYqFRLtXZe6x5vpL5ppyu4o6GqL+23YQ==" }, "vscode-languageclient": { - "version": "6.0.0-next.8", - "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.8.tgz", - "integrity": "sha512-452jskmuT7YKYnPd5uh7aELK4M25OITcnBq4ylPIyUtE5LQRgA9N9pR9NrviTTX/Hh6q6VGzm70OK9SpMO/zcA==", + "version": "6.0.0-next.9", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-6.0.0-next.9.tgz", + "integrity": "sha512-NEpeeFM9FKrrRqlBHXGfwpkhtnjruDz3zfFBP+Cymr10qigAEtE/JsODJsIG/ErGqjh3/JXxu8SUOVTGu5oK+w==", "requires": { "semver": "^6.3.0", - "vscode-languageserver-protocol": "^3.15.0-next.13" + "vscode-languageserver-protocol": "^3.15.0-next.14" }, "dependencies": { "semver": { @@ -1563,9 +1563,9 @@ } }, "vscode-languageserver-protocol": { - "version": "3.15.0-next.13", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.13.tgz", - "integrity": "sha512-2UGxOKc5VHav15n3zY5dtaOXGL/JuV0K2Mem/n6lhF8i3vaqIAnKv004SPU0flYHXIfCcQM7kCL+nwWVJ1K1qw==", + "version": "3.15.0-next.14", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.15.0-next.14.tgz", + "integrity": "sha512-xUwwno6Q6RFd2Z2EWV9D3dQlsKPnHyiZMNWq+EC7JJdp2WH1gRlD+KPX4UGRCnJK0WI5omqHV313IESPwRY5xA==", "requires": { "vscode-jsonrpc": "^5.0.0-next.5", "vscode-languageserver-types": "^3.15.0-next.9" @@ -1577,9 +1577,9 @@ "integrity": "sha512-Rl/8qJ6932nrHCdPn+9y0x08uLVQaSLRG+U4JzhyKpWU4eJbVaDRoAcz1Llj7CErJGbPr6kdBvShPy5fRfR+Uw==" }, "vscode-test": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.2.3.tgz", - "integrity": "sha512-mKRTNso33NaUULiPBFg6zRjyntjcCpIgkrogyPQuKlvoQREQR8jLKN5UD4L5rkTSD+oBhcKtaLR2/g34FexURw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vscode-test/-/vscode-test-1.3.0.tgz", + "integrity": "sha512-LddukcBiSU2FVTDr3c1D8lwkiOvwlJdDL2hqVbn6gIz+rpTqUCkMZSKYm94Y1v0WXlHSDQBsXyY+tchWQgGVsw==", "dev": true, "requires": { "http-proxy-agent": "^2.1.0", diff --git a/editors/code/package.json b/editors/code/package.json index f2e8e647e3..f75fafeb9e 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -13,7 +13,7 @@ "Other" ], "engines": { - "vscode": "^1.40.0" + "vscode": "^1.41.0" }, "scripts": { "vscode:prepublish": "npm run compile", @@ -32,20 +32,20 @@ "trailingComma": "all" }, "dependencies": { - "lookpath": "^1.0.3", + "lookpath": "^1.0.4", "seedrandom": "^3.0.5", - "vscode-languageclient": "^6.0.0-next.8" + "vscode-languageclient": "^6.0.0-next.9" }, "devDependencies": { "@types/glob": "^7.1.1", "@types/mocha": "^5.2.7", - "@types/node": "^10.17.6", + "@types/node": "^12.12.21", "@types/seedrandom": "^2.4.28", - "@types/vscode": "^1.40.0", + "@types/vscode": "^1.41.0", "glob": "^7.1.6", "mocha": "^6.2.2", "prettier": "^1.19.1", - "rollup": "^1.27.9", + "rollup": "^1.27.13", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-sourcemaps": "^0.4.2", @@ -55,8 +55,8 @@ "tslint-config-prettier": "^1.18.0", "tslint-plugin-prettier": "^2.0.1", "typescript": "^3.7.3", - "vsce": "^1.70.0", - "vscode-test": "^1.2.3" + "vsce": "^1.71.0", + "vscode-test": "^1.3.0" }, "activationEvents": [ "onLanguage:rust", From 6049f60a052b4097ab45a631480f8207ac5f6009 Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 13:52:34 -0500 Subject: [PATCH 271/312] Protect against null as revealed by `npm test` --- editors/code/src/commands/cargo_watch.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/editors/code/src/commands/cargo_watch.ts b/editors/code/src/commands/cargo_watch.ts index 748be535cc..ac62bdd48d 100644 --- a/editors/code/src/commands/cargo_watch.ts +++ b/editors/code/src/commands/cargo_watch.ts @@ -111,8 +111,13 @@ export class CargoWatchProvider implements vscode.Disposable { }, ); + if (!this.cargoProcess) { + vscode.window.showErrorMessage('Cargo Watch failed to start'); + return; + } + const stdoutData = new LineBuffer(); - this.cargoProcess.stdout.on('data', (s: string) => { + this.cargoProcess.stdout?.on('data', (s: string) => { stdoutData.processOutput(s, line => { this.logInfo(line); try { @@ -124,7 +129,7 @@ export class CargoWatchProvider implements vscode.Disposable { }); const stderrData = new LineBuffer(); - this.cargoProcess.stderr.on('data', (s: string) => { + this.cargoProcess.stderr?.on('data', (s: string) => { stderrData.processOutput(s, line => { this.logError('Error on cargo-watch : {\n' + line + '}\n'); }); From f5947be0ea6eb909cbb63420c3304adedf470b26 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 20 Dec 2019 20:15:54 +0100 Subject: [PATCH 272/312] Simplify --- crates/ra_hir_def/src/path.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 00325cd99a..8e12942011 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs @@ -135,7 +135,7 @@ impl Path { } pub fn type_anchor(&self) -> Option<&TypeRef> { - self.type_anchor.as_ref().map(|it| &**it) + self.type_anchor.as_deref() } pub fn segments(&self) -> PathSegments<'_> { From ad81d1dbc19803b5ccf1b230237642944edbff13 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 03:37:03 +0800 Subject: [PATCH 273/312] Add support macros in impl blocks --- crates/ra_hir_def/src/body.rs | 22 +++-- crates/ra_hir_def/src/data.rs | 119 ++++++++++++++++++--------- crates/ra_hir_def/src/lib.rs | 1 + crates/ra_hir_expand/src/db.rs | 1 + crates/ra_hir_ty/src/tests/macros.rs | 19 +++++ 5 files changed, 114 insertions(+), 48 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 401fe0b9b5..a92c01f86f 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -23,7 +23,7 @@ use crate::{ DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, }; -struct Expander { +pub(crate) struct Expander { crate_def_map: Arc, current_file_id: HirFileId, hygiene: Hygiene, @@ -32,18 +32,22 @@ struct Expander { } impl Expander { - fn new(db: &impl DefDatabase, current_file_id: HirFileId, module: ModuleId) -> Expander { + pub(crate) fn new( + db: &impl DefDatabase, + current_file_id: HirFileId, + module: ModuleId, + ) -> Expander { let crate_def_map = db.crate_def_map(module.krate); let hygiene = Hygiene::new(db, current_file_id); let ast_id_map = db.ast_id_map(current_file_id); Expander { crate_def_map, current_file_id, hygiene, ast_id_map, module } } - fn enter_expand( + pub(crate) fn enter_expand( &mut self, - db: &impl DefDatabase, + db: &DB, macro_call: ast::MacroCall, - ) -> Option<(Mark, ast::Expr)> { + ) -> Option<(Mark, T)> { let ast_id = AstId::new( self.current_file_id, db.ast_id_map(self.current_file_id).ast_id(¯o_call), @@ -54,7 +58,7 @@ impl Expander { let call_id = def.as_call_id(db, MacroCallKind::FnLike(ast_id)); let file_id = call_id.as_file(); if let Some(node) = db.parse_or_expand(file_id) { - if let Some(expr) = ast::Expr::cast(node) { + if let Some(expr) = T::cast(node) { log::debug!("macro expansion {:#?}", expr.syntax()); let mark = Mark { @@ -77,14 +81,14 @@ impl Expander { None } - fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { + pub(crate) fn exit(&mut self, db: &impl DefDatabase, mut mark: Mark) { self.hygiene = Hygiene::new(db, mark.file_id); self.current_file_id = mark.file_id; self.ast_id_map = mem::take(&mut mark.ast_id_map); mark.bomb.defuse(); } - fn to_source(&self, value: T) -> InFile { + pub(crate) fn to_source(&self, value: T) -> InFile { InFile { file_id: self.current_file_id, value } } @@ -109,7 +113,7 @@ impl Expander { } } -struct Mark { +pub(crate) struct Mark { file_id: HirFileId, ast_id_map: Arc, bomb: DropBomb, diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 14e86936bc..b0a3f17845 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -4,16 +4,16 @@ use std::sync::Arc; use hir_expand::{ name::{name, AsName, Name}, - AstId, + AstId, InFile, }; -use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; +use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner}; use crate::{ db::DefDatabase, src::HasSource, type_ref::{Mutability, TypeRef}, - AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, ImplId, Intern, - Lookup, StaticId, TraitId, TypeAliasId, TypeAliasLoc, + AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, + ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, }; #[derive(Debug, Clone, PartialEq, Eq)] @@ -167,46 +167,24 @@ pub struct ImplData { impl ImplData { pub(crate) fn impl_data_query(db: &impl DefDatabase, id: ImplId) -> Arc { - let src = id.lookup(db).source(db); - let items = db.ast_id_map(src.file_id); + let impl_loc = id.lookup(db); + let src = impl_loc.source(db); let target_trait = src.value.target_trait().map(TypeRef::from_ast); let target_type = TypeRef::from_ast_opt(src.value.target_type()); let is_negative = src.value.is_negative(); + let module_id = impl_loc.container.module(db); - let items = if let Some(item_list) = src.value.item_list() { - item_list - .impl_items() - .map(|item_node| match item_node { - ast::ImplItem::FnDef(it) => { - let def = FunctionLoc { - container: AssocContainerId::ImplId(id), - ast_id: AstId::new(src.file_id, items.ast_id(&it)), - } - .intern(db); - def.into() - } - ast::ImplItem::ConstDef(it) => { - let def = ConstLoc { - container: AssocContainerId::ImplId(id), - ast_id: AstId::new(src.file_id, items.ast_id(&it)), - } - .intern(db); - def.into() - } - ast::ImplItem::TypeAliasDef(it) => { - let def = TypeAliasLoc { - container: AssocContainerId::ImplId(id), - ast_id: AstId::new(src.file_id, items.ast_id(&it)), - } - .intern(db); - def.into() - } - }) - .collect() - } else { - Vec::new() - }; + let mut items = Vec::new(); + if let Some(item_list) = src.value.item_list() { + items.extend(collect_impl_items(db, item_list.impl_items(), src.file_id, id)); + items.extend(collect_impl_items_in_macros( + db, + module_id, + &src.with_value(item_list), + id, + )); + } let res = ImplData { target_trait, target_type, items, is_negative }; Arc::new(res) @@ -237,3 +215,66 @@ impl ConstData { ConstData { name, type_ref } } } + +fn collect_impl_items_in_macros( + db: &impl DefDatabase, + module_id: ModuleId, + impl_block: &InFile, + id: ImplId, +) -> Vec { + let mut expander = Expander::new(db, impl_block.file_id, module_id); + let mut res = Vec::new(); + + for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { + if let Some((mark, items)) = expander.enter_expand(db, m) { + let items: InFile = expander.to_source(items); + expander.exit(db, mark); + res.extend(collect_impl_items( + db, + items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), + items.file_id, + id, + )); + } + } + + res +} + +fn collect_impl_items( + db: &impl DefDatabase, + impl_items: impl Iterator, + file_id: crate::HirFileId, + id: ImplId, +) -> Vec { + let items = db.ast_id_map(file_id); + + impl_items + .map(|item_node| match item_node { + ast::ImplItem::FnDef(it) => { + let def = FunctionLoc { + container: AssocContainerId::ImplId(id), + ast_id: AstId::new(file_id, items.ast_id(&it)), + } + .intern(db); + def.into() + } + ast::ImplItem::ConstDef(it) => { + let def = ConstLoc { + container: AssocContainerId::ImplId(id), + ast_id: AstId::new(file_id, items.ast_id(&it)), + } + .intern(db); + def.into() + } + ast::ImplItem::TypeAliasDef(it) => { + let def = TypeAliasLoc { + container: AssocContainerId::ImplId(id), + ast_id: AstId::new(file_id, items.ast_id(&it)), + } + .intern(db); + def.into() + } + }) + .collect() +} diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 8ed1599ffb..6bb5408a86 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -47,6 +47,7 @@ use ra_arena::{impl_arena_id, RawId}; use ra_db::{impl_intern_key, salsa, CrateId}; use ra_syntax::{ast, AstNode}; +use crate::body::Expander; use crate::builtin_type::BuiltinType; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index f68aca7898..d86445abff 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -188,6 +188,7 @@ fn to_fragment_kind(db: &dyn AstDatabase, macro_call_id: MacroCallId) -> Fragmen ARG_LIST => FragmentKind::Expr, TRY_EXPR => FragmentKind::Expr, TUPLE_EXPR => FragmentKind::Expr, + ITEM_LIST => FragmentKind::Items, _ => { // Unknown , Just guess it is `Items` FragmentKind::Items diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 812f171db8..7fdbf996f4 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -182,6 +182,25 @@ fn test() { S.foo()<|>; } assert_eq!(t, "u128"); } +#[test] +fn infer_impl_items_generated_by_macros() { + let t = type_at( + r#" +//- /main.rs +macro_rules! m { + () => (fn foo(&self) -> u128 {0}) +} +struct S; +impl S { + m!(); +} + +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + #[test] fn infer_macro_with_dollar_crate_is_correct_in_expr() { let (db, pos) = TestDB::with_position( From 0d5d63a80ea08f2af439bcc72fff9b24d144c70d Mon Sep 17 00:00:00 2001 From: kjeremy Date: Fri, 20 Dec 2019 15:14:30 -0500 Subject: [PATCH 274/312] Clippy lints --- crates/ra_assists/src/assists/early_return.rs | 10 ++-- crates/ra_hir_def/src/nameres/collector.rs | 4 +- crates/ra_hir_expand/src/builtin_macro.rs | 2 +- crates/ra_hir_expand/src/db.rs | 9 ++-- crates/ra_hir_ty/src/autoderef.rs | 4 +- crates/ra_hir_ty/src/lib.rs | 2 +- .../ra_ide/src/completion/complete_postfix.rs | 2 +- .../src/completion/completion_context.rs | 17 ++++--- crates/ra_ide/src/expand_macro.rs | 13 ++--- crates/ra_ide/src/extend_selection.rs | 2 +- crates/ra_ide/src/syntax_highlighting.rs | 48 +++++++++---------- crates/ra_lsp_server/src/main_loop.rs | 2 +- .../ra_lsp_server/src/main_loop/handlers.rs | 2 +- crates/ra_lsp_server/src/world.rs | 20 ++++---- crates/ra_mbe/src/lib.rs | 4 +- crates/ra_syntax/src/ast/make.rs | 3 +- 16 files changed, 67 insertions(+), 77 deletions(-) diff --git a/crates/ra_assists/src/assists/early_return.rs b/crates/ra_assists/src/assists/early_return.rs index 2644125266..023917aca7 100644 --- a/crates/ra_assists/src/assists/early_return.rs +++ b/crates/ra_assists/src/assists/early_return.rs @@ -83,8 +83,8 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let parent_container = parent_block.syntax().parent()?.parent()?; let early_expression: ast::Expr = match parent_container.kind() { - WHILE_EXPR | LOOP_EXPR => make::expr_continue().into(), - FN_DEF => make::expr_return().into(), + WHILE_EXPR | LOOP_EXPR => make::expr_continue(), + FN_DEF => make::expr_return(), _ => return None, }; @@ -116,13 +116,13 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt ) .into(), ), - make::expr_path(make::path_from_name_ref(make::name_ref("it"))).into(), + make::expr_path(make::path_from_name_ref(make::name_ref("it"))), ); let sad_arm = make::match_arm( // FIXME: would be cool to use `None` or `Err(_)` if appropriate once(make::placeholder_pat().into()), - early_expression.into(), + early_expression, ); make::expr_match(cond_expr, make::match_arm_list(vec![happy_arm, sad_arm])) @@ -130,7 +130,7 @@ pub(crate) fn convert_to_guarded_return(ctx: AssistCtx) -> Opt let let_stmt = make::let_stmt( make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(), - Some(match_expr.into()), + Some(match_expr), ); let let_stmt = if_indent_level.increase_indent(let_stmt); replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr) diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e68bf48688..3d8ca5dce3 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -406,14 +406,14 @@ where let resolutions = enum_data .variants .iter() - .filter_map(|(local_id, variant_data)| { + .map(|(local_id, variant_data)| { let name = variant_data.name.clone(); let variant = EnumVariantId { parent: e, local_id }; let res = Resolution { def: PerNs::both(variant.into(), variant.into()), import: Some(import_id), }; - Some((name, res)) + (name, res) }) .collect::>(); self.update(module_id, Some(import_id), &resolutions); diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 1749b491b9..857f8a4441 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -138,7 +138,7 @@ fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize if c == '\n' { break; } - col_num = col_num + 1; + col_num += 1; } col_num } diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index f68aca7898..42e599fec7 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs @@ -93,12 +93,11 @@ pub(crate) fn macro_def( Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) } MacroDefKind::BuiltIn(expander) => { - Some(Arc::new((TokenExpander::Builtin(expander.clone()), mbe::TokenMap::default()))) + Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) + } + MacroDefKind::BuiltInDerive(expander) => { + Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) } - MacroDefKind::BuiltInDerive(expander) => Some(Arc::new(( - TokenExpander::BuiltinDerive(expander.clone()), - mbe::TokenMap::default(), - ))), } } diff --git a/crates/ra_hir_ty/src/autoderef.rs b/crates/ra_hir_ty/src/autoderef.rs index ee48fa5370..f32d5786af 100644 --- a/crates/ra_hir_ty/src/autoderef.rs +++ b/crates/ra_hir_ty/src/autoderef.rs @@ -48,7 +48,7 @@ fn deref_by_trait( krate: CrateId, ty: InEnvironment<&Canonical>, ) -> Option> { - let deref_trait = match db.lang_item(krate.into(), "deref".into())? { + let deref_trait = match db.lang_item(krate, "deref".into())? { LangItemTarget::TraitId(it) => it, _ => return None, }; @@ -78,7 +78,7 @@ fn deref_by_trait( let canonical = super::Canonical { num_vars: 1 + ty.value.num_vars, value: in_env }; - let solution = db.trait_solve(krate.into(), canonical)?; + let solution = db.trait_solve(krate, canonical)?; match &solution { Solution::Unique(vars) => { diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index 7310ef10d9..48abf97c92 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs @@ -919,7 +919,7 @@ impl HirDisplay for ApplicationTy { { Option::None => self.parameters.0.as_ref(), Option::Some(default_parameters) => { - for (i, parameter) in self.parameters.into_iter().enumerate() { + for (i, parameter) in self.parameters.iter().enumerate() { match (parameter, default_parameters.get(i)) { (&Ty::Unknown, _) | (_, None) => { non_default_parameters.push(parameter.clone()) diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 646a30c76e..5470dc291f 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs @@ -12,7 +12,7 @@ use crate::{ }; pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { - if ctx.db.feature_flags.get("completion.enable-postfix") == false { + if !ctx.db.feature_flags.get("completion.enable-postfix") { return; } diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 981da2b794..4894ea2f6b 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -239,16 +239,15 @@ impl<'a> CompletionContext<'a> { .expr() .map(|e| e.syntax().text_range()) .and_then(|r| find_node_with_range(original_file.syntax(), r)); - self.dot_receiver_is_ambiguous_float_literal = if let Some(ast::Expr::Literal(l)) = - &self.dot_receiver - { - match l.kind() { - ast::LiteralKind::FloatNumber { suffix: _ } => l.token().text().ends_with('.'), - _ => false, + self.dot_receiver_is_ambiguous_float_literal = + if let Some(ast::Expr::Literal(l)) = &self.dot_receiver { + match l.kind() { + ast::LiteralKind::FloatNumber { .. } => l.token().text().ends_with('.'), + _ => false, + } + } else { + false } - } else { - false - } } if let Some(method_call_expr) = ast::MethodCallExpr::cast(parent) { // As above diff --git a/crates/ra_ide/src/expand_macro.rs b/crates/ra_ide/src/expand_macro.rs index 862c03304a..bdbc31704b 100644 --- a/crates/ra_ide/src/expand_macro.rs +++ b/crates/ra_ide/src/expand_macro.rs @@ -86,21 +86,18 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { let mut is_next = |f: fn(SyntaxKind) -> bool, default| -> bool { token_iter.peek().map(|it| f(it.kind())).unwrap_or(default) }; - let is_last = |f: fn(SyntaxKind) -> bool, default| -> bool { - last.map(|it| f(it)).unwrap_or(default) - }; + let is_last = + |f: fn(SyntaxKind) -> bool, default| -> bool { last.map(f).unwrap_or(default) }; res += &match token.kind() { - k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { - token.text().to_string() + " " - } + k if is_text(k) && is_next(|it| !it.is_punct(), true) => token.text().to_string() + " ", L_CURLY if is_next(|it| it != R_CURLY, true) => { indent += 1; - let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; + let leading_space = if is_last(is_text, false) { " " } else { "" }; format!("{}{{\n{}", leading_space, " ".repeat(indent)) } R_CURLY if is_last(|it| it != L_CURLY, true) => { - indent = indent.checked_sub(1).unwrap_or(0); + indent = indent.saturating_sub(1); format!("\n{}}}", " ".repeat(indent)) } R_CURLY => format!("}}\n{}", " ".repeat(indent)), diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index c096ca6ae4..1ec41a117b 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs @@ -138,7 +138,7 @@ fn extend_ws(root: &SyntaxNode, ws: SyntaxToken, offset: TextUnit) -> TextRange ws.text_range() } -fn pick_best<'a>(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { +fn pick_best(l: SyntaxToken, r: SyntaxToken) -> SyntaxToken { return if priority(&r) > priority(&l) { r } else { l }; fn priority(n: &SyntaxToken) -> usize { match n.kind() { diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 657c7b21a5..0228ee7e90 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs @@ -17,31 +17,31 @@ use crate::{ }; pub mod tags { - pub(crate) const FIELD: &'static str = "field"; - pub(crate) const FUNCTION: &'static str = "function"; - pub(crate) const MODULE: &'static str = "module"; - pub(crate) const TYPE: &'static str = "type"; - pub(crate) const CONSTANT: &'static str = "constant"; - pub(crate) const MACRO: &'static str = "macro"; - pub(crate) const VARIABLE: &'static str = "variable"; - pub(crate) const VARIABLE_MUT: &'static str = "variable.mut"; - pub(crate) const TEXT: &'static str = "text"; + pub(crate) const FIELD: &str = "field"; + pub(crate) const FUNCTION: &str = "function"; + pub(crate) const MODULE: &str = "module"; + pub(crate) const TYPE: &str = "type"; + pub(crate) const CONSTANT: &str = "constant"; + pub(crate) const MACRO: &str = "macro"; + pub(crate) const VARIABLE: &str = "variable"; + pub(crate) const VARIABLE_MUT: &str = "variable.mut"; + pub(crate) const TEXT: &str = "text"; - pub(crate) const TYPE_BUILTIN: &'static str = "type.builtin"; - pub(crate) const TYPE_SELF: &'static str = "type.self"; - pub(crate) const TYPE_PARAM: &'static str = "type.param"; - pub(crate) const TYPE_LIFETIME: &'static str = "type.lifetime"; + pub(crate) const TYPE_BUILTIN: &str = "type.builtin"; + pub(crate) const TYPE_SELF: &str = "type.self"; + pub(crate) const TYPE_PARAM: &str = "type.param"; + pub(crate) const TYPE_LIFETIME: &str = "type.lifetime"; - pub(crate) const LITERAL_BYTE: &'static str = "literal.byte"; - pub(crate) const LITERAL_NUMERIC: &'static str = "literal.numeric"; - pub(crate) const LITERAL_CHAR: &'static str = "literal.char"; - pub(crate) const LITERAL_COMMENT: &'static str = "comment"; - pub(crate) const LITERAL_STRING: &'static str = "string"; - pub(crate) const LITERAL_ATTRIBUTE: &'static str = "attribute"; + pub(crate) const LITERAL_BYTE: &str = "literal.byte"; + pub(crate) const LITERAL_NUMERIC: &str = "literal.numeric"; + pub(crate) const LITERAL_CHAR: &str = "literal.char"; + pub(crate) const LITERAL_COMMENT: &str = "comment"; + pub(crate) const LITERAL_STRING: &str = "string"; + pub(crate) const LITERAL_ATTRIBUTE: &str = "attribute"; - pub(crate) const KEYWORD_UNSAFE: &'static str = "keyword.unsafe"; - pub(crate) const KEYWORD_CONTROL: &'static str = "keyword.control"; - pub(crate) const KEYWORD: &'static str = "keyword"; + pub(crate) const KEYWORD_UNSAFE: &str = "keyword.unsafe"; + pub(crate) const KEYWORD_CONTROL: &str = "keyword.control"; + pub(crate) const KEYWORD: &str = "keyword"; } #[derive(Debug)] @@ -258,9 +258,7 @@ fn highlight_name(db: &RootDatabase, name_kind: NameKind) -> &'static str { SelfType(_) => tags::TYPE_SELF, TypeParam(_) => tags::TYPE_PARAM, Local(local) => { - if local.is_mut(db) { - tags::VARIABLE_MUT - } else if local.ty(db).is_mutable_reference() { + if local.is_mut(db) || local.ty(db).is_mutable_reference() { tags::VARIABLE_MUT } else { tags::VARIABLE diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 965e7c53c1..9e207415e6 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -131,7 +131,7 @@ pub fn main_loop( let feature_flags = { let mut ff = FeatureFlags::default(); for (flag, value) in config.feature_flags { - if let Err(_) = ff.set(flag.as_str(), value) { + if ff.set(flag.as_str(), value).is_err() { log::error!("unknown feature flag: {:?}", flag); show_message( req::MessageType::Error, diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5b64b27cd2..5e3b1a73f0 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -164,7 +164,7 @@ pub fn handle_on_type_formatting( // in `ra_ide`, the `on_type` invariant is that // `text.char_at(position) == typed_char`. - position.offset = position.offset - TextUnit::of_char('.'); + position.offset -= TextUnit::of_char('.'); let char_typed = params.ch.chars().next().unwrap_or('\0'); // We have an assist that inserts ` ` after typing `->` in `fn foo() ->{`, diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 16cc11e8ce..f89b23089e 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -287,19 +287,15 @@ impl WorldSnapshot { /// /// When processing non-windows path, this is essentially the same as `Url::from_file_path`. fn url_from_path_with_drive_lowercasing(path: impl AsRef) -> Result { - let component_has_windows_drive = path - .as_ref() - .components() - .find(|comp| { - if let Component::Prefix(c) = comp { - match c.kind() { - Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true, - _ => return false, - } + let component_has_windows_drive = path.as_ref().components().any(|comp| { + if let Component::Prefix(c) = comp { + match c.kind() { + Prefix::Disk(_) | Prefix::VerbatimDisk(_) => return true, + _ => return false, } - false - }) - .is_some(); + } + false + }); // VSCode expects drive letters to be lowercased, where rust will uppercase the drive letters. if component_has_windows_drive { diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 45dad2d108..2c6ae56589 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -97,7 +97,9 @@ impl Shift { tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id), }, tt::TokenTree::Subtree(tt) => { - tt.delimiter.as_mut().map(|it: &mut Delimiter| it.id = self.shift(it.id)); + if let Some(it) = tt.delimiter.as_mut() { + it.id = self.shift(it.id); + }; self.shift_all(tt) } } diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 40db570da0..04a5408fef 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs @@ -168,8 +168,7 @@ pub fn let_stmt(pattern: ast::Pat, initializer: Option) -> ast::LetSt fn ast_from_text(text: &str) -> N { let parse = SourceFile::parse(text); - let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); - res + parse.tree().syntax().descendants().find_map(N::cast).unwrap() } pub mod tokens { From 360de5ba71a631a118a088dba7c975e9ae592452 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 05:02:31 +0800 Subject: [PATCH 275/312] Recursive collect macros in impl items --- crates/ra_hir_def/src/data.rs | 38 ++++++++++++++++++++-------- crates/ra_hir_ty/src/tests/macros.rs | 23 +++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index b0a3f17845..6a65633aef 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -226,21 +226,39 @@ fn collect_impl_items_in_macros( let mut res = Vec::new(); for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { - if let Some((mark, items)) = expander.enter_expand(db, m) { - let items: InFile = expander.to_source(items); - expander.exit(db, mark); - res.extend(collect_impl_items( - db, - items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), - items.file_id, - id, - )); - } + res.extend(collect_impl_items_in_macro(db, &mut expander, m, id)) } res } +fn collect_impl_items_in_macro( + db: &impl DefDatabase, + expander: &mut Expander, + m: ast::MacroCall, + id: ImplId, +) -> Vec { + if let Some((mark, items)) = expander.enter_expand(db, m) { + let items: InFile = expander.to_source(items); + let mut res = collect_impl_items( + db, + items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), + items.file_id, + id, + ); + // Recursive collect macros + // Note that ast::ModuleItem do not include ast::MacroCall + // We cannot use ModuleItemOwner::items here + for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { + res.extend(collect_impl_items_in_macro(db, expander, it, id)) + } + expander.exit(db, mark); + res + } else { + Vec::new() + } +} + fn collect_impl_items( db: &impl DefDatabase, impl_items: impl Iterator, diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 7fdbf996f4..69c695cc8f 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -201,6 +201,29 @@ fn test() { S.foo()<|>; } assert_eq!(t, "u128"); } +#[test] +fn infer_impl_items_generated_by_macros_chain() { + let t = type_at( + r#" +//- /main.rs +macro_rules! m_inner { + () => {fn foo(&self) -> u128 {0}} +} +macro_rules! m { + () => {m_inner!();} +} + +struct S; +impl S { + m!(); +} + +fn test() { S.foo()<|>; } +"#, + ); + assert_eq!(t, "u128"); +} + #[test] fn infer_macro_with_dollar_crate_is_correct_in_expr() { let (db, pos) = TestDB::with_position( From c1166697a74bca690443525ced8cd8bc08894779 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 05:16:29 +0800 Subject: [PATCH 276/312] Add a limit for protect against infinite recursion --- crates/ra_hir_def/src/data.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 6a65633aef..1aa9a9b7d7 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs @@ -225,8 +225,11 @@ fn collect_impl_items_in_macros( let mut expander = Expander::new(db, impl_block.file_id, module_id); let mut res = Vec::new(); + // We set a limit to protect against infinite recursion + let limit = 100; + for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { - res.extend(collect_impl_items_in_macro(db, &mut expander, m, id)) + res.extend(collect_impl_items_in_macro(db, &mut expander, m, id, limit)) } res @@ -237,7 +240,12 @@ fn collect_impl_items_in_macro( expander: &mut Expander, m: ast::MacroCall, id: ImplId, + limit: usize, ) -> Vec { + if limit == 0 { + return Vec::new(); + } + if let Some((mark, items)) = expander.enter_expand(db, m) { let items: InFile = expander.to_source(items); let mut res = collect_impl_items( @@ -250,7 +258,7 @@ fn collect_impl_items_in_macro( // Note that ast::ModuleItem do not include ast::MacroCall // We cannot use ModuleItemOwner::items here for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { - res.extend(collect_impl_items_in_macro(db, expander, it, id)) + res.extend(collect_impl_items_in_macro(db, expander, it, id, limit - 1)) } expander.exit(db, mark); res From 429199d4815a001e1b60089b4f34c3ae6b7204f9 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Fri, 20 Dec 2019 18:57:31 -0500 Subject: [PATCH 277/312] Use SelectionRange from LSP 3.15 --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- crates/ra_lsp_server/src/caps.rs | 11 ++++++----- crates/ra_lsp_server/src/req.rs | 27 +++------------------------ 4 files changed, 13 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3f2cbc8ab0..c29ce324e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.63.1" +version = "0.65.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1049,7 +1049,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.63.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1841,7 +1841,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.63.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70090cea3cd5db0aa923575e03874b33da90c4d0fe1eaf63fa51b8925a78ef03" +"checksum lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fe9e427e63e6172699737b47f1044bcade7046e2404d59ebd90c459da47cd2b" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index e29b688fdb..e826c10ef0 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.63.1", features = ["proposed"] } +lsp-types = { version = "0.65.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0" diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index e0bb756666..d812ff7ca2 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -2,10 +2,11 @@ use lsp_types::{ CodeActionProviderCapability, CodeLensOptions, CompletionOptions, - DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, GenericCapability, - ImplementationProviderCapability, RenameOptions, RenameProviderCapability, ServerCapabilities, - SignatureHelpOptions, TextDocumentSyncCapability, TextDocumentSyncKind, - TextDocumentSyncOptions, TypeDefinitionProviderCapability, WorkDoneProgressOptions, + DocumentOnTypeFormattingOptions, FoldingRangeProviderCapability, + ImplementationProviderCapability, RenameOptions, RenameProviderCapability, + SelectionRangeProviderCapability, ServerCapabilities, SignatureHelpOptions, + TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, + TypeDefinitionProviderCapability, WorkDoneProgressOptions, }; pub fn server_capabilities() -> ServerCapabilities { @@ -44,7 +45,7 @@ pub fn server_capabilities() -> ServerCapabilities { first_trigger_character: "=".to_string(), more_trigger_character: Some(vec![".".to_string(), ">".to_string()]), }), - selection_range_provider: Some(GenericCapability::default()), + selection_range_provider: Some(SelectionRangeProviderCapability::Simple(true)), folding_range_provider: Some(FoldingRangeProviderCapability::Simple(true)), rename_provider: Some(RenameProviderCapability::Options(RenameOptions { prepare_provider: Some(true), diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 39361b7e8f..2a22b655ce 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -10,8 +10,9 @@ pub use lsp_types::{ DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions, DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, FileSystemWatcher, Hover, InitializeResult, MessageType, PublishDiagnosticsParams, - ReferenceParams, Registration, RegistrationParams, ShowMessageParams, SignatureHelp, - TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams, + ReferenceParams, Registration, RegistrationParams, SelectionRange, SelectionRangeParams, + ShowMessageParams, SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, TextEdit, + WorkspaceEdit, WorkspaceSymbolParams, }; pub enum AnalyzerStatus {} @@ -67,28 +68,6 @@ pub struct ExpandMacroParams { pub position: Option, } -pub enum SelectionRangeRequest {} - -impl Request for SelectionRangeRequest { - type Params = SelectionRangeParams; - type Result = Vec; - const METHOD: &'static str = "textDocument/selectionRange"; -} - -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct SelectionRangeParams { - pub text_document: TextDocumentIdentifier, - pub positions: Vec, -} - -#[derive(Serialize, Debug)] -#[serde(rename_all = "camelCase")] -pub struct SelectionRange { - pub range: Range, - pub parent: Option>, -} - pub enum FindMatchingBrace {} impl Request for FindMatchingBrace { From bea8f581186bb8d933357599468dd7d862ae847b Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 18:29:14 +0800 Subject: [PATCH 278/312] Add macro 2.0 support in parser --- crates/ra_parser/src/grammar/items.rs | 28 ++ crates/ra_parser/src/syntax_kind/generated.rs | 8 +- crates/ra_syntax/src/grammar.ron | 4 +- .../test_data/parser/err/0028_macro_2.0.txt | 328 ------------------ .../parser/inline/ok/0147_macro_def.rs | 2 + .../parser/inline/ok/0147_macro_def.txt | 43 +++ .../parser/inline/ok/0148_pub_macro_def.rs | 1 + .../parser/inline/ok/0148_pub_macro_def.txt | 20 ++ .../0062_macro_2.0.rs} | 0 .../test_data/parser/ok/0062_macro_2.0.txt | 174 ++++++++++ 10 files changed, 278 insertions(+), 330 deletions(-) delete mode 100644 crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt rename crates/ra_syntax/test_data/parser/{err/0028_macro_2.0.rs => ok/0062_macro_2.0.rs} (100%) create mode 100644 crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 370990e21f..7e345f733d 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -249,6 +249,11 @@ fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> { // } adt::struct_def(p, m); } + // test pub_macro_def + // pub macro m($:ident) {} + T![macro] => { + macro_def(p, m); + } IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { // test union_items // union Foo {} @@ -379,6 +384,29 @@ pub(crate) fn mod_item_list(p: &mut Parser) { m.complete(p, ITEM_LIST); } +// test macro_def +// macro m { ($i:ident) => {} } +// macro m($i:ident) {} +fn macro_def(p: &mut Parser, m: Marker) { + p.expect(T![macro]); + p.expect(IDENT); + if p.at(T!['{']) { + token_tree(p); + } else if !p.at(T!['(']) { + p.error("unmatched `(`"); + } else { + let m = p.start(); + token_tree(p); + match p.current() { + T!['{'] | T!['['] | T!['('] => token_tree(p), + _ => p.error("expected `{`, `[`, `(`"), + } + m.complete(p, TOKEN_TREE); + } + + m.complete(p, MACRO_DEF); +} + fn macro_call(p: &mut Parser) -> BlockLike { assert!(paths::is_use_path_start(p)); paths::use_path(p); diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index fe0fcdb33f..afe4ce51a9 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -100,6 +100,7 @@ pub enum SyntaxKind { TRY_KW, BOX_KW, AWAIT_KW, + MACRO_KW, AUTO_KW, DEFAULT_KW, EXISTENTIAL_KW, @@ -136,6 +137,7 @@ pub enum SyntaxKind { TYPE_ALIAS_DEF, MACRO_CALL, TOKEN_TREE, + MACRO_DEF, PAREN_TYPE, TUPLE_TYPE, NEVER_TYPE, @@ -251,7 +253,7 @@ impl SyntaxKind { | SUPER_KW | IN_KW | WHERE_KW | FOR_KW | LOOP_KW | WHILE_KW | CONTINUE_KW | BREAK_KW | IF_KW | ELSE_KW | MATCH_KW | CONST_KW | STATIC_KW | MUT_KW | UNSAFE_KW | TYPE_KW | REF_KW | LET_KW | MOVE_KW | RETURN_KW | TRY_KW | BOX_KW | AWAIT_KW - | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true, + | MACRO_KW | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true, _ => false, } } @@ -314,6 +316,7 @@ impl SyntaxKind { "try" => TRY_KW, "box" => BOX_KW, "await" => AWAIT_KW, + "macro" => MACRO_KW, _ => return None, }; Some(kw) @@ -628,6 +631,9 @@ macro_rules! T { ( await ) => { $crate::SyntaxKind::AWAIT_KW }; + ( macro ) => { + $crate::SyntaxKind::MACRO_KW + }; ( auto ) => { $crate::SyntaxKind::AUTO_KW }; diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index a228fa9d6e..3f1cd0b903 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -94,7 +94,8 @@ Grammar( "return", "try", "box", - "await" + "await", + "macro" ], contextual_keywords: [ "auto", @@ -140,6 +141,7 @@ Grammar( "TYPE_ALIAS_DEF", "MACRO_CALL", "TOKEN_TREE", + "MACRO_DEF", "PAREN_TYPE", "TUPLE_TYPE", diff --git a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt b/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt deleted file mode 100644 index c5be73a5a0..0000000000 --- a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.txt +++ /dev/null @@ -1,328 +0,0 @@ -SOURCE_FILE@[0; 349) - MACRO_CALL@[0; 41) - PATH@[0; 5) - PATH_SEGMENT@[0; 5) - NAME_REF@[0; 5) - IDENT@[0; 5) "macro" - WHITESPACE@[5; 6) " " - NAME@[6; 21) - IDENT@[6; 21) "parse_use_trees" - TOKEN_TREE@[21; 41) - L_PAREN@[21; 22) "(" - DOLLAR@[22; 23) "$" - TOKEN_TREE@[23; 32) - L_PAREN@[23; 24) "(" - DOLLAR@[24; 25) "$" - IDENT@[25; 26) "s" - COLON@[26; 27) ":" - IDENT@[27; 31) "expr" - R_PAREN@[31; 32) ")" - COMMA@[32; 33) "," - STAR@[33; 34) "*" - WHITESPACE@[34; 35) " " - DOLLAR@[35; 36) "$" - TOKEN_TREE@[36; 39) - L_PAREN@[36; 37) "(" - COMMA@[37; 38) "," - R_PAREN@[38; 39) ")" - STAR@[39; 40) "*" - R_PAREN@[40; 41) ")" - WHITESPACE@[41; 42) " " - ERROR@[42; 93) - L_CURLY@[42; 43) "{" - WHITESPACE@[43; 48) "\n " - MACRO_CALL@[48; 91) - PATH@[48; 51) - PATH_SEGMENT@[48; 51) - NAME_REF@[48; 51) - IDENT@[48; 51) "vec" - EXCL@[51; 52) "!" - TOKEN_TREE@[52; 91) - L_BRACK@[52; 53) "[" - WHITESPACE@[53; 62) "\n " - DOLLAR@[62; 63) "$" - TOKEN_TREE@[63; 84) - L_PAREN@[63; 64) "(" - IDENT@[64; 78) "parse_use_tree" - TOKEN_TREE@[78; 82) - L_PAREN@[78; 79) "(" - DOLLAR@[79; 80) "$" - IDENT@[80; 81) "s" - R_PAREN@[81; 82) ")" - COMMA@[82; 83) "," - R_PAREN@[83; 84) ")" - STAR@[84; 85) "*" - WHITESPACE@[85; 90) "\n " - R_BRACK@[90; 91) "]" - WHITESPACE@[91; 92) "\n" - R_CURLY@[92; 93) "}" - WHITESPACE@[93; 95) "\n\n" - FN_DEF@[95; 348) - ATTR@[95; 102) - POUND@[95; 96) "#" - L_BRACK@[96; 97) "[" - PATH@[97; 101) - PATH_SEGMENT@[97; 101) - NAME_REF@[97; 101) - IDENT@[97; 101) "test" - R_BRACK@[101; 102) "]" - WHITESPACE@[102; 103) "\n" - FN_KW@[103; 105) "fn" - WHITESPACE@[105; 106) " " - NAME@[106; 125) - IDENT@[106; 125) "test_use_tree_merge" - PARAM_LIST@[125; 127) - L_PAREN@[125; 126) "(" - R_PAREN@[126; 127) ")" - WHITESPACE@[127; 128) " " - BLOCK_EXPR@[128; 348) - BLOCK@[128; 348) - L_CURLY@[128; 129) "{" - WHITESPACE@[129; 134) "\n " - EXPR_STMT@[134; 139) - PATH_EXPR@[134; 139) - PATH@[134; 139) - PATH_SEGMENT@[134; 139) - NAME_REF@[134; 139) - IDENT@[134; 139) "macro" - WHITESPACE@[139; 140) " " - EXPR_STMT@[140; 154) - CALL_EXPR@[140; 154) - PATH_EXPR@[140; 150) - PATH@[140; 150) - PATH_SEGMENT@[140; 150) - NAME_REF@[140; 150) - IDENT@[140; 150) "test_merge" - ARG_LIST@[150; 154) - L_PAREN@[150; 151) "(" - ARRAY_EXPR@[151; 154) - L_BRACK@[151; 152) "[" - ERROR@[152; 153) - DOLLAR@[152; 153) "$" - PAREN_EXPR@[153; 154) - L_PAREN@[153; 154) "(" - EXPR_STMT@[154; 155) - ERROR@[154; 155) - DOLLAR@[154; 155) "$" - EXPR_STMT@[155; 160) - PATH_EXPR@[155; 160) - PATH@[155; 160) - PATH_SEGMENT@[155; 160) - NAME_REF@[155; 160) - IDENT@[155; 160) "input" - EXPR_STMT@[160; 161) - ERROR@[160; 161) - COLON@[160; 161) ":" - EXPR_STMT@[161; 165) - PATH_EXPR@[161; 165) - PATH@[161; 165) - PATH_SEGMENT@[161; 165) - NAME_REF@[161; 165) - IDENT@[161; 165) "expr" - EXPR_STMT@[165; 166) - ERROR@[165; 166) - R_PAREN@[165; 166) ")" - EXPR_STMT@[166; 167) - ERROR@[166; 167) - COMMA@[166; 167) "," - EXPR_STMT@[167; 170) - PREFIX_EXPR@[167; 170) - STAR@[167; 168) "*" - WHITESPACE@[168; 169) " " - ERROR@[169; 170) - DOLLAR@[169; 170) "$" - EXPR_STMT@[170; 171) - PAREN_EXPR@[170; 171) - L_PAREN@[170; 171) "(" - EXPR_STMT@[171; 172) - ERROR@[171; 172) - COMMA@[171; 172) "," - EXPR_STMT@[172; 173) - ERROR@[172; 173) - R_PAREN@[172; 173) ")" - EXPR_STMT@[173; 175) - PREFIX_EXPR@[173; 175) - STAR@[173; 174) "*" - ERROR@[174; 175) - R_BRACK@[174; 175) "]" - EXPR_STMT@[175; 176) - ERROR@[175; 176) - COMMA@[175; 176) "," - WHITESPACE@[176; 177) " " - EXPR_STMT@[177; 180) - ARRAY_EXPR@[177; 180) - L_BRACK@[177; 178) "[" - ERROR@[178; 179) - DOLLAR@[178; 179) "$" - PAREN_EXPR@[179; 180) - L_PAREN@[179; 180) "(" - EXPR_STMT@[180; 181) - ERROR@[180; 181) - DOLLAR@[180; 181) "$" - EXPR_STMT@[181; 187) - PATH_EXPR@[181; 187) - PATH@[181; 187) - PATH_SEGMENT@[181; 187) - NAME_REF@[181; 187) - IDENT@[181; 187) "output" - EXPR_STMT@[187; 188) - ERROR@[187; 188) - COLON@[187; 188) ":" - EXPR_STMT@[188; 192) - PATH_EXPR@[188; 192) - PATH@[188; 192) - PATH_SEGMENT@[188; 192) - NAME_REF@[188; 192) - IDENT@[188; 192) "expr" - EXPR_STMT@[192; 193) - ERROR@[192; 193) - R_PAREN@[192; 193) ")" - EXPR_STMT@[193; 194) - ERROR@[193; 194) - COMMA@[193; 194) "," - EXPR_STMT@[194; 197) - PREFIX_EXPR@[194; 197) - STAR@[194; 195) "*" - WHITESPACE@[195; 196) " " - ERROR@[196; 197) - DOLLAR@[196; 197) "$" - EXPR_STMT@[197; 198) - PAREN_EXPR@[197; 198) - L_PAREN@[197; 198) "(" - EXPR_STMT@[198; 199) - ERROR@[198; 199) - COMMA@[198; 199) "," - EXPR_STMT@[199; 200) - ERROR@[199; 200) - R_PAREN@[199; 200) ")" - EXPR_STMT@[200; 202) - PREFIX_EXPR@[200; 202) - STAR@[200; 201) "*" - ERROR@[201; 202) - R_BRACK@[201; 202) "]" - EXPR_STMT@[202; 203) - ERROR@[202; 203) - R_PAREN@[202; 203) ")" - WHITESPACE@[203; 204) " " - BLOCK_EXPR@[204; 346) - BLOCK@[204; 346) - L_CURLY@[204; 205) "{" - WHITESPACE@[205; 214) "\n " - EXPR_STMT@[214; 340) - MACRO_CALL@[214; 339) - PATH@[214; 223) - PATH_SEGMENT@[214; 223) - NAME_REF@[214; 223) - IDENT@[214; 223) "assert_eq" - EXCL@[223; 224) "!" - TOKEN_TREE@[224; 339) - L_PAREN@[224; 225) "(" - WHITESPACE@[225; 238) "\n " - IDENT@[238; 253) "merge_use_trees" - TOKEN_TREE@[253; 284) - L_PAREN@[253; 254) "(" - IDENT@[254; 269) "parse_use_trees" - EXCL@[269; 270) "!" - TOKEN_TREE@[270; 283) - L_PAREN@[270; 271) "(" - DOLLAR@[271; 272) "$" - TOKEN_TREE@[272; 281) - L_PAREN@[272; 273) "(" - DOLLAR@[273; 274) "$" - IDENT@[274; 279) "input" - COMMA@[279; 280) "," - R_PAREN@[280; 281) ")" - STAR@[281; 282) "*" - R_PAREN@[282; 283) ")" - R_PAREN@[283; 284) ")" - COMMA@[284; 285) "," - WHITESPACE@[285; 298) "\n " - IDENT@[298; 313) "parse_use_trees" - EXCL@[313; 314) "!" - TOKEN_TREE@[314; 328) - L_PAREN@[314; 315) "(" - DOLLAR@[315; 316) "$" - TOKEN_TREE@[316; 326) - L_PAREN@[316; 317) "(" - DOLLAR@[317; 318) "$" - IDENT@[318; 324) "output" - COMMA@[324; 325) "," - R_PAREN@[325; 326) ")" - STAR@[326; 327) "*" - R_PAREN@[327; 328) ")" - COMMA@[328; 329) "," - WHITESPACE@[329; 338) "\n " - R_PAREN@[338; 339) ")" - SEMI@[339; 340) ";" - WHITESPACE@[340; 345) "\n " - R_CURLY@[345; 346) "}" - WHITESPACE@[346; 347) "\n" - R_CURLY@[347; 348) "}" - WHITESPACE@[348; 349) "\n" -error 5: expected EXCL -error 41: expected SEMI -error 42: expected an item -error 139: expected SEMI -error 152: expected expression -error 153: expected COMMA -error 154: expected expression -error 154: expected R_PAREN -error 154: expected COMMA -error 154: expected expression -error 154: expected R_BRACK -error 154: expected COMMA -error 154: expected SEMI -error 154: expected expression -error 155: expected SEMI -error 160: expected SEMI -error 160: expected expression -error 161: expected SEMI -error 165: expected SEMI -error 165: expected expression -error 166: expected SEMI -error 166: expected expression -error 167: expected SEMI -error 169: expected expression -error 170: expected SEMI -error 171: expected expression -error 171: expected R_PAREN -error 171: expected SEMI -error 171: expected expression -error 172: expected SEMI -error 172: expected expression -error 173: expected SEMI -error 174: expected expression -error 175: expected SEMI -error 175: expected expression -error 176: expected SEMI -error 178: expected expression -error 179: expected COMMA -error 180: expected expression -error 180: expected R_PAREN -error 180: expected COMMA -error 180: expected expression -error 180: expected R_BRACK -error 180: expected SEMI -error 180: expected expression -error 181: expected SEMI -error 187: expected SEMI -error 187: expected expression -error 188: expected SEMI -error 192: expected SEMI -error 192: expected expression -error 193: expected SEMI -error 193: expected expression -error 194: expected SEMI -error 196: expected expression -error 197: expected SEMI -error 198: expected expression -error 198: expected R_PAREN -error 198: expected SEMI -error 198: expected expression -error 199: expected SEMI -error 199: expected expression -error 200: expected SEMI -error 201: expected expression -error 202: expected SEMI -error 202: expected expression -error 203: expected SEMI diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs new file mode 100644 index 0000000000..319a4e2aad --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.rs @@ -0,0 +1,2 @@ +macro m { ($i:ident) => {} } +macro m($i:ident) {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt new file mode 100644 index 0000000000..af1122bfa4 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt @@ -0,0 +1,43 @@ +SOURCE_FILE@[0; 50) + MACRO_DEF@[0; 28) + MACRO_KW@[0; 5) "macro" + WHITESPACE@[5; 6) " " + IDENT@[6; 7) "m" + WHITESPACE@[7; 8) " " + TOKEN_TREE@[8; 28) + L_CURLY@[8; 9) "{" + WHITESPACE@[9; 10) " " + TOKEN_TREE@[10; 20) + L_PAREN@[10; 11) "(" + DOLLAR@[11; 12) "$" + IDENT@[12; 13) "i" + COLON@[13; 14) ":" + IDENT@[14; 19) "ident" + R_PAREN@[19; 20) ")" + WHITESPACE@[20; 21) " " + EQ@[21; 22) "=" + R_ANGLE@[22; 23) ">" + WHITESPACE@[23; 24) " " + TOKEN_TREE@[24; 26) + L_CURLY@[24; 25) "{" + R_CURLY@[25; 26) "}" + WHITESPACE@[26; 27) " " + R_CURLY@[27; 28) "}" + WHITESPACE@[28; 29) "\n" + MACRO_DEF@[29; 49) + MACRO_KW@[29; 34) "macro" + WHITESPACE@[34; 35) " " + IDENT@[35; 36) "m" + TOKEN_TREE@[36; 49) + TOKEN_TREE@[36; 46) + L_PAREN@[36; 37) "(" + DOLLAR@[37; 38) "$" + IDENT@[38; 39) "i" + COLON@[39; 40) ":" + IDENT@[40; 45) "ident" + R_PAREN@[45; 46) ")" + WHITESPACE@[46; 47) " " + TOKEN_TREE@[47; 49) + L_CURLY@[47; 48) "{" + R_CURLY@[48; 49) "}" + WHITESPACE@[49; 50) "\n" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs new file mode 100644 index 0000000000..3b2be597fd --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.rs @@ -0,0 +1 @@ +pub macro m($:ident) {} diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt new file mode 100644 index 0000000000..985f61f89e --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt @@ -0,0 +1,20 @@ +SOURCE_FILE@[0; 24) + MACRO_DEF@[0; 23) + VISIBILITY@[0; 3) + PUB_KW@[0; 3) "pub" + WHITESPACE@[3; 4) " " + MACRO_KW@[4; 9) "macro" + WHITESPACE@[9; 10) " " + IDENT@[10; 11) "m" + TOKEN_TREE@[11; 23) + TOKEN_TREE@[11; 20) + L_PAREN@[11; 12) "(" + DOLLAR@[12; 13) "$" + COLON@[13; 14) ":" + IDENT@[14; 19) "ident" + R_PAREN@[19; 20) ")" + WHITESPACE@[20; 21) " " + TOKEN_TREE@[21; 23) + L_CURLY@[21; 22) "{" + R_CURLY@[22; 23) "}" + WHITESPACE@[23; 24) "\n" diff --git a/crates/ra_syntax/test_data/parser/err/0028_macro_2.0.rs b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rs similarity index 100% rename from crates/ra_syntax/test_data/parser/err/0028_macro_2.0.rs rename to crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.rs diff --git a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt new file mode 100644 index 0000000000..158af85f55 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt @@ -0,0 +1,174 @@ +SOURCE_FILE@[0; 349) + MACRO_DEF@[0; 93) + MACRO_KW@[0; 5) "macro" + WHITESPACE@[5; 6) " " + IDENT@[6; 21) "parse_use_trees" + TOKEN_TREE@[21; 93) + TOKEN_TREE@[21; 41) + L_PAREN@[21; 22) "(" + DOLLAR@[22; 23) "$" + TOKEN_TREE@[23; 32) + L_PAREN@[23; 24) "(" + DOLLAR@[24; 25) "$" + IDENT@[25; 26) "s" + COLON@[26; 27) ":" + IDENT@[27; 31) "expr" + R_PAREN@[31; 32) ")" + COMMA@[32; 33) "," + STAR@[33; 34) "*" + WHITESPACE@[34; 35) " " + DOLLAR@[35; 36) "$" + TOKEN_TREE@[36; 39) + L_PAREN@[36; 37) "(" + COMMA@[37; 38) "," + R_PAREN@[38; 39) ")" + STAR@[39; 40) "*" + R_PAREN@[40; 41) ")" + WHITESPACE@[41; 42) " " + TOKEN_TREE@[42; 93) + L_CURLY@[42; 43) "{" + WHITESPACE@[43; 48) "\n " + IDENT@[48; 51) "vec" + EXCL@[51; 52) "!" + TOKEN_TREE@[52; 91) + L_BRACK@[52; 53) "[" + WHITESPACE@[53; 62) "\n " + DOLLAR@[62; 63) "$" + TOKEN_TREE@[63; 84) + L_PAREN@[63; 64) "(" + IDENT@[64; 78) "parse_use_tree" + TOKEN_TREE@[78; 82) + L_PAREN@[78; 79) "(" + DOLLAR@[79; 80) "$" + IDENT@[80; 81) "s" + R_PAREN@[81; 82) ")" + COMMA@[82; 83) "," + R_PAREN@[83; 84) ")" + STAR@[84; 85) "*" + WHITESPACE@[85; 90) "\n " + R_BRACK@[90; 91) "]" + WHITESPACE@[91; 92) "\n" + R_CURLY@[92; 93) "}" + WHITESPACE@[93; 95) "\n\n" + FN_DEF@[95; 348) + ATTR@[95; 102) + POUND@[95; 96) "#" + L_BRACK@[96; 97) "[" + PATH@[97; 101) + PATH_SEGMENT@[97; 101) + NAME_REF@[97; 101) + IDENT@[97; 101) "test" + R_BRACK@[101; 102) "]" + WHITESPACE@[102; 103) "\n" + FN_KW@[103; 105) "fn" + WHITESPACE@[105; 106) " " + NAME@[106; 125) + IDENT@[106; 125) "test_use_tree_merge" + PARAM_LIST@[125; 127) + L_PAREN@[125; 126) "(" + R_PAREN@[126; 127) ")" + WHITESPACE@[127; 128) " " + BLOCK_EXPR@[128; 348) + BLOCK@[128; 348) + L_CURLY@[128; 129) "{" + WHITESPACE@[129; 134) "\n " + MACRO_DEF@[134; 346) + MACRO_KW@[134; 139) "macro" + WHITESPACE@[139; 140) " " + IDENT@[140; 150) "test_merge" + TOKEN_TREE@[150; 346) + TOKEN_TREE@[150; 203) + L_PAREN@[150; 151) "(" + TOKEN_TREE@[151; 175) + L_BRACK@[151; 152) "[" + DOLLAR@[152; 153) "$" + TOKEN_TREE@[153; 166) + L_PAREN@[153; 154) "(" + DOLLAR@[154; 155) "$" + IDENT@[155; 160) "input" + COLON@[160; 161) ":" + IDENT@[161; 165) "expr" + R_PAREN@[165; 166) ")" + COMMA@[166; 167) "," + STAR@[167; 168) "*" + WHITESPACE@[168; 169) " " + DOLLAR@[169; 170) "$" + TOKEN_TREE@[170; 173) + L_PAREN@[170; 171) "(" + COMMA@[171; 172) "," + R_PAREN@[172; 173) ")" + STAR@[173; 174) "*" + R_BRACK@[174; 175) "]" + COMMA@[175; 176) "," + WHITESPACE@[176; 177) " " + TOKEN_TREE@[177; 202) + L_BRACK@[177; 178) "[" + DOLLAR@[178; 179) "$" + TOKEN_TREE@[179; 193) + L_PAREN@[179; 180) "(" + DOLLAR@[180; 181) "$" + IDENT@[181; 187) "output" + COLON@[187; 188) ":" + IDENT@[188; 192) "expr" + R_PAREN@[192; 193) ")" + COMMA@[193; 194) "," + STAR@[194; 195) "*" + WHITESPACE@[195; 196) " " + DOLLAR@[196; 197) "$" + TOKEN_TREE@[197; 200) + L_PAREN@[197; 198) "(" + COMMA@[198; 199) "," + R_PAREN@[199; 200) ")" + STAR@[200; 201) "*" + R_BRACK@[201; 202) "]" + R_PAREN@[202; 203) ")" + WHITESPACE@[203; 204) " " + TOKEN_TREE@[204; 346) + L_CURLY@[204; 205) "{" + WHITESPACE@[205; 214) "\n " + IDENT@[214; 223) "assert_eq" + EXCL@[223; 224) "!" + TOKEN_TREE@[224; 339) + L_PAREN@[224; 225) "(" + WHITESPACE@[225; 238) "\n " + IDENT@[238; 253) "merge_use_trees" + TOKEN_TREE@[253; 284) + L_PAREN@[253; 254) "(" + IDENT@[254; 269) "parse_use_trees" + EXCL@[269; 270) "!" + TOKEN_TREE@[270; 283) + L_PAREN@[270; 271) "(" + DOLLAR@[271; 272) "$" + TOKEN_TREE@[272; 281) + L_PAREN@[272; 273) "(" + DOLLAR@[273; 274) "$" + IDENT@[274; 279) "input" + COMMA@[279; 280) "," + R_PAREN@[280; 281) ")" + STAR@[281; 282) "*" + R_PAREN@[282; 283) ")" + R_PAREN@[283; 284) ")" + COMMA@[284; 285) "," + WHITESPACE@[285; 298) "\n " + IDENT@[298; 313) "parse_use_trees" + EXCL@[313; 314) "!" + TOKEN_TREE@[314; 328) + L_PAREN@[314; 315) "(" + DOLLAR@[315; 316) "$" + TOKEN_TREE@[316; 326) + L_PAREN@[316; 317) "(" + DOLLAR@[317; 318) "$" + IDENT@[318; 324) "output" + COMMA@[324; 325) "," + R_PAREN@[325; 326) ")" + STAR@[326; 327) "*" + R_PAREN@[327; 328) ")" + COMMA@[328; 329) "," + WHITESPACE@[329; 338) "\n " + R_PAREN@[338; 339) ")" + SEMI@[339; 340) ";" + WHITESPACE@[340; 345) "\n " + R_CURLY@[345; 346) "}" + WHITESPACE@[346; 347) "\n" + R_CURLY@[347; 348) "}" + WHITESPACE@[348; 349) "\n" From 4195c0e5f9a3db7646d4df28aa8c77a863c35759 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sat, 21 Dec 2019 18:42:17 +0800 Subject: [PATCH 279/312] Add macro keyword to ITEM_RECOVERY_SET --- crates/ra_parser/src/grammar/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 7e345f733d..3c717e5f9e 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -33,7 +33,7 @@ pub(super) enum ItemFlavor { pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![ FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW, - CRATE_KW, USE_KW + CRATE_KW, USE_KW, MACRO_KW ]; pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) { From 67ba9072fad8698af4e96b38b8b4acfdd801f7f7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 12:15:56 +0100 Subject: [PATCH 280/312] Remove hir for imports --- crates/ra_hir/src/code_model.rs | 18 ++++++++---------- crates/ra_hir/src/has_source.rs | 16 ++-------------- crates/ra_hir/src/lib.rs | 4 ++-- crates/ra_ide/src/completion/complete_path.rs | 17 +++++++---------- .../src/completion/completion_context.rs | 4 ++++ 5 files changed, 23 insertions(+), 36 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index fca3a29509..e6768ea0bc 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,8 +12,8 @@ use hir_def::{ resolver::HasResolver, type_ref::{Mutability, TypeRef}, AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, - LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, TypeParamId, UnionId, + LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, + TypeParamId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -180,13 +180,11 @@ impl Module { } /// Returns a `ModuleScope`: a set of items, visible in this module. - pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option)> { + pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef)> { db.crate_def_map(self.id.krate)[self.id.local_id] .scope .entries() - .map(|(name, res)| { - (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id })) - }) + .map(|(name, res)| (name.clone(), res.def.into())) .collect() } @@ -229,10 +227,10 @@ impl Module { } } -pub struct Import { - pub(crate) parent: Module, - pub(crate) id: LocalImportId, -} +// pub struct Import { +// pub(crate) parent: Module, +// pub(crate) id: LocalImportId, +// } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructField { diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 72afecf26c..5541266e2b 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -9,8 +9,8 @@ use hir_def::{ use ra_syntax::ast; use crate::{ - db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, - Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, + db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, MacroDef, Module, + Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub use hir_expand::InFile; @@ -117,18 +117,6 @@ impl HasSource for ImplBlock { self.id.lookup(db).source(db) } } -impl HasSource for Import { - type Ast = Either; - - /// Returns the syntax of the last path segment corresponding to this import - fn source(self, db: &impl DefDatabase) -> InFile { - let src = self.parent.definition_source(db); - let (_, source_map) = db.raw_items_with_source_map(src.file_id); - let root = db.parse_or_expand(src.file_id).unwrap(); - let ptr = source_map.get(self.id); - src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) - } -} impl HasSource for TypeParam { type Ast = Either; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 7f9aef7707..0008a8858f 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -40,8 +40,8 @@ mod from_source; pub use crate::{ code_model::{ Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, - EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, - MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, + EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Local, MacroDef, + Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, }, from_source::FromSource, diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 28f94e0a77..8ce86ad7d2 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs @@ -1,7 +1,6 @@ //! FIXME: write short doc here -use either::Either; -use hir::{Adt, HasSource, PathResolution}; +use hir::{Adt, PathResolution, ScopeDef}; use ra_syntax::AstNode; use test_utils::tested_by; @@ -19,17 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { match def { hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); - for (name, def, import) in module_scope { - if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { - if ctx.use_item_syntax.is_some() { + for (name, def) in module_scope { + if ctx.use_item_syntax.is_some() { + if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { tested_by!(dont_complete_primitive_in_use); continue; } - } - if Some(module) == ctx.module { - if let Some(import) = import { - if let Either::Left(use_tree) = import.source(ctx.db).value { - if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { + if let ScopeDef::Unknown = def { + if let Some(name_ref) = ctx.name_ref.as_ref() { + if &name_ref.syntax().text() == name.to_string().as_str() { // for `use self::foo<|>`, don't suggest `foo` as a completion tested_by!(dont_complete_current_use); continue; diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 4894ea2f6b..8f56ce7062 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -18,6 +18,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) analyzer: hir::SourceAnalyzer, pub(super) offset: TextUnit, pub(super) token: SyntaxToken, + pub(super) name_ref: Option, pub(super) module: Option, pub(super) function_syntax: Option, pub(super) use_item_syntax: Option, @@ -68,6 +69,7 @@ impl<'a> CompletionContext<'a> { analyzer, token, offset: position.offset, + name_ref: None, module, function_syntax: None, use_item_syntax: None, @@ -142,6 +144,8 @@ impl<'a> CompletionContext<'a> { } fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { + self.name_ref = + find_node_at_offset(original_file.syntax(), name_ref.syntax().text_range().start()); let name_range = name_ref.syntax().text_range(); if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); From ab7a70fb14d281507b6e6726b47614035b073a28 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 12:38:40 +0100 Subject: [PATCH 281/312] Don't track imports --- crates/ra_hir_def/src/item_scope.rs | 35 ++++++------------- crates/ra_hir_def/src/nameres/collector.rs | 39 +++++++++------------- 2 files changed, 26 insertions(+), 48 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 6b9be8325d..5c14fefff4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,7 +5,7 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { @@ -30,7 +30,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) + (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), declaration: false }) }) .collect() }); @@ -53,11 +53,9 @@ impl ItemScope { } pub fn declarations(&self) -> impl Iterator + '_ { - self.entries() - .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) - .flat_map(|per_ns| { - per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) - }) + self.entries().filter(|(_name, res)| res.declaration).flat_map(|(_name, res)| { + res.def.take_types().into_iter().chain(res.def.take_values().into_iter()) + }) } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -112,38 +110,26 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res( - &mut self, - name: Name, - res: &Resolution, - import: Option, - ) -> bool { + pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, declaration: bool) -> bool { let mut changed = false; let existing = self.items.entry(name.clone()).or_default(); if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; - existing.import = import.or(res.import); + existing.declaration |= declaration; changed = true; } if existing.def.values.is_none() && res.def.values.is_some() { existing.def.values = res.def.values; - existing.import = import.or(res.import); + existing.declaration |= declaration; changed = true; } if existing.def.macros.is_none() && res.def.macros.is_some() { existing.def.macros = res.def.macros; - existing.import = import.or(res.import); + existing.declaration |= declaration; changed = true; } - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { - existing.import = res.import; - } changed } @@ -160,6 +146,5 @@ impl ItemScope { pub struct Resolution { /// None for unresolved pub def: PerNs, - /// ident by which this is imported into local scope. - pub import: Option, + pub declaration: bool, } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 45199fa114..e43aafedb9 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -218,8 +218,7 @@ where if export { self.update( self.def_map.root, - None, - &[(name, Resolution { def: PerNs::macros(macro_), import: None })], + &[(name, Resolution { def: PerNs::macros(macro_), declaration: false })], ); } } @@ -374,7 +373,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, Some(import_id), &items); + self.update(module_id, &items); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further @@ -384,7 +383,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, Some(import_id), &items); + self.update(module_id, &items); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); if !glob.iter().any(|it| *it == (module_id, import_id)) { @@ -404,12 +403,12 @@ where let variant = EnumVariantId { parent: e, local_id }; let res = Resolution { def: PerNs::both(variant.into(), variant.into()), - import: Some(import_id), + declaration: false, }; (name, res) }) .collect::>(); - self.update(module_id, Some(import_id), &resolutions); + self.update(module_id, &resolutions); } Some(d) => { log::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -431,27 +430,21 @@ where } } - let resolution = Resolution { def, import: Some(import_id) }; - self.update(module_id, Some(import_id), &[(name, resolution)]); + let resolution = Resolution { def, declaration: false }; + self.update(module_id, &[(name, resolution)]); } None => tested_by!(bogus_paths), } } } - fn update( - &mut self, - module_id: LocalModuleId, - import: Option, - resolutions: &[(Name, Resolution)], - ) { - self.update_recursive(module_id, import, resolutions, 0) + fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, Resolution)]) { + self.update_recursive(module_id, resolutions, 0) } fn update_recursive( &mut self, module_id: LocalModuleId, - import: Option, resolutions: &[(Name, Resolution)], depth: usize, ) { @@ -462,7 +455,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res, import); + changed |= scope.push_res(name.clone(), res, depth == 0 && res.declaration); } if !changed { @@ -475,9 +468,9 @@ where .flat_map(|v| v.iter()) .cloned() .collect::>(); - for (glob_importing_module, glob_import) in glob_imports { + for (glob_importing_module, _glob_import) in glob_imports { // We pass the glob import so that the tracked import in those modules is that glob import - self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1); + self.update_recursive(glob_importing_module, resolutions, depth + 1); } } @@ -719,9 +712,9 @@ where def: PerNs::types( ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(), ), - import: None, + declaration: true, }; - self.def_collector.update(self.module_id, None, &[(name, resolution)]); + self.def_collector.update(self.module_id, &[(name, resolution)]); res } @@ -791,8 +784,8 @@ where PerNs::types(def.into()) } }; - let resolution = Resolution { def, import: None }; - self.def_collector.update(self.module_id, None, &[(name, resolution)]) + let resolution = Resolution { def, declaration: true }; + self.def_collector.update(self.module_id, &[(name, resolution)]) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { From d3353118939d5ab77a63218db6ef542843256aac Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 12:44:28 +0100 Subject: [PATCH 282/312] Remove import source map --- crates/ra_hir/src/db.rs | 4 +- crates/ra_hir_def/src/db.rs | 11 +---- crates/ra_hir_def/src/nameres/raw.rs | 62 ++++++---------------------- crates/ra_hir_def/src/trace.rs | 8 ---- crates/ra_ide/src/change.rs | 2 - 5 files changed, 15 insertions(+), 72 deletions(-) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index bfae3660b4..f5ffd64fa7 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -4,8 +4,8 @@ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, - LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, - StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery, + LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, + TraitDataQuery, TypeAliasDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 98bff6cb78..c55fd41110 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -13,10 +13,7 @@ use crate::{ docs::Documentation, generics::GenericParams, lang_item::{LangItemTarget, LangItems}, - nameres::{ - raw::{ImportSourceMap, RawItems}, - CrateDefMap, - }, + nameres::{raw::RawItems, CrateDefMap}, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, @@ -46,12 +43,6 @@ pub trait InternDatabase: SourceDatabase { #[salsa::query_group(DefDatabaseStorage)] pub trait DefDatabase: InternDatabase + AstDatabase { - #[salsa::invoke(RawItems::raw_items_with_source_map_query)] - fn raw_items_with_source_map( - &self, - file_id: HirFileId, - ) -> (Arc, Arc); - #[salsa::invoke(RawItems::raw_items_query)] fn raw_items(&self, file_id: HirFileId) -> Arc; diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index ecb4d7c03d..73e57f1e55 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -7,23 +7,21 @@ use std::{ops::Index, sync::Arc}; -use either::Either; use hir_expand::{ ast_id_map::AstIdMap, db::AstDatabase, hygiene::Hygiene, name::{AsName, Name}, }; -use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; +use ra_arena::{impl_arena_id, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, - AstNode, AstPtr, + AstNode, }; use test_utils::tested_by; use crate::{ - attr::Attrs, db::DefDatabase, path::ModPath, trace::Trace, FileAstId, HirFileId, InFile, - LocalImportId, + attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile, LocalImportId, }; /// `RawItems` is a set of top-level items in a file (except for impls). @@ -41,35 +39,14 @@ pub struct RawItems { items: Vec, } -#[derive(Debug, Default, PartialEq, Eq)] -pub struct ImportSourceMap { - map: ArenaMap, -} - -type ImportSourcePtr = Either, AstPtr>; - -impl ImportSourceMap { - pub fn get(&self, import: LocalImportId) -> ImportSourcePtr { - self.map[import].clone() - } -} - impl RawItems { pub(crate) fn raw_items_query( db: &(impl DefDatabase + AstDatabase), file_id: HirFileId, ) -> Arc { - db.raw_items_with_source_map(file_id).0 - } - - pub(crate) fn raw_items_with_source_map_query( - db: &(impl DefDatabase + AstDatabase), - file_id: HirFileId, - ) -> (Arc, Arc) { let mut collector = RawItemsCollector { raw_items: RawItems::default(), source_ast_id_map: db.ast_id_map(file_id), - imports: Trace::new(), file_id, hygiene: Hygiene::new(db, file_id), }; @@ -80,11 +57,8 @@ impl RawItems { collector.process_module(None, item_list); } } - let mut raw_items = collector.raw_items; - let (arena, map) = collector.imports.into_arena_and_map(); - raw_items.imports = arena; - let source_map = ImportSourceMap { map }; - (Arc::new(raw_items), Arc::new(source_map)) + let raw_items = collector.raw_items; + Arc::new(raw_items) } pub(super) fn items(&self) -> &[RawItem] { @@ -223,7 +197,6 @@ pub(super) struct ImplData { struct RawItemsCollector { raw_items: RawItems, - imports: Trace, source_ast_id_map: Arc, file_id: HirFileId, hygiene: Hygiene, @@ -330,7 +303,7 @@ impl RawItemsCollector { ModPath::expand_use_item( InFile { value: use_item, file_id: self.file_id }, &self.hygiene, - |path, use_tree, is_glob, alias| { + |path, _use_tree, is_glob, alias| { let import_data = ImportData { path, alias, @@ -339,11 +312,11 @@ impl RawItemsCollector { is_extern_crate: false, is_macro_use: false, }; - buf.push((import_data, Either::Left(AstPtr::new(use_tree)))); + buf.push(import_data); }, ); - for (import_data, ptr) in buf { - self.push_import(current_module, attrs.clone(), import_data, ptr); + for import_data in buf { + self.push_import(current_module, attrs.clone(), import_data); } } @@ -366,12 +339,7 @@ impl RawItemsCollector { is_extern_crate: true, is_macro_use, }; - self.push_import( - current_module, - attrs, - import_data, - Either::Right(AstPtr::new(&extern_crate)), - ); + self.push_import(current_module, attrs, import_data); } } @@ -402,14 +370,8 @@ impl RawItemsCollector { self.push_item(current_module, attrs, RawItemKind::Impl(imp)) } - fn push_import( - &mut self, - current_module: Option, - attrs: Attrs, - data: ImportData, - source: ImportSourcePtr, - ) { - let import = self.imports.alloc(|| source, || data); + fn push_import(&mut self, current_module: Option, attrs: Attrs, data: ImportData) { + let import = self.raw_items.imports.alloc(data); self.push_item(current_module, attrs, RawItemKind::Import(import)) } diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs index 2bcd707bcd..9769e88df5 100644 --- a/crates/ra_hir_def/src/trace.rs +++ b/crates/ra_hir_def/src/trace.rs @@ -18,10 +18,6 @@ pub(crate) struct Trace { } impl Trace { - pub(crate) fn new() -> Trace { - Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 } - } - pub(crate) fn new_for_arena() -> Trace { Trace { arena: Some(Arena::default()), map: None, len: 0 } } @@ -52,8 +48,4 @@ impl Trace { pub(crate) fn into_map(mut self) -> ArenaMap { self.map.take().unwrap() } - - pub(crate) fn into_arena_and_map(mut self) -> (Arena, ArenaMap) { - (self.arena.take().unwrap(), self.map.take().unwrap()) - } } diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide/src/change.rs index 4a76d1dd83..387a9cafb6 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide/src/change.rs @@ -270,7 +270,6 @@ impl RootDatabase { self.query(hir::db::AstIdMapQuery).sweep(sweep); - self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep); @@ -309,7 +308,6 @@ impl RootDatabase { hir::db::StructDataQuery hir::db::EnumDataQuery hir::db::TraitDataQuery - hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery hir::db::GenericParamsQuery From 2d3fdf3fb52f32ececdfa19df7ab2971a24bae71 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 12:47:34 +0100 Subject: [PATCH 283/312] Privatize LocalImportID --- crates/ra_hir_def/src/lib.rs | 4 ---- crates/ra_hir_def/src/nameres/collector.rs | 7 +++---- crates/ra_hir_def/src/nameres/raw.rs | 8 +++++--- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index acd4f4af17..f6c7f38d17 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -51,10 +51,6 @@ use ra_syntax::{ast, AstNode}; use crate::body::Expander; use crate::builtin_type::BuiltinType; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalImportId(RawId); -impl_arena_id!(LocalImportId); - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ModuleId { pub krate: CrateId, diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index e43aafedb9..9419461a86 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -26,8 +26,7 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, - LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, - TypeAliasLoc, UnionLoc, + LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -93,7 +92,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] struct ImportDirective { module_id: LocalModuleId, - import_id: LocalImportId, + import_id: raw::LocalImportId, import: raw::ImportData, status: PartialResolvedImport, } @@ -110,7 +109,7 @@ struct MacroDirective { struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, unexpanded_macros: Vec, diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 73e57f1e55..b10e458a20 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -20,9 +20,11 @@ use ra_syntax::{ }; use test_utils::tested_by; -use crate::{ - attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile, LocalImportId, -}; +use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(super) struct LocalImportId(RawId); +impl_arena_id!(LocalImportId); /// `RawItems` is a set of top-level items in a file (except for impls). /// From 2058f704cb5045d0b19c299b1ebe0f261d153765 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 13:33:44 +0100 Subject: [PATCH 284/312] Add dummy implementations of env! and option_env! builtins They don't do anything except return the correct type. Also refactor the builtin macro tests a bit. --- crates/ra_hir_expand/src/builtin_macro.rs | 138 +++++++++++++++------- crates/ra_hir_expand/src/name.rs | 2 + crates/ra_hir_expand/src/quote.rs | 2 + 3 files changed, 99 insertions(+), 43 deletions(-) diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 857f8a4441..2c119269c1 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -26,6 +26,13 @@ macro_rules! register_builtin { }; expander(db, id, tt) } + + fn by_name(ident: &name::Name) -> Option { + match ident { + $( id if id == &name::name![$name] => Some(BuiltinFnLikeExpander::$kind), )* + _ => return None, + } + } } pub fn find_builtin_macro( @@ -33,10 +40,7 @@ macro_rules! register_builtin { krate: CrateId, ast_id: AstId, ) -> Option { - let kind = match ident { - $( id if id == &name::name![$name] => BuiltinFnLikeExpander::$kind, )* - _ => return None, - }; + let kind = BuiltinFnLikeExpander::by_name(ident)?; Some(MacroDefId { krate: Some(krate), ast_id: Some(ast_id), kind: MacroDefKind::BuiltIn(kind) }) } @@ -50,6 +54,8 @@ register_builtin! { (line, Line) => line_expand, (stringify, Stringify) => stringify_expand, (format_args, FormatArgs) => format_args_expand, + (env, Env) => env_expand, + (option_env, OptionEnv) => option_env_expand, // format_args_nl only differs in that it adds a newline in the end, // so we use the same stub expansion for now (format_args_nl, FormatArgsNl) => format_args_expand @@ -121,6 +127,28 @@ fn stringify_expand( Ok(expanded) } +fn env_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + // dummy implementation for type-checking purposes + let expanded = quote! { "" }; + + Ok(expanded) +} + +fn option_env_expand( + _db: &dyn AstDatabase, + _id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + // dummy implementation for type-checking purposes + let expanded = quote! { std::option::Option::None::<&str> }; + + Ok(expanded) +} + fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { // FIXME: Use expansion info let file_id = file.original_file(db); @@ -248,10 +276,11 @@ fn format_args_expand( #[cfg(test)] mod tests { use super::*; - use crate::{test_db::TestDB, MacroCallKind, MacroCallLoc}; + use crate::{name::AsName, test_db::TestDB, MacroCallKind, MacroCallLoc}; use ra_db::{fixture::WithFixture, SourceDatabase}; + use ra_syntax::ast::NameOwner; - fn expand_builtin_macro(s: &str, expander: BuiltinFnLikeExpander) -> String { + fn expand_builtin_macro(s: &str) -> String { let (db, file_id) = TestDB::with_single_file(&s); let parsed = db.parse(file_id); let macro_calls: Vec<_> = @@ -259,6 +288,9 @@ mod tests { let ast_id_map = db.ast_id_map(file_id.into()); + let expander = + BuiltinFnLikeExpander::by_name(¯o_calls[0].name().unwrap().as_name()).unwrap(); + // the first one should be a macro_rules let def = MacroDefId { krate: Some(CrateId(0)), @@ -284,25 +316,23 @@ mod tests { fn test_column_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! column {() => {}} - column!() -"#, - BuiltinFnLikeExpander::Column, + #[rustc_builtin_macro] + macro_rules! column {() => {}} + column!() + "#, ); - assert_eq!(expanded, "9"); + assert_eq!(expanded, "13"); } #[test] fn test_line_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! line {() => {}} - line!() -"#, - BuiltinFnLikeExpander::Line, + #[rustc_builtin_macro] + macro_rules! line {() => {}} + line!() + "#, ); assert_eq!(expanded, "4"); @@ -312,25 +342,49 @@ mod tests { fn test_stringify_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! stringify {() => {}} - stringify!(a b c) -"#, - BuiltinFnLikeExpander::Stringify, + #[rustc_builtin_macro] + macro_rules! stringify {() => {}} + stringify!(a b c) + "#, ); assert_eq!(expanded, "\"a b c\""); } + #[test] + fn test_env_expand() { + let expanded = expand_builtin_macro( + r#" + #[rustc_builtin_macro] + macro_rules! env {() => {}} + env!("TEST_ENV_VAR") + "#, + ); + + assert_eq!(expanded, "\"\""); + } + + #[test] + fn test_option_env_expand() { + let expanded = expand_builtin_macro( + r#" + #[rustc_builtin_macro] + macro_rules! option_env {() => {}} + option_env!("TEST_ENV_VAR") + "#, + ); + + assert_eq!(expanded, "std::option::Option::None:: <&str>"); + } + #[test] fn test_file_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! file {() => {}} - file!() -"#, - BuiltinFnLikeExpander::File, + #[rustc_builtin_macro] + macro_rules! file {() => {}} + file!() + "#, ); assert_eq!(expanded, "\"\""); @@ -340,14 +394,13 @@ mod tests { fn test_compile_error_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! compile_error { - ($msg:expr) => ({ /* compiler built-in */ }); - ($msg:expr,) => ({ /* compiler built-in */ }) - } - compile_error!("error!"); -"#, - BuiltinFnLikeExpander::CompileError, + #[rustc_builtin_macro] + macro_rules! compile_error { + ($msg:expr) => ({ /* compiler built-in */ }); + ($msg:expr,) => ({ /* compiler built-in */ }) + } + compile_error!("error!"); + "#, ); assert_eq!(expanded, r#"loop{"error!"}"#); @@ -357,14 +410,13 @@ mod tests { fn test_format_args_expand() { let expanded = expand_builtin_macro( r#" - #[rustc_builtin_macro] - macro_rules! format_args { - ($fmt:expr) => ({ /* compiler built-in */ }); - ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) - } - format_args!("{} {:?}", arg1(a, b, c), arg2); -"#, - BuiltinFnLikeExpander::FormatArgs, + #[rustc_builtin_macro] + macro_rules! format_args { + ($fmt:expr) => ({ /* compiler built-in */ }); + ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) + } + format_args!("{} {:?}", arg1(a, b, c), arg2); + "#, ); assert_eq!( diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index fd02ffa4e1..e62693b685 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -170,6 +170,8 @@ pub mod known { stringify, format_args, format_args_nl, + env, + option_env, // Builtin derives Copy, Clone, diff --git a/crates/ra_hir_expand/src/quote.rs b/crates/ra_hir_expand/src/quote.rs index 49155fe626..4de219ce46 100644 --- a/crates/ra_hir_expand/src/quote.rs +++ b/crates/ra_hir_expand/src/quote.rs @@ -102,6 +102,8 @@ macro_rules! __quote { ( : ) => {$crate::__quote!(@PUNCT ':')}; ( :: ) => {$crate::__quote!(@PUNCT ':', ':')}; ( . ) => {$crate::__quote!(@PUNCT '.')}; + ( < ) => {$crate::__quote!(@PUNCT '<')}; + ( > ) => {$crate::__quote!(@PUNCT '>')}; ( $first:tt $($tail:tt)+ ) => { { From 973b5cf7e20842711d59a810b268796b26241382 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 15:04:33 +0100 Subject: [PATCH 285/312] Revert "Merge #2629" This reverts commit cdc9d682b066b110e0a44e5f8f1c574b38c16ba9, reversing changes made to 90ef070db3dce0a7acb9cd11d0b0d72de13c9d79. --- crates/ra_hir/src/code_model.rs | 18 ++--- crates/ra_hir/src/db.rs | 4 +- crates/ra_hir/src/has_source.rs | 16 ++++- crates/ra_hir/src/lib.rs | 4 +- crates/ra_hir_def/src/db.rs | 11 ++- crates/ra_hir_def/src/item_scope.rs | 35 +++++++--- crates/ra_hir_def/src/lib.rs | 4 ++ crates/ra_hir_def/src/nameres/collector.rs | 46 +++++++------ crates/ra_hir_def/src/nameres/raw.rs | 68 ++++++++++++++----- crates/ra_hir_def/src/trace.rs | 8 +++ crates/ra_ide/src/change.rs | 2 + crates/ra_ide/src/completion/complete_path.rs | 17 +++-- .../src/completion/completion_context.rs | 4 -- 13 files changed, 166 insertions(+), 71 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e6768ea0bc..fca3a29509 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,8 +12,8 @@ use hir_def::{ resolver::HasResolver, type_ref::{Mutability, TypeRef}, AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, - LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, - TypeParamId, UnionId, + LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, + TraitId, TypeAliasId, TypeParamId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -180,11 +180,13 @@ impl Module { } /// Returns a `ModuleScope`: a set of items, visible in this module. - pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef)> { + pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option)> { db.crate_def_map(self.id.krate)[self.id.local_id] .scope .entries() - .map(|(name, res)| (name.clone(), res.def.into())) + .map(|(name, res)| { + (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id })) + }) .collect() } @@ -227,10 +229,10 @@ impl Module { } } -// pub struct Import { -// pub(crate) parent: Module, -// pub(crate) id: LocalImportId, -// } +pub struct Import { + pub(crate) parent: Module, + pub(crate) id: LocalImportId, +} #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructField { diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index f5ffd64fa7..bfae3660b4 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -4,8 +4,8 @@ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, - LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, - TraitDataQuery, TypeAliasDataQuery, + LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, + StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 5541266e2b..72afecf26c 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -9,8 +9,8 @@ use hir_def::{ use ra_syntax::ast; use crate::{ - db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, MacroDef, Module, - Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, + db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, + Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub use hir_expand::InFile; @@ -117,6 +117,18 @@ impl HasSource for ImplBlock { self.id.lookup(db).source(db) } } +impl HasSource for Import { + type Ast = Either; + + /// Returns the syntax of the last path segment corresponding to this import + fn source(self, db: &impl DefDatabase) -> InFile { + let src = self.parent.definition_source(db); + let (_, source_map) = db.raw_items_with_source_map(src.file_id); + let root = db.parse_or_expand(src.file_id).unwrap(); + let ptr = source_map.get(self.id); + src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) + } +} impl HasSource for TypeParam { type Ast = Either; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0008a8858f..7f9aef7707 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -40,8 +40,8 @@ mod from_source; pub use crate::{ code_model::{ Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, - EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Local, MacroDef, - Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, + EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, + MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, }, from_source::FromSource, diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index c55fd41110..98bff6cb78 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -13,7 +13,10 @@ use crate::{ docs::Documentation, generics::GenericParams, lang_item::{LangItemTarget, LangItems}, - nameres::{raw::RawItems, CrateDefMap}, + nameres::{ + raw::{ImportSourceMap, RawItems}, + CrateDefMap, + }, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, @@ -43,6 +46,12 @@ pub trait InternDatabase: SourceDatabase { #[salsa::query_group(DefDatabaseStorage)] pub trait DefDatabase: InternDatabase + AstDatabase { + #[salsa::invoke(RawItems::raw_items_with_source_map_query)] + fn raw_items_with_source_map( + &self, + file_id: HirFileId, + ) -> (Arc, Arc); + #[salsa::invoke(RawItems::raw_items_query)] fn raw_items(&self, file_id: HirFileId) -> Arc; diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 5c14fefff4..6b9be8325d 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,7 +5,7 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { @@ -30,7 +30,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), declaration: false }) + (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) }) .collect() }); @@ -53,9 +53,11 @@ impl ItemScope { } pub fn declarations(&self) -> impl Iterator + '_ { - self.entries().filter(|(_name, res)| res.declaration).flat_map(|(_name, res)| { - res.def.take_types().into_iter().chain(res.def.take_values().into_iter()) - }) + self.entries() + .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) + .flat_map(|per_ns| { + per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) + }) } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -110,26 +112,38 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, declaration: bool) -> bool { + pub(crate) fn push_res( + &mut self, + name: Name, + res: &Resolution, + import: Option, + ) -> bool { let mut changed = false; let existing = self.items.entry(name.clone()).or_default(); if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; - existing.declaration |= declaration; + existing.import = import.or(res.import); changed = true; } if existing.def.values.is_none() && res.def.values.is_some() { existing.def.values = res.def.values; - existing.declaration |= declaration; + existing.import = import.or(res.import); changed = true; } if existing.def.macros.is_none() && res.def.macros.is_some() { existing.def.macros = res.def.macros; - existing.declaration |= declaration; + existing.import = import.or(res.import); changed = true; } + if existing.def.is_none() + && res.def.is_none() + && existing.import.is_none() + && res.import.is_some() + { + existing.import = res.import; + } changed } @@ -146,5 +160,6 @@ impl ItemScope { pub struct Resolution { /// None for unresolved pub def: PerNs, - pub declaration: bool, + /// ident by which this is imported into local scope. + pub import: Option, } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index f6c7f38d17..acd4f4af17 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -51,6 +51,10 @@ use ra_syntax::{ast, AstNode}; use crate::body::Expander; use crate::builtin_type::BuiltinType; +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct LocalImportId(RawId); +impl_arena_id!(LocalImportId); + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ModuleId { pub krate: CrateId, diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 9419461a86..45199fa114 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -26,7 +26,8 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, - LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, + LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, + TypeAliasLoc, UnionLoc, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -92,7 +93,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] struct ImportDirective { module_id: LocalModuleId, - import_id: raw::LocalImportId, + import_id: LocalImportId, import: raw::ImportData, status: PartialResolvedImport, } @@ -109,7 +110,7 @@ struct MacroDirective { struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, unexpanded_macros: Vec, @@ -217,7 +218,8 @@ where if export { self.update( self.def_map.root, - &[(name, Resolution { def: PerNs::macros(macro_), declaration: false })], + None, + &[(name, Resolution { def: PerNs::macros(macro_), import: None })], ); } } @@ -372,7 +374,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, &items); + self.update(module_id, Some(import_id), &items); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further @@ -382,7 +384,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, &items); + self.update(module_id, Some(import_id), &items); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); if !glob.iter().any(|it| *it == (module_id, import_id)) { @@ -402,12 +404,12 @@ where let variant = EnumVariantId { parent: e, local_id }; let res = Resolution { def: PerNs::both(variant.into(), variant.into()), - declaration: false, + import: Some(import_id), }; (name, res) }) .collect::>(); - self.update(module_id, &resolutions); + self.update(module_id, Some(import_id), &resolutions); } Some(d) => { log::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -429,21 +431,27 @@ where } } - let resolution = Resolution { def, declaration: false }; - self.update(module_id, &[(name, resolution)]); + let resolution = Resolution { def, import: Some(import_id) }; + self.update(module_id, Some(import_id), &[(name, resolution)]); } None => tested_by!(bogus_paths), } } } - fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, Resolution)]) { - self.update_recursive(module_id, resolutions, 0) + fn update( + &mut self, + module_id: LocalModuleId, + import: Option, + resolutions: &[(Name, Resolution)], + ) { + self.update_recursive(module_id, import, resolutions, 0) } fn update_recursive( &mut self, module_id: LocalModuleId, + import: Option, resolutions: &[(Name, Resolution)], depth: usize, ) { @@ -454,7 +462,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res, depth == 0 && res.declaration); + changed |= scope.push_res(name.clone(), res, import); } if !changed { @@ -467,9 +475,9 @@ where .flat_map(|v| v.iter()) .cloned() .collect::>(); - for (glob_importing_module, _glob_import) in glob_imports { + for (glob_importing_module, glob_import) in glob_imports { // We pass the glob import so that the tracked import in those modules is that glob import - self.update_recursive(glob_importing_module, resolutions, depth + 1); + self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1); } } @@ -711,9 +719,9 @@ where def: PerNs::types( ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(), ), - declaration: true, + import: None, }; - self.def_collector.update(self.module_id, &[(name, resolution)]); + self.def_collector.update(self.module_id, None, &[(name, resolution)]); res } @@ -783,8 +791,8 @@ where PerNs::types(def.into()) } }; - let resolution = Resolution { def, declaration: true }; - self.def_collector.update(self.module_id, &[(name, resolution)]) + let resolution = Resolution { def, import: None }; + self.def_collector.update(self.module_id, None, &[(name, resolution)]) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index b10e458a20..ecb4d7c03d 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -7,24 +7,24 @@ use std::{ops::Index, sync::Arc}; +use either::Either; use hir_expand::{ ast_id_map::AstIdMap, db::AstDatabase, hygiene::Hygiene, name::{AsName, Name}, }; -use ra_arena::{impl_arena_id, Arena, RawId}; +use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, - AstNode, + AstNode, AstPtr, }; use test_utils::tested_by; -use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub(super) struct LocalImportId(RawId); -impl_arena_id!(LocalImportId); +use crate::{ + attr::Attrs, db::DefDatabase, path::ModPath, trace::Trace, FileAstId, HirFileId, InFile, + LocalImportId, +}; /// `RawItems` is a set of top-level items in a file (except for impls). /// @@ -41,14 +41,35 @@ pub struct RawItems { items: Vec, } +#[derive(Debug, Default, PartialEq, Eq)] +pub struct ImportSourceMap { + map: ArenaMap, +} + +type ImportSourcePtr = Either, AstPtr>; + +impl ImportSourceMap { + pub fn get(&self, import: LocalImportId) -> ImportSourcePtr { + self.map[import].clone() + } +} + impl RawItems { pub(crate) fn raw_items_query( db: &(impl DefDatabase + AstDatabase), file_id: HirFileId, ) -> Arc { + db.raw_items_with_source_map(file_id).0 + } + + pub(crate) fn raw_items_with_source_map_query( + db: &(impl DefDatabase + AstDatabase), + file_id: HirFileId, + ) -> (Arc, Arc) { let mut collector = RawItemsCollector { raw_items: RawItems::default(), source_ast_id_map: db.ast_id_map(file_id), + imports: Trace::new(), file_id, hygiene: Hygiene::new(db, file_id), }; @@ -59,8 +80,11 @@ impl RawItems { collector.process_module(None, item_list); } } - let raw_items = collector.raw_items; - Arc::new(raw_items) + let mut raw_items = collector.raw_items; + let (arena, map) = collector.imports.into_arena_and_map(); + raw_items.imports = arena; + let source_map = ImportSourceMap { map }; + (Arc::new(raw_items), Arc::new(source_map)) } pub(super) fn items(&self) -> &[RawItem] { @@ -199,6 +223,7 @@ pub(super) struct ImplData { struct RawItemsCollector { raw_items: RawItems, + imports: Trace, source_ast_id_map: Arc, file_id: HirFileId, hygiene: Hygiene, @@ -305,7 +330,7 @@ impl RawItemsCollector { ModPath::expand_use_item( InFile { value: use_item, file_id: self.file_id }, &self.hygiene, - |path, _use_tree, is_glob, alias| { + |path, use_tree, is_glob, alias| { let import_data = ImportData { path, alias, @@ -314,11 +339,11 @@ impl RawItemsCollector { is_extern_crate: false, is_macro_use: false, }; - buf.push(import_data); + buf.push((import_data, Either::Left(AstPtr::new(use_tree)))); }, ); - for import_data in buf { - self.push_import(current_module, attrs.clone(), import_data); + for (import_data, ptr) in buf { + self.push_import(current_module, attrs.clone(), import_data, ptr); } } @@ -341,7 +366,12 @@ impl RawItemsCollector { is_extern_crate: true, is_macro_use, }; - self.push_import(current_module, attrs, import_data); + self.push_import( + current_module, + attrs, + import_data, + Either::Right(AstPtr::new(&extern_crate)), + ); } } @@ -372,8 +402,14 @@ impl RawItemsCollector { self.push_item(current_module, attrs, RawItemKind::Impl(imp)) } - fn push_import(&mut self, current_module: Option, attrs: Attrs, data: ImportData) { - let import = self.raw_items.imports.alloc(data); + fn push_import( + &mut self, + current_module: Option, + attrs: Attrs, + data: ImportData, + source: ImportSourcePtr, + ) { + let import = self.imports.alloc(|| source, || data); self.push_item(current_module, attrs, RawItemKind::Import(import)) } diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs index 9769e88df5..2bcd707bcd 100644 --- a/crates/ra_hir_def/src/trace.rs +++ b/crates/ra_hir_def/src/trace.rs @@ -18,6 +18,10 @@ pub(crate) struct Trace { } impl Trace { + pub(crate) fn new() -> Trace { + Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 } + } + pub(crate) fn new_for_arena() -> Trace { Trace { arena: Some(Arena::default()), map: None, len: 0 } } @@ -48,4 +52,8 @@ impl Trace { pub(crate) fn into_map(mut self) -> ArenaMap { self.map.take().unwrap() } + + pub(crate) fn into_arena_and_map(mut self) -> (Arena, ArenaMap) { + (self.arena.take().unwrap(), self.map.take().unwrap()) + } } diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide/src/change.rs index 387a9cafb6..4a76d1dd83 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide/src/change.rs @@ -270,6 +270,7 @@ impl RootDatabase { self.query(hir::db::AstIdMapQuery).sweep(sweep); + self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep); @@ -308,6 +309,7 @@ impl RootDatabase { hir::db::StructDataQuery hir::db::EnumDataQuery hir::db::TraitDataQuery + hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery hir::db::GenericParamsQuery diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 8ce86ad7d2..28f94e0a77 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs @@ -1,6 +1,7 @@ //! FIXME: write short doc here -use hir::{Adt, PathResolution, ScopeDef}; +use either::Either; +use hir::{Adt, HasSource, PathResolution}; use ra_syntax::AstNode; use test_utils::tested_by; @@ -18,15 +19,17 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { match def { hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); - for (name, def) in module_scope { - if ctx.use_item_syntax.is_some() { - if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { + for (name, def, import) in module_scope { + if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { + if ctx.use_item_syntax.is_some() { tested_by!(dont_complete_primitive_in_use); continue; } - if let ScopeDef::Unknown = def { - if let Some(name_ref) = ctx.name_ref.as_ref() { - if &name_ref.syntax().text() == name.to_string().as_str() { + } + if Some(module) == ctx.module { + if let Some(import) = import { + if let Either::Left(use_tree) = import.source(ctx.db).value { + if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { // for `use self::foo<|>`, don't suggest `foo` as a completion tested_by!(dont_complete_current_use); continue; diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 8f56ce7062..4894ea2f6b 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -18,7 +18,6 @@ pub(crate) struct CompletionContext<'a> { pub(super) analyzer: hir::SourceAnalyzer, pub(super) offset: TextUnit, pub(super) token: SyntaxToken, - pub(super) name_ref: Option, pub(super) module: Option, pub(super) function_syntax: Option, pub(super) use_item_syntax: Option, @@ -69,7 +68,6 @@ impl<'a> CompletionContext<'a> { analyzer, token, offset: position.offset, - name_ref: None, module, function_syntax: None, use_item_syntax: None, @@ -144,8 +142,6 @@ impl<'a> CompletionContext<'a> { } fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { - self.name_ref = - find_node_at_offset(original_file.syntax(), name_ref.syntax().text_range().start()); let name_range = name_ref.syntax().text_range(); if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); From 4e0168ec14b74003e8388b72b64c2ca78b580274 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 15:17:10 +0100 Subject: [PATCH 286/312] Remove imports from hir --- crates/ra_hir/src/code_model.rs | 15 ++++----------- crates/ra_hir/src/has_source.rs | 16 ++-------------- crates/ra_hir/src/lib.rs | 4 ++-- crates/ra_hir_def/src/item_scope.rs | 2 +- crates/ra_hir_def/src/lib.rs | 2 +- crates/ra_hir_def/src/nameres/raw.rs | 6 ------ crates/ra_ide/src/completion/complete_path.rs | 18 ++++++++---------- .../src/completion/completion_context.rs | 4 ++++ 8 files changed, 22 insertions(+), 45 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index fca3a29509..4cd28eb4e3 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -12,8 +12,8 @@ use hir_def::{ resolver::HasResolver, type_ref::{Mutability, TypeRef}, AdtId, ConstId, DefWithBodyId, EnumId, FunctionId, HasModule, ImplId, LocalEnumVariantId, - LocalImportId, LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, - TraitId, TypeAliasId, TypeParamId, UnionId, + LocalModuleId, LocalStructFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, + TypeParamId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -180,13 +180,11 @@ impl Module { } /// Returns a `ModuleScope`: a set of items, visible in this module. - pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef, Option)> { + pub fn scope(self, db: &impl HirDatabase) -> Vec<(Name, ScopeDef)> { db.crate_def_map(self.id.krate)[self.id.local_id] .scope .entries() - .map(|(name, res)| { - (name.clone(), res.def.into(), res.import.map(|id| Import { parent: self, id })) - }) + .map(|(name, res)| (name.clone(), res.def.into())) .collect() } @@ -229,11 +227,6 @@ impl Module { } } -pub struct Import { - pub(crate) parent: Module, - pub(crate) id: LocalImportId, -} - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructField { pub(crate) parent: VariantDef, diff --git a/crates/ra_hir/src/has_source.rs b/crates/ra_hir/src/has_source.rs index 72afecf26c..5541266e2b 100644 --- a/crates/ra_hir/src/has_source.rs +++ b/crates/ra_hir/src/has_source.rs @@ -9,8 +9,8 @@ use hir_def::{ use ra_syntax::ast; use crate::{ - db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, Import, MacroDef, - Module, Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, + db::DefDatabase, Const, Enum, EnumVariant, FieldSource, Function, ImplBlock, MacroDef, Module, + Static, Struct, StructField, Trait, TypeAlias, TypeParam, Union, }; pub use hir_expand::InFile; @@ -117,18 +117,6 @@ impl HasSource for ImplBlock { self.id.lookup(db).source(db) } } -impl HasSource for Import { - type Ast = Either; - - /// Returns the syntax of the last path segment corresponding to this import - fn source(self, db: &impl DefDatabase) -> InFile { - let src = self.parent.definition_source(db); - let (_, source_map) = db.raw_items_with_source_map(src.file_id); - let root = db.parse_or_expand(src.file_id).unwrap(); - let ptr = source_map.get(self.id); - src.with_value(ptr.map_left(|it| it.to_node(&root)).map_right(|it| it.to_node(&root))) - } -} impl HasSource for TypeParam { type Ast = Either; diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 7f9aef7707..0008a8858f 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -40,8 +40,8 @@ mod from_source; pub use crate::{ code_model::{ Adt, AssocItem, AttrDef, Const, Crate, CrateDependency, DefWithBody, Docs, Enum, - EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Import, Local, - MacroDef, Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, + EnumVariant, FieldSource, Function, GenericDef, HasAttrs, ImplBlock, Local, MacroDef, + Module, ModuleDef, ScopeDef, Static, Struct, StructField, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, }, from_source::FromSource, diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 6b9be8325d..ad104bb3d7 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -161,5 +161,5 @@ pub struct Resolution { /// None for unresolved pub def: PerNs, /// ident by which this is imported into local scope. - pub import: Option, + pub(crate) import: Option, } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index acd4f4af17..8cb5ab8d03 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -52,7 +52,7 @@ use crate::body::Expander; use crate::builtin_type::BuiltinType; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalImportId(RawId); +pub(crate) struct LocalImportId(RawId); impl_arena_id!(LocalImportId); #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index ecb4d7c03d..df5dac88a5 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -48,12 +48,6 @@ pub struct ImportSourceMap { type ImportSourcePtr = Either, AstPtr>; -impl ImportSourceMap { - pub fn get(&self, import: LocalImportId) -> ImportSourcePtr { - self.map[import].clone() - } -} - impl RawItems { pub(crate) fn raw_items_query( db: &(impl DefDatabase + AstDatabase), diff --git a/crates/ra_ide/src/completion/complete_path.rs b/crates/ra_ide/src/completion/complete_path.rs index 28f94e0a77..cc1f7c8305 100644 --- a/crates/ra_ide/src/completion/complete_path.rs +++ b/crates/ra_ide/src/completion/complete_path.rs @@ -1,7 +1,6 @@ //! FIXME: write short doc here -use either::Either; -use hir::{Adt, HasSource, PathResolution}; +use hir::{Adt, PathResolution, ScopeDef}; use ra_syntax::AstNode; use test_utils::tested_by; @@ -19,17 +18,15 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { match def { hir::ModuleDef::Module(module) => { let module_scope = module.scope(ctx.db); - for (name, def, import) in module_scope { - if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { - if ctx.use_item_syntax.is_some() { + for (name, def) in module_scope { + if ctx.use_item_syntax.is_some() { + if let hir::ScopeDef::ModuleDef(hir::ModuleDef::BuiltinType(..)) = def { tested_by!(dont_complete_primitive_in_use); continue; } - } - if Some(module) == ctx.module { - if let Some(import) = import { - if let Either::Left(use_tree) = import.source(ctx.db).value { - if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { + if let ScopeDef::Unknown = def { + if let Some(name_ref) = ctx.name_ref_syntax.as_ref() { + if &name_ref.syntax().text() == name.to_string().as_str() { // for `use self::foo<|>`, don't suggest `foo` as a completion tested_by!(dont_complete_current_use); continue; @@ -37,6 +34,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { } } } + acc.add_resolution(ctx, name.to_string(), &def); } } diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 4894ea2f6b..48d69f7e54 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs @@ -19,6 +19,7 @@ pub(crate) struct CompletionContext<'a> { pub(super) offset: TextUnit, pub(super) token: SyntaxToken, pub(super) module: Option, + pub(super) name_ref_syntax: Option, pub(super) function_syntax: Option, pub(super) use_item_syntax: Option, pub(super) record_lit_syntax: Option, @@ -69,6 +70,7 @@ impl<'a> CompletionContext<'a> { token, offset: position.offset, module, + name_ref_syntax: None, function_syntax: None, use_item_syntax: None, record_lit_syntax: None, @@ -142,6 +144,8 @@ impl<'a> CompletionContext<'a> { } fn classify_name_ref(&mut self, original_file: SourceFile, name_ref: ast::NameRef) { + self.name_ref_syntax = + find_node_at_offset(original_file.syntax(), name_ref.syntax().text_range().start()); let name_range = name_ref.syntax().text_range(); if name_ref.syntax().parent().and_then(ast::RecordField::cast).is_some() { self.record_lit_syntax = find_node_at_offset(original_file.syntax(), self.offset); From e9ed34696810135c4dbd7d628ecd2a9d6a0f048a Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sat, 21 Dec 2019 10:44:02 -0500 Subject: [PATCH 287/312] Update crates --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c29ce324e8..60b6da8eb9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -761,7 +761,7 @@ dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1076,7 +1076,7 @@ dependencies = [ "ra_syntax 0.1.0", "ra_tt 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "test_utils 0.1.0", ] @@ -1121,7 +1121,7 @@ dependencies = [ "once_cell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_parser 0.1.0", "ra_text_edit 0.1.0", - "rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rowan 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1387,7 +1387,7 @@ dependencies = [ [[package]] name = "rowan" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1442,7 +1442,7 @@ dependencies = [ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "salsa-macros 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1539,7 +1539,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1642,7 +1642,7 @@ name = "unicode-normalization" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1892,7 +1892,7 @@ dependencies = [ "checksum relative-path 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bedde000f40f2921ce439ea165c9c53fd629bfa115140c72e22aceacb4a21954" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum ron 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ece421e0c4129b90e4a35b6f625e472e96c552136f5093a2f4fa2bbb75a62d5" -"checksum rowan 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "769d42f547015b761f70c3086ccb3f7bff355124d52e9bf96d17de41774ede4b" +"checksum rowan 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3eb10a10a48f0f809a217bcf074b85a03dcf79831bae80e7f1a043d0897463e2" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc_lexer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" @@ -1910,7 +1910,7 @@ dependencies = [ "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" "checksum smol_str 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "34836c9a295c62c2ce3514471117c5cb269891e8421b2aafdd910050576c4d8b" "checksum superslice 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ab16ced94dbd8a46c82fd81e3ed9a8727dac2977ea869d217bcc4ea1f122e81f" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" From ec56f59ac17ad5ae797ce431883be8f31e795d1b Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 17:22:48 +0100 Subject: [PATCH 288/312] Remove import from resolution --- crates/ra_hir_def/src/item_scope.rs | 19 +++++++------------ crates/ra_hir_def/src/nameres/collector.rs | 10 +++++----- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index ad104bb3d7..8b70e13c46 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -30,7 +30,7 @@ static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: None }) + (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: false }) }) .collect() }); @@ -54,7 +54,7 @@ impl ItemScope { pub fn declarations(&self) -> impl Iterator + '_ { self.entries() - .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None }) + .filter_map(|(_name, res)| if !res.import { Some(res.def) } else { None }) .flat_map(|per_ns| { per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) }) @@ -123,25 +123,21 @@ impl ItemScope { if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; - existing.import = import.or(res.import); + existing.import = import.is_some() || res.import; changed = true; } if existing.def.values.is_none() && res.def.values.is_some() { existing.def.values = res.def.values; - existing.import = import.or(res.import); + existing.import = import.is_some() || res.import; changed = true; } if existing.def.macros.is_none() && res.def.macros.is_some() { existing.def.macros = res.def.macros; - existing.import = import.or(res.import); + existing.import = import.is_some() || res.import; changed = true; } - if existing.def.is_none() - && res.def.is_none() - && existing.import.is_none() - && res.import.is_some() - { + if existing.def.is_none() && res.def.is_none() && !existing.import && res.import { existing.import = res.import; } changed @@ -160,6 +156,5 @@ impl ItemScope { pub struct Resolution { /// None for unresolved pub def: PerNs, - /// ident by which this is imported into local scope. - pub(crate) import: Option, + pub(crate) import: bool, } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 45199fa114..c2db5472b4 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -219,7 +219,7 @@ where self.update( self.def_map.root, None, - &[(name, Resolution { def: PerNs::macros(macro_), import: None })], + &[(name, Resolution { def: PerNs::macros(macro_), import: false })], ); } } @@ -404,7 +404,7 @@ where let variant = EnumVariantId { parent: e, local_id }; let res = Resolution { def: PerNs::both(variant.into(), variant.into()), - import: Some(import_id), + import: true, }; (name, res) }) @@ -431,7 +431,7 @@ where } } - let resolution = Resolution { def, import: Some(import_id) }; + let resolution = Resolution { def, import: true }; self.update(module_id, Some(import_id), &[(name, resolution)]); } None => tested_by!(bogus_paths), @@ -719,7 +719,7 @@ where def: PerNs::types( ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(), ), - import: None, + import: false, }; self.def_collector.update(self.module_id, None, &[(name, resolution)]); res @@ -791,7 +791,7 @@ where PerNs::types(def.into()) } }; - let resolution = Resolution { def, import: None }; + let resolution = Resolution { def, import: false }; self.def_collector.update(self.module_id, None, &[(name, resolution)]) } From 02f79e37ca1c4a617a46b85bf897dffbf4abed9e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 17:26:05 +0100 Subject: [PATCH 289/312] Remove import source map --- crates/ra_hir/src/db.rs | 4 +- crates/ra_hir_def/src/db.rs | 11 +----- crates/ra_hir_def/src/nameres/raw.rs | 56 ++++++---------------------- crates/ra_hir_def/src/trace.rs | 8 ---- crates/ra_ide/src/change.rs | 2 - 5 files changed, 15 insertions(+), 66 deletions(-) diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index bfae3660b4..f5ffd64fa7 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -4,8 +4,8 @@ pub use hir_def::db::{ BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, CrateDefMapQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, DocumentationQuery, EnumDataQuery, ExprScopesQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, - LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, RawItemsWithSourceMapQuery, - StaticDataQuery, StructDataQuery, TraitDataQuery, TypeAliasDataQuery, + LangItemQuery, ModuleLangItemsQuery, RawItemsQuery, StaticDataQuery, StructDataQuery, + TraitDataQuery, TypeAliasDataQuery, }; pub use hir_expand::db::{ AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 98bff6cb78..c55fd41110 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -13,10 +13,7 @@ use crate::{ docs::Documentation, generics::GenericParams, lang_item::{LangItemTarget, LangItems}, - nameres::{ - raw::{ImportSourceMap, RawItems}, - CrateDefMap, - }, + nameres::{raw::RawItems, CrateDefMap}, AttrDefId, ConstId, ConstLoc, DefWithBodyId, EnumId, EnumLoc, FunctionId, FunctionLoc, GenericDefId, ImplId, ImplLoc, ModuleId, StaticId, StaticLoc, StructId, StructLoc, TraitId, TraitLoc, TypeAliasId, TypeAliasLoc, UnionId, UnionLoc, @@ -46,12 +43,6 @@ pub trait InternDatabase: SourceDatabase { #[salsa::query_group(DefDatabaseStorage)] pub trait DefDatabase: InternDatabase + AstDatabase { - #[salsa::invoke(RawItems::raw_items_with_source_map_query)] - fn raw_items_with_source_map( - &self, - file_id: HirFileId, - ) -> (Arc, Arc); - #[salsa::invoke(RawItems::raw_items_query)] fn raw_items(&self, file_id: HirFileId) -> Arc; diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index df5dac88a5..73e57f1e55 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -7,23 +7,21 @@ use std::{ops::Index, sync::Arc}; -use either::Either; use hir_expand::{ ast_id_map::AstIdMap, db::AstDatabase, hygiene::Hygiene, name::{AsName, Name}, }; -use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId}; +use ra_arena::{impl_arena_id, Arena, RawId}; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, - AstNode, AstPtr, + AstNode, }; use test_utils::tested_by; use crate::{ - attr::Attrs, db::DefDatabase, path::ModPath, trace::Trace, FileAstId, HirFileId, InFile, - LocalImportId, + attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile, LocalImportId, }; /// `RawItems` is a set of top-level items in a file (except for impls). @@ -41,29 +39,14 @@ pub struct RawItems { items: Vec, } -#[derive(Debug, Default, PartialEq, Eq)] -pub struct ImportSourceMap { - map: ArenaMap, -} - -type ImportSourcePtr = Either, AstPtr>; - impl RawItems { pub(crate) fn raw_items_query( db: &(impl DefDatabase + AstDatabase), file_id: HirFileId, ) -> Arc { - db.raw_items_with_source_map(file_id).0 - } - - pub(crate) fn raw_items_with_source_map_query( - db: &(impl DefDatabase + AstDatabase), - file_id: HirFileId, - ) -> (Arc, Arc) { let mut collector = RawItemsCollector { raw_items: RawItems::default(), source_ast_id_map: db.ast_id_map(file_id), - imports: Trace::new(), file_id, hygiene: Hygiene::new(db, file_id), }; @@ -74,11 +57,8 @@ impl RawItems { collector.process_module(None, item_list); } } - let mut raw_items = collector.raw_items; - let (arena, map) = collector.imports.into_arena_and_map(); - raw_items.imports = arena; - let source_map = ImportSourceMap { map }; - (Arc::new(raw_items), Arc::new(source_map)) + let raw_items = collector.raw_items; + Arc::new(raw_items) } pub(super) fn items(&self) -> &[RawItem] { @@ -217,7 +197,6 @@ pub(super) struct ImplData { struct RawItemsCollector { raw_items: RawItems, - imports: Trace, source_ast_id_map: Arc, file_id: HirFileId, hygiene: Hygiene, @@ -324,7 +303,7 @@ impl RawItemsCollector { ModPath::expand_use_item( InFile { value: use_item, file_id: self.file_id }, &self.hygiene, - |path, use_tree, is_glob, alias| { + |path, _use_tree, is_glob, alias| { let import_data = ImportData { path, alias, @@ -333,11 +312,11 @@ impl RawItemsCollector { is_extern_crate: false, is_macro_use: false, }; - buf.push((import_data, Either::Left(AstPtr::new(use_tree)))); + buf.push(import_data); }, ); - for (import_data, ptr) in buf { - self.push_import(current_module, attrs.clone(), import_data, ptr); + for import_data in buf { + self.push_import(current_module, attrs.clone(), import_data); } } @@ -360,12 +339,7 @@ impl RawItemsCollector { is_extern_crate: true, is_macro_use, }; - self.push_import( - current_module, - attrs, - import_data, - Either::Right(AstPtr::new(&extern_crate)), - ); + self.push_import(current_module, attrs, import_data); } } @@ -396,14 +370,8 @@ impl RawItemsCollector { self.push_item(current_module, attrs, RawItemKind::Impl(imp)) } - fn push_import( - &mut self, - current_module: Option, - attrs: Attrs, - data: ImportData, - source: ImportSourcePtr, - ) { - let import = self.imports.alloc(|| source, || data); + fn push_import(&mut self, current_module: Option, attrs: Attrs, data: ImportData) { + let import = self.raw_items.imports.alloc(data); self.push_item(current_module, attrs, RawItemKind::Import(import)) } diff --git a/crates/ra_hir_def/src/trace.rs b/crates/ra_hir_def/src/trace.rs index 2bcd707bcd..9769e88df5 100644 --- a/crates/ra_hir_def/src/trace.rs +++ b/crates/ra_hir_def/src/trace.rs @@ -18,10 +18,6 @@ pub(crate) struct Trace { } impl Trace { - pub(crate) fn new() -> Trace { - Trace { arena: Some(Arena::default()), map: Some(ArenaMap::default()), len: 0 } - } - pub(crate) fn new_for_arena() -> Trace { Trace { arena: Some(Arena::default()), map: None, len: 0 } } @@ -52,8 +48,4 @@ impl Trace { pub(crate) fn into_map(mut self) -> ArenaMap { self.map.take().unwrap() } - - pub(crate) fn into_arena_and_map(mut self) -> (Arena, ArenaMap) { - (self.arena.take().unwrap(), self.map.take().unwrap()) - } } diff --git a/crates/ra_ide/src/change.rs b/crates/ra_ide/src/change.rs index 4a76d1dd83..387a9cafb6 100644 --- a/crates/ra_ide/src/change.rs +++ b/crates/ra_ide/src/change.rs @@ -270,7 +270,6 @@ impl RootDatabase { self.query(hir::db::AstIdMapQuery).sweep(sweep); - self.query(hir::db::RawItemsWithSourceMapQuery).sweep(sweep); self.query(hir::db::BodyWithSourceMapQuery).sweep(sweep); self.query(hir::db::ExprScopesQuery).sweep(sweep); @@ -309,7 +308,6 @@ impl RootDatabase { hir::db::StructDataQuery hir::db::EnumDataQuery hir::db::TraitDataQuery - hir::db::RawItemsWithSourceMapQuery hir::db::RawItemsQuery hir::db::CrateDefMapQuery hir::db::GenericParamsQuery From 1a8f2aa024c6f1a5e9704c9cbd2e5a020debe2c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 17:34:28 +0100 Subject: [PATCH 290/312] Move LocalImportId --- crates/ra_hir_def/src/item_scope.rs | 15 +++++---------- crates/ra_hir_def/src/lib.rs | 4 ---- crates/ra_hir_def/src/nameres/collector.rs | 13 ++++++------- crates/ra_hir_def/src/nameres/raw.rs | 16 +++++++++------- 4 files changed, 20 insertions(+), 28 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 8b70e13c46..9e082c5f74 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,7 +5,7 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, ImplId, LocalImportId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { @@ -112,28 +112,23 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res( - &mut self, - name: Name, - res: &Resolution, - import: Option, - ) -> bool { + pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, import: bool) -> bool { let mut changed = false; let existing = self.items.entry(name.clone()).or_default(); if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; - existing.import = import.is_some() || res.import; + existing.import = import || res.import; changed = true; } if existing.def.values.is_none() && res.def.values.is_some() { existing.def.values = res.def.values; - existing.import = import.is_some() || res.import; + existing.import = import || res.import; changed = true; } if existing.def.macros.is_none() && res.def.macros.is_some() { existing.def.macros = res.def.macros; - existing.import = import.is_some() || res.import; + existing.import = import || res.import; changed = true; } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 8cb5ab8d03..f6c7f38d17 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -51,10 +51,6 @@ use ra_syntax::{ast, AstNode}; use crate::body::Expander; use crate::builtin_type::BuiltinType; -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub(crate) struct LocalImportId(RawId); -impl_arena_id!(LocalImportId); - #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ModuleId { pub krate: CrateId, diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index c2db5472b4..2b194f4881 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -26,8 +26,7 @@ use crate::{ path::{ModPath, PathKind}, per_ns::PerNs, AdtId, AstId, ConstLoc, ContainerId, EnumLoc, EnumVariantId, FunctionLoc, ImplLoc, Intern, - LocalImportId, LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, - TypeAliasLoc, UnionLoc, + LocalModuleId, ModuleDefId, ModuleId, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, }; pub(super) fn collect_defs(db: &impl DefDatabase, mut def_map: CrateDefMap) -> CrateDefMap { @@ -93,7 +92,7 @@ impl PartialResolvedImport { #[derive(Clone, Debug, Eq, PartialEq)] struct ImportDirective { module_id: LocalModuleId, - import_id: LocalImportId, + import_id: raw::Import, import: raw::ImportData, status: PartialResolvedImport, } @@ -110,7 +109,7 @@ struct MacroDirective { struct DefCollector<'a, DB> { db: &'a DB, def_map: CrateDefMap, - glob_imports: FxHashMap>, + glob_imports: FxHashMap>, unresolved_imports: Vec, resolved_imports: Vec, unexpanded_macros: Vec, @@ -442,7 +441,7 @@ where fn update( &mut self, module_id: LocalModuleId, - import: Option, + import: Option, resolutions: &[(Name, Resolution)], ) { self.update_recursive(module_id, import, resolutions, 0) @@ -451,7 +450,7 @@ where fn update_recursive( &mut self, module_id: LocalModuleId, - import: Option, + import: Option, resolutions: &[(Name, Resolution)], depth: usize, ) { @@ -462,7 +461,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res, import); + changed |= scope.push_res(name.clone(), res, import.is_some()); } if !changed { diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 73e57f1e55..1b83b22474 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -20,9 +20,7 @@ use ra_syntax::{ }; use test_utils::tested_by; -use crate::{ - attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile, LocalImportId, -}; +use crate::{attr::Attrs, db::DefDatabase, path::ModPath, FileAstId, HirFileId, InFile}; /// `RawItems` is a set of top-level items in a file (except for impls). /// @@ -31,7 +29,7 @@ use crate::{ #[derive(Debug, Default, PartialEq, Eq)] pub struct RawItems { modules: Arena, - imports: Arena, + imports: Arena, defs: Arena, macros: Arena, impls: Arena, @@ -73,9 +71,9 @@ impl Index for RawItems { } } -impl Index for RawItems { +impl Index for RawItems { type Output = ImportData; - fn index(&self, idx: LocalImportId) -> &ImportData { + fn index(&self, idx: Import) -> &ImportData { &self.imports[idx] } } @@ -110,7 +108,7 @@ pub(super) struct RawItem { #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub(super) enum RawItemKind { Module(Module), - Import(LocalImportId), + Import(Import), Def(Def), Macro(Macro), Impl(Impl), @@ -126,6 +124,10 @@ pub(super) enum ModuleData { Definition { name: Name, ast_id: FileAstId, items: Vec }, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub(crate) struct Import(RawId); +impl_arena_id!(Import); + #[derive(Debug, Clone, PartialEq, Eq)] pub struct ImportData { pub(super) path: ModPath, From d4b135f38c8c0050768c50e62043ddca5f09079a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 18:45:46 +0100 Subject: [PATCH 291/312] Optimize and profile --- Cargo.lock | 1 + crates/ra_hir/Cargo.toml | 1 + crates/ra_hir/src/from_source.rs | 4 ++++ crates/ra_hir/src/source_binder.rs | 3 +++ crates/ra_hir_def/src/body.rs | 2 ++ crates/ra_ide/src/inlay_hints.rs | 11 ++++++++--- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60b6da8eb9..55afcda7bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -948,6 +948,7 @@ dependencies = [ "ra_hir_def 0.1.0", "ra_hir_expand 0.1.0", "ra_hir_ty 0.1.0", + "ra_prof 0.1.0", "ra_syntax 0.1.0", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index 6ca9cc2e7d..7dc31ad3cb 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml @@ -14,6 +14,7 @@ either = "1.5" ra_syntax = { path = "../ra_syntax" } ra_db = { path = "../ra_db" } +ra_prof = { path = "../ra_prof" } hir_expand = { path = "../ra_hir_expand", package = "ra_hir_expand" } hir_def = { path = "../ra_hir_def", package = "ra_hir_def" } hir_ty = { path = "../ra_hir_ty", package = "ra_hir_ty" } diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 42ca55fe72..ebd9ee2a8e 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -7,6 +7,7 @@ use hir_def::{ StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; +use ra_prof::profile; use ra_syntax::{ ast::{self, AstNode, NameOwner}, match_ast, SyntaxNode, @@ -169,6 +170,7 @@ impl TypeParam { impl Module { pub fn from_declaration(db: &impl DefDatabase, src: InFile) -> Option { + let _p = profile("Module::from_declaration"); let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast); let parent_module = match parent_declaration { @@ -191,6 +193,7 @@ impl Module { } pub fn from_definition(db: &impl DefDatabase, src: InFile) -> Option { + let _p = profile("Module::from_definition"); match src.value { ModuleSource::Module(ref module) => { assert!(!module.has_semi()); @@ -214,6 +217,7 @@ impl Module { } fn analyze_container(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> DynMap { + let _p = profile("analyze_container"); return child_by_source(db, src).unwrap_or_default(); fn child_by_source(db: &impl DefDatabase, src: InFile<&SyntaxNode>) -> Option { diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index b60a6b87e4..85b378483c 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -26,6 +26,7 @@ use hir_ty::{ method_resolution::{self, implements_trait}, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty, }; +use ra_prof::profile; use ra_syntax::{ ast::{self, AstNode}, match_ast, AstPtr, @@ -83,6 +84,7 @@ fn def_with_body_from_child_node( db: &impl HirDatabase, child: InFile<&SyntaxNode>, ) -> Option { + let _p = profile("def_with_body_from_child_node"); child.cloned().ancestors_with_macros(db).find_map(|node| { let n = &node.value; match_ast! { @@ -169,6 +171,7 @@ impl SourceAnalyzer { node: InFile<&SyntaxNode>, offset: Option, ) -> SourceAnalyzer { + let _p = profile("SourceAnalyzer::new"); let def_with_body = def_with_body_from_child_node(db, node); if let Some(def) = def_with_body { let (_body, source_map) = db.body_with_source_map(def.into()); diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 445d215b7b..148ff007ed 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -11,6 +11,7 @@ use hir_expand::{ ast_id_map::AstIdMap, hygiene::Hygiene, AstId, HirFileId, InFile, MacroCallKind, MacroDefId, }; use ra_arena::{map::ArenaMap, Arena}; +use ra_prof::profile; use ra_syntax::{ast, AstNode, AstPtr}; use rustc_hash::FxHashMap; @@ -168,6 +169,7 @@ impl Body { db: &impl DefDatabase, def: DefWithBodyId, ) -> (Arc, Arc) { + let _p = profile("body_with_source_map_query"); let mut params = None; let (file_id, module, body) = match def { diff --git a/crates/ra_ide/src/inlay_hints.rs b/crates/ra_ide/src/inlay_hints.rs index 3154df4572..c5e4069773 100644 --- a/crates/ra_ide/src/inlay_hints.rs +++ b/crates/ra_ide/src/inlay_hints.rs @@ -1,12 +1,15 @@ //! FIXME: write short doc here -use crate::{db::RootDatabase, FileId}; use hir::{HirDisplay, SourceAnalyzer}; +use once_cell::unsync::Lazy; +use ra_prof::profile; use ra_syntax::{ ast::{self, AstNode, TypeAscriptionOwner}, match_ast, SmolStr, SourceFile, SyntaxKind, SyntaxNode, TextRange, }; +use crate::{db::RootDatabase, FileId}; + #[derive(Debug, PartialEq, Eq)] pub enum InlayKind { TypeHint, @@ -27,7 +30,7 @@ pub(crate) fn inlay_hints( ) -> Vec { file.syntax() .descendants() - .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default()) + .flat_map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length)) .flatten() .collect() } @@ -38,7 +41,9 @@ fn get_inlay_hints( node: &SyntaxNode, max_inlay_hint_length: Option, ) -> Option> { - let analyzer = SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None); + let _p = profile("get_inlay_hints"); + let analyzer = + Lazy::new(|| SourceAnalyzer::new(db, hir::InFile::new(file_id.into(), node), None)); match_ast! { match node { ast::LetStmt(it) => { From e903f58d29662b5509fb20c74d7c4131271bfbf0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 21 Dec 2019 19:40:20 +0100 Subject: [PATCH 292/312] More profiling --- crates/ra_hir/src/from_source.rs | 9 +++++++-- crates/ra_hir_def/src/adt.rs | 2 ++ crates/ra_hir_def/src/nameres/raw.rs | 2 ++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index ebd9ee2a8e..6314be8d4c 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs @@ -7,6 +7,7 @@ use hir_def::{ StaticId, StructId, TraitId, TypeAliasId, UnionId, VariantId, }; use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; +use ra_db::FileId; use ra_prof::profile; use ra_syntax::{ ast::{self, AstNode, NameOwner}, @@ -206,10 +207,14 @@ impl Module { }; let original_file = src.file_id.original_file(db); + Module::from_file(db, original_file) + } - let (krate, local_id) = db.relevant_crates(original_file).iter().find_map(|&crate_id| { + fn from_file(db: &impl DefDatabase, file: FileId) -> Option { + let _p = profile("Module::from_file"); + let (krate, local_id) = db.relevant_crates(file).iter().find_map(|&crate_id| { let crate_def_map = db.crate_def_map(crate_id); - let local_id = crate_def_map.modules_for_file(original_file).next()?; + let local_id = crate_def_map.modules_for_file(file).next()?; Some((crate_id, local_id)) })?; Some(Module { id: ModuleId { krate, local_id } }) diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index ec3d57d1a9..d9ea693e34 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs @@ -8,6 +8,7 @@ use hir_expand::{ InFile, }; use ra_arena::{map::ArenaMap, Arena}; +use ra_prof::profile; use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; use crate::{ @@ -72,6 +73,7 @@ impl StructData { impl EnumData { pub(crate) fn enum_data_query(db: &impl DefDatabase, e: EnumId) -> Arc { + let _p = profile("enum_data_query"); let src = e.lookup(db).source(db); let name = src.value.name().map_or_else(Name::missing, |n| n.as_name()); let mut trace = Trace::new_for_arena(); diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index 1b83b22474..73dc087459 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs @@ -14,6 +14,7 @@ use hir_expand::{ name::{AsName, Name}, }; use ra_arena::{impl_arena_id, Arena, RawId}; +use ra_prof::profile; use ra_syntax::{ ast::{self, AttrsOwner, NameOwner}, AstNode, @@ -42,6 +43,7 @@ impl RawItems { db: &(impl DefDatabase + AstDatabase), file_id: HirFileId, ) -> Arc { + let _p = profile("raw_items_query"); let mut collector = RawItemsCollector { raw_items: RawItems::default(), source_ast_id_map: db.ast_id_map(file_id), From 4ef5cd9a89fd5ee02ae655ba08486087af9ffcf4 Mon Sep 17 00:00:00 2001 From: Jeremy Kolb Date: Sat, 21 Dec 2019 15:27:38 -0500 Subject: [PATCH 293/312] Add some module docs --- crates/ra_lsp_server/src/caps.rs | 2 +- crates/ra_lsp_server/src/conv.rs | 2 +- crates/ra_lsp_server/src/main_loop.rs | 3 ++- crates/ra_lsp_server/src/main_loop/handlers.rs | 3 ++- crates/ra_lsp_server/src/main_loop/pending_requests.rs | 2 +- crates/ra_lsp_server/src/main_loop/subscriptions.rs | 2 +- crates/ra_lsp_server/src/markdown.rs | 2 +- crates/ra_lsp_server/src/req.rs | 2 +- crates/ra_lsp_server/src/world.rs | 5 ++++- 9 files changed, 14 insertions(+), 9 deletions(-) diff --git a/crates/ra_lsp_server/src/caps.rs b/crates/ra_lsp_server/src/caps.rs index d812ff7ca2..eeca67ee19 100644 --- a/crates/ra_lsp_server/src/caps.rs +++ b/crates/ra_lsp_server/src/caps.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Advertizes the capabilities of the LSP Server. use lsp_types::{ CodeActionProviderCapability, CodeLensOptions, CompletionOptions, diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index 5561f6270b..e93d4ea33d 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Convenience module responsible for translating between rust-analyzer's types and LSP types. use lsp_types::{ self, CreateFile, DiagnosticSeverity, DocumentChangeOperation, DocumentChanges, Documentation, diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 9e207415e6..81fd08c910 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -1,4 +1,5 @@ -//! FIXME: write short doc here +//! The main loop of `ra_lsp_server` responsible for dispatching LSP requests/replies and +//! notifications back to the client. mod handlers; mod subscriptions; diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 5e3b1a73f0..39eb3df3e5 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs @@ -1,4 +1,5 @@ -//! FIXME: write short doc here +//! This module is responsible for implementing handlers for Lanuage Server Protocol. +//! The majority of requests are fulfilled by calling into the `ra_ide` crate. use std::{fmt::Write as _, io::Write as _}; diff --git a/crates/ra_lsp_server/src/main_loop/pending_requests.rs b/crates/ra_lsp_server/src/main_loop/pending_requests.rs index e7ea7aa5b8..2d22134641 100644 --- a/crates/ra_lsp_server/src/main_loop/pending_requests.rs +++ b/crates/ra_lsp_server/src/main_loop/pending_requests.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Datastructures that keep track of inflight requests. use std::time::{Duration, Instant}; diff --git a/crates/ra_lsp_server/src/main_loop/subscriptions.rs b/crates/ra_lsp_server/src/main_loop/subscriptions.rs index 609b2adcc9..b0bae90f5c 100644 --- a/crates/ra_lsp_server/src/main_loop/subscriptions.rs +++ b/crates/ra_lsp_server/src/main_loop/subscriptions.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Keeps track of file subscriptions. use ra_ide::FileId; use rustc_hash::FxHashSet; diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs index f51fc4ade3..76bef45ccc 100644 --- a/crates/ra_lsp_server/src/markdown.rs +++ b/crates/ra_lsp_server/src/markdown.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Transforms markdown pub(crate) fn format_docs(src: &str) -> String { let mut processed_lines = Vec::new(); diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs index 2a22b655ce..b34e6f9b89 100644 --- a/crates/ra_lsp_server/src/req.rs +++ b/crates/ra_lsp_server/src/req.rs @@ -1,4 +1,4 @@ -//! FIXME: write short doc here +//! Defines `rust-analyzer` specific custom messages. use lsp_types::{Location, Position, Range, TextDocumentIdentifier, Url}; use rustc_hash::FxHashMap; diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index f89b23089e..5e53b02785 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -1,4 +1,7 @@ -//! FIXME: write short doc here +//! The context or environment in which the language server functions. +//! In our server implementation this is know as the `WorldState`. +//! +//! Each tick provides an immutable snapshot of the state as `WorldSnapshot`. use std::{ path::{Path, PathBuf}, From b04d4a88d1ba7f04445e807b6a816930b1e9bbf2 Mon Sep 17 00:00:00 2001 From: roblabla Date: Sun, 22 Dec 2019 00:38:23 +0000 Subject: [PATCH 294/312] Parse const generics Fixes #1574 Fixes #2281 --- crates/ra_parser/src/grammar/type_params.rs | 11 +++++++ crates/ra_parser/src/syntax_kind/generated.rs | 1 + crates/ra_syntax/src/ast/generated.rs | 30 +++++++++++++++++++ crates/ra_syntax/src/grammar.ron | 5 ++++ .../parser/inline/ok/0147_const_param.rs | 1 + .../parser/inline/ok/0147_const_param.txt | 23 ++++++++++++++ 6 files changed, 71 insertions(+) create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rs create mode 100644 crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.txt diff --git a/crates/ra_parser/src/grammar/type_params.rs b/crates/ra_parser/src/grammar/type_params.rs index 34406b5bd5..50e4900c31 100644 --- a/crates/ra_parser/src/grammar/type_params.rs +++ b/crates/ra_parser/src/grammar/type_params.rs @@ -25,6 +25,7 @@ fn type_param_list(p: &mut Parser) { match p.current() { LIFETIME => lifetime_param(p, m), IDENT => type_param(p, m), + CONST_KW => type_const_param(p, m), _ => { m.abandon(p); p.err_and_bump("expected type parameter") @@ -62,6 +63,16 @@ fn type_param(p: &mut Parser, m: Marker) { m.complete(p, TYPE_PARAM); } +// test const_param +// struct S; +fn type_const_param(p: &mut Parser, m: Marker) { + assert!(p.at(CONST_KW)); + p.bump(T![const]); + name(p); + types::ascription(p); + m.complete(p, CONST_PARAM); +} + // test type_param_bounds // struct S; pub(super) fn bounds(p: &mut Parser) { diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index fe0fcdb33f..bee1f11347 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs @@ -227,6 +227,7 @@ pub enum SyntaxKind { TYPE_PARAM_LIST, LIFETIME_PARAM, TYPE_PARAM, + CONST_PARAM, TYPE_ARG_LIST, LIFETIME_ARG, TYPE_ARG, diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 9dd6bd3eac..b917f77fef 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -551,6 +551,36 @@ impl ConstDef { } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct ConstParam { + pub(crate) syntax: SyntaxNode, +} +impl AstNode for ConstParam { + fn can_cast(kind: SyntaxKind) -> bool { + match kind { + CONST_PARAM => true, + _ => false, + } + } + fn cast(syntax: SyntaxNode) -> Option { + if Self::can_cast(syntax.kind()) { + Some(Self { syntax }) + } else { + None + } + } + fn syntax(&self) -> &SyntaxNode { + &self.syntax + } +} +impl ast::NameOwner for ConstParam {} +impl ast::AttrsOwner for ConstParam {} +impl ast::TypeAscriptionOwner for ConstParam {} +impl ConstParam { + pub fn default_val(&self) -> Option { + AstChildren::new(&self.syntax).next() + } +} +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ContinueExpr { pub(crate) syntax: SyntaxNode, } diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 9ffa9095bc..d6802b6fb2 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -243,6 +243,7 @@ Grammar( "TYPE_PARAM_LIST", "LIFETIME_PARAM", "TYPE_PARAM", + "CONST_PARAM", "TYPE_ARG_LIST", "LIFETIME_ARG", "TYPE_ARG", @@ -602,6 +603,10 @@ Grammar( options: [("default_type", "TypeRef")], traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"], ), + "ConstParam": ( + options: [("default_val", "Expr")], + traits: ["NameOwner", "AttrsOwner", "TypeAscriptionOwner"], + ), "LifetimeParam": ( traits: ["AttrsOwner"], ), diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rs b/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rs new file mode 100644 index 0000000000..8cdb3b7036 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.rs @@ -0,0 +1 @@ +struct S; diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.txt b/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.txt new file mode 100644 index 0000000000..f81de7bac7 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_const_param.txt @@ -0,0 +1,23 @@ +SOURCE_FILE@[0; 24) + STRUCT_DEF@[0; 23) + STRUCT_KW@[0; 6) "struct" + WHITESPACE@[6; 7) " " + NAME@[7; 8) + IDENT@[7; 8) "S" + TYPE_PARAM_LIST@[8; 22) + L_ANGLE@[8; 9) "<" + CONST_PARAM@[9; 21) + CONST_KW@[9; 14) "const" + WHITESPACE@[14; 15) " " + NAME@[15; 16) + IDENT@[15; 16) "N" + COLON@[16; 17) ":" + WHITESPACE@[17; 18) " " + PATH_TYPE@[18; 21) + PATH@[18; 21) + PATH_SEGMENT@[18; 21) + NAME_REF@[18; 21) + IDENT@[18; 21) "u32" + R_ANGLE@[21; 22) ">" + SEMI@[22; 23) ";" + WHITESPACE@[23; 24) "\n" From 737045c1eac87ab78f0042340f0311d3679158b0 Mon Sep 17 00:00:00 2001 From: Edwin Cheng Date: Sun, 22 Dec 2019 11:11:10 +0800 Subject: [PATCH 295/312] Use name instead of ident for macro 2.0 sytnax --- crates/ra_parser/src/grammar/items.rs | 2 +- .../ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt | 6 ++++-- .../test_data/parser/inline/ok/0148_pub_macro_def.txt | 3 ++- crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt | 6 ++++-- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/crates/ra_parser/src/grammar/items.rs b/crates/ra_parser/src/grammar/items.rs index 3c717e5f9e..6e23d9b72d 100644 --- a/crates/ra_parser/src/grammar/items.rs +++ b/crates/ra_parser/src/grammar/items.rs @@ -389,7 +389,7 @@ pub(crate) fn mod_item_list(p: &mut Parser) { // macro m($i:ident) {} fn macro_def(p: &mut Parser, m: Marker) { p.expect(T![macro]); - p.expect(IDENT); + name_r(p, ITEM_RECOVERY_SET); if p.at(T!['{']) { token_tree(p); } else if !p.at(T!['(']) { diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt index af1122bfa4..3556099bd0 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0147_macro_def.txt @@ -2,7 +2,8 @@ SOURCE_FILE@[0; 50) MACRO_DEF@[0; 28) MACRO_KW@[0; 5) "macro" WHITESPACE@[5; 6) " " - IDENT@[6; 7) "m" + NAME@[6; 7) + IDENT@[6; 7) "m" WHITESPACE@[7; 8) " " TOKEN_TREE@[8; 28) L_CURLY@[8; 9) "{" @@ -27,7 +28,8 @@ SOURCE_FILE@[0; 50) MACRO_DEF@[29; 49) MACRO_KW@[29; 34) "macro" WHITESPACE@[34; 35) " " - IDENT@[35; 36) "m" + NAME@[35; 36) + IDENT@[35; 36) "m" TOKEN_TREE@[36; 49) TOKEN_TREE@[36; 46) L_PAREN@[36; 37) "(" diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt index 985f61f89e..cfd79d9c26 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt +++ b/crates/ra_syntax/test_data/parser/inline/ok/0148_pub_macro_def.txt @@ -5,7 +5,8 @@ SOURCE_FILE@[0; 24) WHITESPACE@[3; 4) " " MACRO_KW@[4; 9) "macro" WHITESPACE@[9; 10) " " - IDENT@[10; 11) "m" + NAME@[10; 11) + IDENT@[10; 11) "m" TOKEN_TREE@[11; 23) TOKEN_TREE@[11; 20) L_PAREN@[11; 12) "(" diff --git a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt index 158af85f55..2be523fc35 100644 --- a/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt +++ b/crates/ra_syntax/test_data/parser/ok/0062_macro_2.0.txt @@ -2,7 +2,8 @@ SOURCE_FILE@[0; 349) MACRO_DEF@[0; 93) MACRO_KW@[0; 5) "macro" WHITESPACE@[5; 6) " " - IDENT@[6; 21) "parse_use_trees" + NAME@[6; 21) + IDENT@[6; 21) "parse_use_trees" TOKEN_TREE@[21; 93) TOKEN_TREE@[21; 41) L_PAREN@[21; 22) "(" @@ -75,7 +76,8 @@ SOURCE_FILE@[0; 349) MACRO_DEF@[134; 346) MACRO_KW@[134; 139) "macro" WHITESPACE@[139; 140) " " - IDENT@[140; 150) "test_merge" + NAME@[140; 150) + IDENT@[140; 150) "test_merge" TOKEN_TREE@[150; 346) TOKEN_TREE@[150; 203) L_PAREN@[150; 151) "(" From 6acef5a7c088bcc1cdf8a64e28b8f20ddf9dcde7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 13:56:19 +0100 Subject: [PATCH 296/312] Don't fire no-op changes after files are saved to disk --- crates/ra_lsp_server/src/main_loop.rs | 10 ++++++---- crates/ra_lsp_server/src/world.rs | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 81fd08c910..dda318e43e 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs @@ -305,7 +305,6 @@ fn loop_turn( log::info!("queued count = {}", queue_count); } - let mut state_changed = false; match event { Event::Task(task) => { on_task(task, &connection.sender, &mut loop_state.pending_requests, world_state); @@ -313,7 +312,6 @@ fn loop_turn( } Event::Vfs(task) => { world_state.vfs.write().handle_task(task); - state_changed = true; } Event::Lib(lib) => { world_state.add_lib(lib); @@ -338,7 +336,6 @@ fn loop_turn( &mut loop_state.subscriptions, not, )?; - state_changed = true; } Message::Response(resp) => { let removed = loop_state.pending_responses.remove(&resp.id); @@ -349,7 +346,12 @@ fn loop_turn( }, }; - loop_state.pending_libraries.extend(world_state.process_changes()); + let mut state_changed = false; + if let Some(changes) = world_state.process_changes() { + state_changed = true; + loop_state.pending_libraries.extend(changes); + } + while loop_state.in_flight_libraries < MAX_IN_FLIGHT_LIBS && !loop_state.pending_libraries.is_empty() { diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs index 5e53b02785..79431e7e6f 100644 --- a/crates/ra_lsp_server/src/world.rs +++ b/crates/ra_lsp_server/src/world.rs @@ -145,10 +145,10 @@ impl WorldState { /// FIXME: better API here pub fn process_changes( &mut self, - ) -> Vec<(SourceRootId, Vec<(FileId, RelativePathBuf, Arc)>)> { + ) -> Option)>)>> { let changes = self.vfs.write().commit_changes(); if changes.is_empty() { - return Vec::new(); + return None; } let mut libs = Vec::new(); let mut change = AnalysisChange::new(); @@ -182,7 +182,7 @@ impl WorldState { } } self.analysis_host.apply_change(change); - libs + Some(libs) } pub fn add_lib(&mut self, data: LibraryData) { From 08df35537574d242f5f09b0f21eef14a5d0eb4ac Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 14:17:31 +0100 Subject: [PATCH 297/312] More compact profiling display --- crates/ra_prof/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 845b2221c8..f260c40a32 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -217,7 +217,7 @@ fn print( total: Option, ) { let mut last = 0; - let indent = repeat(" ").take(lvl + 1).collect::(); + let indent = repeat(" ").take(lvl).collect::(); // We output hierarchy for long calls, but sum up all short calls let mut short = Vec::new(); let mut accounted_for = Duration::default(); @@ -227,7 +227,7 @@ fn print( } accounted_for += duration; if duration >= longer_than { - writeln!(out, "{} {:6}ms - {}", indent, duration.as_millis(), msg) + writeln!(out, "{}{:5}ms - {}", indent, duration.as_millis(), msg) .expect("printing profiling info to stdout"); print(lvl + 1, &msgs[last..i], out, longer_than, Some(duration)); @@ -245,14 +245,14 @@ fn print( count += 1; total_duration += *time; }); - writeln!(out, "{} {:6}ms - {} ({} calls)", indent, total_duration.as_millis(), msg, count) + writeln!(out, "{}{:5}ms - {} ({} calls)", indent, total_duration.as_millis(), msg, count) .expect("printing profiling info to stdout"); } if let Some(total) = total { if let Some(unaccounted) = total.checked_sub(accounted_for) { if unaccounted >= longer_than && last > 0 { - writeln!(out, "{} {:6}ms - ???", indent, unaccounted.as_millis()) + writeln!(out, "{}{:5}ms - ???", indent, unaccounted.as_millis()) .expect("printing profiling info to stdout"); } } From fe38fffaa90f656abbeff7b8a167afc45cc492a9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:04:31 +0100 Subject: [PATCH 298/312] Minor rename --- crates/ra_hir_def/src/item_scope.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 9e082c5f74..eab3e2fff4 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -9,7 +9,7 @@ use crate::{per_ns::PerNs, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { - items: FxHashMap, + visible: FxHashMap, impls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -49,7 +49,7 @@ pub(crate) enum BuiltinShadowMode { impl ItemScope { pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing - self.items.iter().chain(BUILTIN_SCOPE.iter()) + self.visible.iter().chain(BUILTIN_SCOPE.iter()) } pub fn declarations(&self) -> impl Iterator + '_ { @@ -66,7 +66,7 @@ impl ItemScope { /// Iterate over all module scoped macros pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { - self.items + self.visible .iter() .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) } @@ -79,9 +79,9 @@ impl ItemScope { /// Get a name from current module scope, legacy macros are not included pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { match shadow { - BuiltinShadowMode::Module => self.items.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Module => self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)), BuiltinShadowMode::Other => { - let item = self.items.get(name); + let item = self.visible.get(name); if let Some(res) = item { if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { return BUILTIN_SCOPE.get(name).or(item); @@ -94,7 +94,7 @@ impl ItemScope { } pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { - self.items.values().filter_map(|r| match r.def.take_types() { + self.visible.values().filter_map(|r| match r.def.take_types() { Some(ModuleDefId::TraitId(t)) => Some(t), _ => None, }) @@ -114,7 +114,7 @@ impl ItemScope { pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, import: bool) -> bool { let mut changed = false; - let existing = self.items.entry(name.clone()).or_default(); + let existing = self.visible.entry(name.clone()).or_default(); if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; @@ -139,7 +139,7 @@ impl ItemScope { } pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { - self.items.iter().map(|(name, res)| (name.clone(), res.clone())).collect() + self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect() } pub(crate) fn collect_legacy_macros(&self) -> FxHashMap { From e69af8596262931f8e55b7f9203f65d14827e2d8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:08:57 +0100 Subject: [PATCH 299/312] Refactor PerNs construction --- crates/ra_hir_def/src/item_scope.rs | 20 +++++- crates/ra_hir_def/src/nameres/collector.rs | 81 +++++++++------------- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index eab3e2fff4..a96b5cfd26 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -5,7 +5,7 @@ use hir_expand::name::Name; use once_cell::sync::Lazy; use rustc_hash::FxHashMap; -use crate::{per_ns::PerNs, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; +use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, TraitId}; #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { @@ -153,3 +153,21 @@ pub struct Resolution { pub def: PerNs, pub(crate) import: bool, } + +impl From for PerNs { + fn from(def: ModuleDefId) -> PerNs { + match def { + ModuleDefId::ModuleId(_) => PerNs::types(def), + ModuleDefId::FunctionId(_) => PerNs::values(def), + ModuleDefId::AdtId(adt) => match adt { + AdtId::StructId(_) | AdtId::UnionId(_) => PerNs::both(def, def), + AdtId::EnumId(_) => PerNs::types(def), + }, + ModuleDefId::EnumVariantId(_) => PerNs::both(def, def), + ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def), + ModuleDefId::TraitId(_) => PerNs::types(def), + ModuleDefId::TypeAliasId(_) => PerNs::types(def), + ModuleDefId::BuiltinType(_) => PerNs::types(def), + } + } +} diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 2b194f4881..b4e438257a 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -714,12 +714,9 @@ where modules[res].scope.define_legacy_macro(name, mac) } modules[self.module_id].children.insert(name.clone(), res); - let resolution = Resolution { - def: PerNs::types( - ModuleId { krate: self.def_collector.def_map.krate, local_id: res }.into(), - ), - import: false, - }; + let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; + let def: ModuleDefId = module.into(); + let resolution = Resolution { def: def.into(), import: false }; self.def_collector.update(self.module_id, None, &[(name, resolution)]); res } @@ -734,63 +731,51 @@ where let name = def.name.clone(); let container = ContainerId::ModuleId(module); - let def: PerNs = match def.kind { - raw::DefKind::Function(ast_id) => { - let def = FunctionLoc { - container: container.into(), - ast_id: AstId::new(self.file_id, ast_id), - } - .intern(self.def_collector.db); - - PerNs::values(def.into()) + let def: ModuleDefId = match def.kind { + raw::DefKind::Function(ast_id) => FunctionLoc { + container: container.into(), + ast_id: AstId::new(self.file_id, ast_id), } + .intern(self.def_collector.db) + .into(), raw::DefKind::Struct(ast_id) => { - let def = StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } - .intern(self.def_collector.db); - PerNs::both(def.into(), def.into()) + StructLoc { container, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } raw::DefKind::Union(ast_id) => { - let def = UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) } - .intern(self.def_collector.db); - PerNs::both(def.into(), def.into()) + UnionLoc { container, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } raw::DefKind::Enum(ast_id) => { - let def = EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) } - .intern(self.def_collector.db); - PerNs::types(def.into()) + EnumLoc { container, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } raw::DefKind::Const(ast_id) => { - let def = ConstLoc { - container: container.into(), - ast_id: AstId::new(self.file_id, ast_id), - } - .intern(self.def_collector.db); - - PerNs::values(def.into()) + ConstLoc { container: container.into(), ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } raw::DefKind::Static(ast_id) => { - let def = StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) } - .intern(self.def_collector.db); - - PerNs::values(def.into()) + StaticLoc { container, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } raw::DefKind::Trait(ast_id) => { - let def = TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) } - .intern(self.def_collector.db); - - PerNs::types(def.into()) + TraitLoc { container, ast_id: AstId::new(self.file_id, ast_id) } + .intern(self.def_collector.db) + .into() } - raw::DefKind::TypeAlias(ast_id) => { - let def = TypeAliasLoc { - container: container.into(), - ast_id: AstId::new(self.file_id, ast_id), - } - .intern(self.def_collector.db); - - PerNs::types(def.into()) + raw::DefKind::TypeAlias(ast_id) => TypeAliasLoc { + container: container.into(), + ast_id: AstId::new(self.file_id, ast_id), } + .intern(self.def_collector.db) + .into(), }; - let resolution = Resolution { def, import: false }; + let resolution = Resolution { def: def.into(), import: false }; self.def_collector.update(self.module_id, None, &[(name, resolution)]) } From 2c60f42825e68d8133854d378d9550139c71d9b4 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:21:48 +0100 Subject: [PATCH 300/312] Separate defs from imports --- crates/ra_hir_def/src/item_scope.rs | 11 ++++++----- crates/ra_hir_def/src/nameres/collector.rs | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index a96b5cfd26..b5c07ed5ff 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -10,6 +10,7 @@ use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { visible: FxHashMap, + defs: Vec, impls: Vec, /// Macros visible in current module in legacy textual scope /// @@ -53,11 +54,7 @@ impl ItemScope { } pub fn declarations(&self) -> impl Iterator + '_ { - self.entries() - .filter_map(|(_name, res)| if !res.import { Some(res.def) } else { None }) - .flat_map(|per_ns| { - per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter()) - }) + self.defs.iter().copied() } pub fn impls(&self) -> impl Iterator + ExactSizeIterator + '_ { @@ -100,6 +97,10 @@ impl ItemScope { }) } + pub(crate) fn define_def(&mut self, def: ModuleDefId) { + self.defs.push(def) + } + pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option { self.legacy_macros.get(name).copied() } diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index b4e438257a..745e31c0d3 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -716,6 +716,7 @@ where modules[self.module_id].children.insert(name.clone(), res); let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; let def: ModuleDefId = module.into(); + self.def_collector.def_map.modules[self.module_id].scope.define_def(def); let resolution = Resolution { def: def.into(), import: false }; self.def_collector.update(self.module_id, None, &[(name, resolution)]); res @@ -775,6 +776,7 @@ where .intern(self.def_collector.db) .into(), }; + self.def_collector.def_map.modules[self.module_id].scope.define_def(def); let resolution = Resolution { def: def.into(), import: false }; self.def_collector.update(self.module_id, None, &[(name, resolution)]) } From 558956c84be5e8752986bae001c7fd3f06cbe86d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:28:55 +0100 Subject: [PATCH 301/312] Remove import field --- crates/ra_hir_def/src/item_scope.rs | 13 ++----------- crates/ra_hir_def/src/nameres/collector.rs | 14 ++++++-------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index b5c07ed5ff..81089554f0 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -30,9 +30,7 @@ pub struct ItemScope { static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() - .map(|(name, ty)| { - (name.clone(), Resolution { def: PerNs::types(ty.clone().into()), import: false }) - }) + .map(|(name, ty)| (name.clone(), Resolution { def: PerNs::types(ty.clone().into()) })) .collect() }); @@ -113,29 +111,23 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, import: bool) -> bool { + pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, _import: bool) -> bool { let mut changed = false; let existing = self.visible.entry(name.clone()).or_default(); if existing.def.types.is_none() && res.def.types.is_some() { existing.def.types = res.def.types; - existing.import = import || res.import; changed = true; } if existing.def.values.is_none() && res.def.values.is_some() { existing.def.values = res.def.values; - existing.import = import || res.import; changed = true; } if existing.def.macros.is_none() && res.def.macros.is_some() { existing.def.macros = res.def.macros; - existing.import = import || res.import; changed = true; } - if existing.def.is_none() && res.def.is_none() && !existing.import && res.import { - existing.import = res.import; - } changed } @@ -152,7 +144,6 @@ impl ItemScope { pub struct Resolution { /// None for unresolved pub def: PerNs, - pub(crate) import: bool, } impl From for PerNs { diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 745e31c0d3..3706c12233 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -218,7 +218,7 @@ where self.update( self.def_map.root, None, - &[(name, Resolution { def: PerNs::macros(macro_), import: false })], + &[(name, Resolution { def: PerNs::macros(macro_) })], ); } } @@ -401,10 +401,8 @@ where .map(|(local_id, variant_data)| { let name = variant_data.name.clone(); let variant = EnumVariantId { parent: e, local_id }; - let res = Resolution { - def: PerNs::both(variant.into(), variant.into()), - import: true, - }; + let res = + Resolution { def: PerNs::both(variant.into(), variant.into()) }; (name, res) }) .collect::>(); @@ -430,7 +428,7 @@ where } } - let resolution = Resolution { def, import: true }; + let resolution = Resolution { def }; self.update(module_id, Some(import_id), &[(name, resolution)]); } None => tested_by!(bogus_paths), @@ -717,7 +715,7 @@ where let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; let def: ModuleDefId = module.into(); self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - let resolution = Resolution { def: def.into(), import: false }; + let resolution = Resolution { def: def.into() }; self.def_collector.update(self.module_id, None, &[(name, resolution)]); res } @@ -777,7 +775,7 @@ where .into(), }; self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - let resolution = Resolution { def: def.into(), import: false }; + let resolution = Resolution { def: def.into() }; self.def_collector.update(self.module_id, None, &[(name, resolution)]) } From e8da7d4061960844502e3064c33eef4a0dc3828e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:31:30 +0100 Subject: [PATCH 302/312] Remove unused parameters --- crates/ra_hir_def/src/item_scope.rs | 2 +- crates/ra_hir_def/src/nameres/collector.rs | 34 ++++++++-------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 81089554f0..71f44b5563 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -111,7 +111,7 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, res: &Resolution, _import: bool) -> bool { + pub(crate) fn push_res(&mut self, name: Name, res: &Resolution) -> bool { let mut changed = false; let existing = self.visible.entry(name.clone()).or_default(); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 3706c12233..d27c3e1977 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -215,11 +215,7 @@ where // In Rust, `#[macro_export]` macros are unconditionally visible at the // crate root, even if the parent modules is **not** visible. if export { - self.update( - self.def_map.root, - None, - &[(name, Resolution { def: PerNs::macros(macro_) })], - ); + self.update(self.def_map.root, &[(name, Resolution { def: PerNs::macros(macro_) })]); } } @@ -373,7 +369,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, Some(import_id), &items); + self.update(module_id, &items); } else { // glob import from same crate => we do an initial // import, and then need to propagate any further @@ -383,7 +379,7 @@ where // Module scoped macros is included let items = scope.collect_resolutions(); - self.update(module_id, Some(import_id), &items); + self.update(module_id, &items); // record the glob import in case we add further items let glob = self.glob_imports.entry(m.local_id).or_default(); if !glob.iter().any(|it| *it == (module_id, import_id)) { @@ -406,7 +402,7 @@ where (name, res) }) .collect::>(); - self.update(module_id, Some(import_id), &resolutions); + self.update(module_id, &resolutions); } Some(d) => { log::debug!("glob import {:?} from non-module/enum {:?}", import, d); @@ -429,26 +425,20 @@ where } let resolution = Resolution { def }; - self.update(module_id, Some(import_id), &[(name, resolution)]); + self.update(module_id, &[(name, resolution)]); } None => tested_by!(bogus_paths), } } } - fn update( - &mut self, - module_id: LocalModuleId, - import: Option, - resolutions: &[(Name, Resolution)], - ) { - self.update_recursive(module_id, import, resolutions, 0) + fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, Resolution)]) { + self.update_recursive(module_id, resolutions, 0) } fn update_recursive( &mut self, module_id: LocalModuleId, - import: Option, resolutions: &[(Name, Resolution)], depth: usize, ) { @@ -459,7 +449,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res, import.is_some()); + changed |= scope.push_res(name.clone(), res); } if !changed { @@ -472,9 +462,9 @@ where .flat_map(|v| v.iter()) .cloned() .collect::>(); - for (glob_importing_module, glob_import) in glob_imports { + for (glob_importing_module, _glob_import) in glob_imports { // We pass the glob import so that the tracked import in those modules is that glob import - self.update_recursive(glob_importing_module, Some(glob_import), resolutions, depth + 1); + self.update_recursive(glob_importing_module, resolutions, depth + 1); } } @@ -716,7 +706,7 @@ where let def: ModuleDefId = module.into(); self.def_collector.def_map.modules[self.module_id].scope.define_def(def); let resolution = Resolution { def: def.into() }; - self.def_collector.update(self.module_id, None, &[(name, resolution)]); + self.def_collector.update(self.module_id, &[(name, resolution)]); res } @@ -776,7 +766,7 @@ where }; self.def_collector.def_map.modules[self.module_id].scope.define_def(def); let resolution = Resolution { def: def.into() }; - self.def_collector.update(self.module_id, None, &[(name, resolution)]) + self.def_collector.update(self.module_id, &[(name, resolution)]) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { From 6c3ddcfa501060cff3a7f81c179f712ef072c808 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:37:07 +0100 Subject: [PATCH 303/312] Simplify --- crates/ra_hir/src/code_model.rs | 2 +- crates/ra_hir_def/src/body/scope.rs | 4 +- crates/ra_hir_def/src/item_scope.rs | 44 ++++++++----------- crates/ra_hir_def/src/nameres/collector.rs | 19 +++----- .../ra_hir_def/src/nameres/path_resolution.rs | 12 ++--- crates/ra_hir_def/src/nameres/tests.rs | 10 ++--- crates/ra_hir_def/src/resolver.rs | 8 ++-- 7 files changed, 41 insertions(+), 58 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 4cd28eb4e3..bcfc0d03ec 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -184,7 +184,7 @@ impl Module { db.crate_def_map(self.id.krate)[self.id.local_id] .scope .entries() - .map(|(name, res)| (name.clone(), res.def.into())) + .map(|(name, def)| (name.clone(), def.into())) .collect() } diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index ab6599b23f..a635523275 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs @@ -183,8 +183,8 @@ mod tests { let crate_def_map = db.crate_def_map(krate); let module = crate_def_map.modules_for_file(file_id).next().unwrap(); - let (_, res) = crate_def_map[module].scope.entries().next().unwrap(); - match res.def.take_values().unwrap() { + let (_, def) = crate_def_map[module].scope.entries().next().unwrap(); + match def.take_values().unwrap() { ModuleDefId::FunctionId(it) => it, _ => panic!(), } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 71f44b5563..f1adc3b58c 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -9,7 +9,7 @@ use crate::{per_ns::PerNs, AdtId, BuiltinType, ImplId, MacroDefId, ModuleDefId, #[derive(Debug, Default, PartialEq, Eq)] pub struct ItemScope { - visible: FxHashMap, + visible: FxHashMap, defs: Vec, impls: Vec, /// Macros visible in current module in legacy textual scope @@ -27,10 +27,10 @@ pub struct ItemScope { legacy_macros: FxHashMap, } -static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { +static BUILTIN_SCOPE: Lazy> = Lazy::new(|| { BuiltinType::ALL .iter() - .map(|(name, ty)| (name.clone(), Resolution { def: PerNs::types(ty.clone().into()) })) + .map(|(name, ty)| (name.clone(), PerNs::types(ty.clone().into()))) .collect() }); @@ -46,9 +46,9 @@ pub(crate) enum BuiltinShadowMode { /// Legacy macros can only be accessed through special methods like `get_legacy_macros`. /// Other methods will only resolve values, types and module scoped macros only. impl ItemScope { - pub fn entries<'a>(&'a self) -> impl Iterator + 'a { + pub fn entries<'a>(&'a self) -> impl Iterator + 'a { //FIXME: shadowing - self.visible.iter().chain(BUILTIN_SCOPE.iter()) + self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def)) } pub fn declarations(&self) -> impl Iterator + '_ { @@ -61,9 +61,7 @@ impl ItemScope { /// Iterate over all module scoped macros pub(crate) fn macros<'a>(&'a self) -> impl Iterator + 'a { - self.visible - .iter() - .filter_map(|(name, res)| res.def.take_macros().map(|macro_| (name, macro_))) + self.visible.iter().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_))) } /// Iterate over all legacy textual scoped macros visible at the end of the module @@ -72,13 +70,13 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&Resolution> { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&PerNs> { match shadow { BuiltinShadowMode::Module => self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)), BuiltinShadowMode::Other => { let item = self.visible.get(name); - if let Some(res) = item { - if let Some(ModuleDefId::ModuleId(_)) = res.def.take_types() { + if let Some(def) = item { + if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { return BUILTIN_SCOPE.get(name).or(item); } } @@ -89,7 +87,7 @@ impl ItemScope { } pub(crate) fn traits<'a>(&'a self) -> impl Iterator + 'a { - self.visible.values().filter_map(|r| match r.def.take_types() { + self.visible.values().filter_map(|def| match def.take_types() { Some(ModuleDefId::TraitId(t)) => Some(t), _ => None, }) @@ -111,27 +109,27 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, res: &Resolution) -> bool { + pub(crate) fn push_res(&mut self, name: Name, def: &PerNs) -> bool { let mut changed = false; let existing = self.visible.entry(name.clone()).or_default(); - if existing.def.types.is_none() && res.def.types.is_some() { - existing.def.types = res.def.types; + if existing.types.is_none() && def.types.is_some() { + existing.types = def.types; changed = true; } - if existing.def.values.is_none() && res.def.values.is_some() { - existing.def.values = res.def.values; + if existing.values.is_none() && def.values.is_some() { + existing.values = def.values; changed = true; } - if existing.def.macros.is_none() && res.def.macros.is_some() { - existing.def.macros = res.def.macros; + if existing.macros.is_none() && def.macros.is_some() { + existing.macros = def.macros; changed = true; } changed } - pub(crate) fn collect_resolutions(&self) -> Vec<(Name, Resolution)> { + pub(crate) fn collect_resolutions(&self) -> Vec<(Name, PerNs)> { self.visible.iter().map(|(name, res)| (name.clone(), res.clone())).collect() } @@ -140,12 +138,6 @@ impl ItemScope { } } -#[derive(Debug, Clone, PartialEq, Eq, Default)] -pub struct Resolution { - /// None for unresolved - pub def: PerNs, -} - impl From for PerNs { fn from(def: ModuleDefId) -> PerNs { match def { diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index d27c3e1977..4f1fd48018 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -18,7 +18,6 @@ use test_utils::tested_by; use crate::{ attr::Attrs, db::DefDatabase, - item_scope::Resolution, nameres::{ diagnostics::DefDiagnostic, mod_resolution::ModDir, path_resolution::ReachedFixedPoint, raw, BuiltinShadowMode, CrateDefMap, ModuleData, ModuleOrigin, ResolveMode, @@ -215,7 +214,7 @@ where // In Rust, `#[macro_export]` macros are unconditionally visible at the // crate root, even if the parent modules is **not** visible. if export { - self.update(self.def_map.root, &[(name, Resolution { def: PerNs::macros(macro_) })]); + self.update(self.def_map.root, &[(name, PerNs::macros(macro_))]); } } @@ -397,8 +396,7 @@ where .map(|(local_id, variant_data)| { let name = variant_data.name.clone(); let variant = EnumVariantId { parent: e, local_id }; - let res = - Resolution { def: PerNs::both(variant.into(), variant.into()) }; + let res = PerNs::both(variant.into(), variant.into()); (name, res) }) .collect::>(); @@ -424,22 +422,21 @@ where } } - let resolution = Resolution { def }; - self.update(module_id, &[(name, resolution)]); + self.update(module_id, &[(name, def)]); } None => tested_by!(bogus_paths), } } } - fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, Resolution)]) { + fn update(&mut self, module_id: LocalModuleId, resolutions: &[(Name, PerNs)]) { self.update_recursive(module_id, resolutions, 0) } fn update_recursive( &mut self, module_id: LocalModuleId, - resolutions: &[(Name, Resolution)], + resolutions: &[(Name, PerNs)], depth: usize, ) { if depth > 100 { @@ -705,8 +702,7 @@ where let module = ModuleId { krate: self.def_collector.def_map.krate, local_id: res }; let def: ModuleDefId = module.into(); self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - let resolution = Resolution { def: def.into() }; - self.def_collector.update(self.module_id, &[(name, resolution)]); + self.def_collector.update(self.module_id, &[(name, def.into())]); res } @@ -765,8 +761,7 @@ where .into(), }; self.def_collector.def_map.modules[self.module_id].scope.define_def(def); - let resolution = Resolution { def: def.into() }; - self.def_collector.update(self.module_id, &[(name, resolution)]) + self.def_collector.update(self.module_id, &[(name, def.into())]) } fn collect_derives(&mut self, attrs: &Attrs, def: &raw::DefData) { diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 2dd779b66e..378d494555 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -181,7 +181,7 @@ impl CrateDefMap { // Since it is a qualified path here, it should not contains legacy macros match self[module.local_id].scope.get(&segment, prefer_module(i)) { - Some(res) => res.def, + Some(def) => *def, _ => { log::debug!("path segment {:?} not found", segment); return ResolvePathResult::empty(ReachedFixedPoint::No); @@ -243,8 +243,7 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = - self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def); + let from_scope = self[module].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name, shadow); @@ -258,7 +257,7 @@ impl CrateDefMap { shadow: BuiltinShadowMode, ) -> PerNs { let from_crate_root = - self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def); + self[self.root].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) @@ -279,10 +278,7 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id] - .scope - .get(name, shadow) - .map_or_else(PerNs::none, |res| res.def) + def_map[prelude.local_id].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none) } else { PerNs::none() } diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 4e968bcc84..ff474b53b0 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs @@ -35,19 +35,19 @@ fn render_crate_def_map(map: &CrateDefMap) -> String { let mut entries = map.modules[module].scope.collect_resolutions(); entries.sort_by_key(|(name, _)| name.clone()); - for (name, res) in entries { + for (name, def) in entries { *buf += &format!("{}:", name); - if res.def.types.is_some() { + if def.types.is_some() { *buf += " t"; } - if res.def.values.is_some() { + if def.values.is_some() { *buf += " v"; } - if res.def.macros.is_some() { + if def.macros.is_some() { *buf += " m"; } - if res.def.is_none() { + if def.is_none() { *buf += " _"; } diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index 83013fed3d..e70049617d 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -413,8 +413,8 @@ impl Scope { // def: m.module.into(), // }), // ); - m.crate_def_map[m.module_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), ScopeDef::PerNs(res.def)); + m.crate_def_map[m.module_id].scope.entries().for_each(|(name, def)| { + f(name.clone(), ScopeDef::PerNs(def)); }); m.crate_def_map[m.module_id].scope.legacy_macros().for_each(|(name, macro_)| { f(name.clone(), ScopeDef::PerNs(PerNs::macros(macro_))); @@ -424,8 +424,8 @@ impl Scope { }); if let Some(prelude) = m.crate_def_map.prelude { let prelude_def_map = db.crate_def_map(prelude.krate); - prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, res)| { - f(name.clone(), ScopeDef::PerNs(res.def)); + prelude_def_map[prelude.local_id].scope.entries().for_each(|(name, def)| { + f(name.clone(), ScopeDef::PerNs(def)); }); } } From baee74618524ad75819163d701ff9e6fe9883e95 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 15:49:39 +0100 Subject: [PATCH 304/312] Share impl Scope between modules and blocks --- crates/ra_hir_def/src/body.rs | 5 +- crates/ra_hir_def/src/body/lower.rs | 4 +- crates/ra_hir_def/src/child_by_source.rs | 102 ++++++++++++----------- 3 files changed, 57 insertions(+), 54 deletions(-) diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs index 148ff007ed..d3e4c50ae0 100644 --- a/crates/ra_hir_def/src/body.rs +++ b/crates/ra_hir_def/src/body.rs @@ -19,10 +19,11 @@ use crate::{ db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, item_scope::BuiltinShadowMode, + item_scope::ItemScope, nameres::CrateDefMap, path::{ModPath, Path}, src::HasSource, - DefWithBodyId, HasModule, Lookup, ModuleDefId, ModuleId, + DefWithBodyId, HasModule, Lookup, ModuleId, }; pub(crate) struct Expander { @@ -135,7 +136,7 @@ pub struct Body { pub params: Vec, /// The `ExprId` of the actual body expression. pub body_expr: ExprId, - pub defs: Vec, + pub item_scope: ItemScope, } pub type ExprPtr = Either, AstPtr>; diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index be5d17d85e..7549240505 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -46,7 +46,7 @@ pub(super) fn lower( pats: Arena::default(), params: Vec::new(), body_expr: ExprId::dummy(), - defs: Vec::new(), + item_scope: Default::default(), }, } .collect(params, body) @@ -532,7 +532,7 @@ where | ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::Module(_) => continue, }; - self.body.defs.push(def) + self.body.item_scope.define_def(def) } } diff --git a/crates/ra_hir_def/src/child_by_source.rs b/crates/ra_hir_def/src/child_by_source.rs index 4488e85020..8b6c773eeb 100644 --- a/crates/ra_hir_def/src/child_by_source.rs +++ b/crates/ra_hir_def/src/child_by_source.rs @@ -9,6 +9,7 @@ use either::Either; use crate::{ db::DefDatabase, dyn_map::DynMap, + item_scope::ItemScope, keys, src::{HasChildSource, HasSource}, AdtId, AssocItemId, DefWithBodyId, EnumId, EnumVariantId, ImplId, Lookup, ModuleDefId, @@ -73,59 +74,62 @@ impl ChildBySource for ImplId { impl ChildBySource for ModuleId { fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { - let mut res = DynMap::default(); - let crate_def_map = db.crate_def_map(self.krate); let module_data = &crate_def_map[self.local_id]; - - module_data.scope.declarations().for_each(|item| add_module_def(db, &mut res, item)); - - for imp in module_data.scope.impls() { - let src = imp.lookup(db).source(db); - res[keys::IMPL].insert(src, imp) - } - - res + module_data.scope.child_by_source(db) } } -fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) { - match item { - ModuleDefId::FunctionId(func) => { - let src = func.lookup(db).source(db); - map[keys::FUNCTION].insert(src, func) - } - ModuleDefId::ConstId(konst) => { - let src = konst.lookup(db).source(db); - map[keys::CONST].insert(src, konst) - } - ModuleDefId::StaticId(statik) => { - let src = statik.lookup(db).source(db); - map[keys::STATIC].insert(src, statik) - } - ModuleDefId::TypeAliasId(ty) => { - let src = ty.lookup(db).source(db); - map[keys::TYPE_ALIAS].insert(src, ty) - } - ModuleDefId::TraitId(trait_) => { - let src = trait_.lookup(db).source(db); - map[keys::TRAIT].insert(src, trait_) - } - ModuleDefId::AdtId(adt) => match adt { - AdtId::StructId(strukt) => { - let src = strukt.lookup(db).source(db); - map[keys::STRUCT].insert(src, strukt) +impl ChildBySource for ItemScope { + fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { + let mut res = DynMap::default(); + self.declarations().for_each(|item| add_module_def(db, &mut res, item)); + self.impls().for_each(|imp| add_impl(db, &mut res, imp)); + return res; + + fn add_module_def(db: &impl DefDatabase, map: &mut DynMap, item: ModuleDefId) { + match item { + ModuleDefId::FunctionId(func) => { + let src = func.lookup(db).source(db); + map[keys::FUNCTION].insert(src, func) + } + ModuleDefId::ConstId(konst) => { + let src = konst.lookup(db).source(db); + map[keys::CONST].insert(src, konst) + } + ModuleDefId::StaticId(statik) => { + let src = statik.lookup(db).source(db); + map[keys::STATIC].insert(src, statik) + } + ModuleDefId::TypeAliasId(ty) => { + let src = ty.lookup(db).source(db); + map[keys::TYPE_ALIAS].insert(src, ty) + } + ModuleDefId::TraitId(trait_) => { + let src = trait_.lookup(db).source(db); + map[keys::TRAIT].insert(src, trait_) + } + ModuleDefId::AdtId(adt) => match adt { + AdtId::StructId(strukt) => { + let src = strukt.lookup(db).source(db); + map[keys::STRUCT].insert(src, strukt) + } + AdtId::UnionId(union_) => { + let src = union_.lookup(db).source(db); + map[keys::UNION].insert(src, union_) + } + AdtId::EnumId(enum_) => { + let src = enum_.lookup(db).source(db); + map[keys::ENUM].insert(src, enum_) + } + }, + _ => (), } - AdtId::UnionId(union_) => { - let src = union_.lookup(db).source(db); - map[keys::UNION].insert(src, union_) - } - AdtId::EnumId(enum_) => { - let src = enum_.lookup(db).source(db); - map[keys::ENUM].insert(src, enum_) - } - }, - _ => (), + } + fn add_impl(db: &impl DefDatabase, map: &mut DynMap, imp: ImplId) { + let src = imp.lookup(db).source(db); + map[keys::IMPL].insert(src, imp) + } } } @@ -167,9 +171,7 @@ impl ChildBySource for EnumId { impl ChildBySource for DefWithBodyId { fn child_by_source(&self, db: &impl DefDatabase) -> DynMap { - let mut res = DynMap::default(); let body = db.body(*self); - body.defs.iter().copied().for_each(|item| add_module_def(db, &mut res, item)); - res + body.item_scope.child_by_source(db) } } From 007032f8504be1274972e4f23afaf0bc431d92d5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 19:31:01 +0100 Subject: [PATCH 305/312] Refactor --- crates/ra_hir_def/src/item_scope.rs | 12 +++++++----- crates/ra_hir_def/src/nameres/path_resolution.rs | 9 ++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index f1adc3b58c..08d788cc9c 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -70,18 +70,20 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option<&PerNs> { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option { match shadow { - BuiltinShadowMode::Module => self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)), + BuiltinShadowMode::Module => { + self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)).copied() + } BuiltinShadowMode::Other => { - let item = self.visible.get(name); + let item = self.visible.get(name).copied(); if let Some(def) = item { if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { - return BUILTIN_SCOPE.get(name).or(item); + return BUILTIN_SCOPE.get(name).copied().or(item); } } - item.or_else(|| BUILTIN_SCOPE.get(name)) + item.or_else(|| BUILTIN_SCOPE.get(name).copied()) } } } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 378d494555..9b85ae0181 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -181,7 +181,7 @@ impl CrateDefMap { // Since it is a qualified path here, it should not contains legacy macros match self[module.local_id].scope.get(&segment, prefer_module(i)) { - Some(def) => *def, + Some(def) => def, _ => { log::debug!("path segment {:?} not found", segment); return ResolvePathResult::empty(ReachedFixedPoint::No); @@ -243,7 +243,7 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = self[module].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); + let from_scope = self[module].scope.get(name, shadow).unwrap_or_else(PerNs::none); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name, shadow); @@ -256,8 +256,7 @@ impl CrateDefMap { name: &Name, shadow: BuiltinShadowMode, ) -> PerNs { - let from_crate_root = - self[self.root].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none); + let from_crate_root = self[self.root].scope.get(name, shadow).unwrap_or_else(PerNs::none); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) @@ -278,7 +277,7 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id].scope.get(name, shadow).copied().unwrap_or_else(PerNs::none) + def_map[prelude.local_id].scope.get(name, shadow).unwrap_or_else(PerNs::none) } else { PerNs::none() } From 7c405c01567e814f18ebf8bdc6aa1f8f694919f0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 19:32:35 +0100 Subject: [PATCH 306/312] Simplify --- crates/ra_hir_def/src/item_scope.rs | 19 +++++++++++++------ .../ra_hir_def/src/nameres/path_resolution.rs | 14 ++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index 08d788cc9c..e8ddcc3c27 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -70,20 +70,27 @@ impl ItemScope { } /// Get a name from current module scope, legacy macros are not included - pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> Option { + pub(crate) fn get(&self, name: &Name, shadow: BuiltinShadowMode) -> PerNs { match shadow { - BuiltinShadowMode::Module => { - self.visible.get(name).or_else(|| BUILTIN_SCOPE.get(name)).copied() - } + BuiltinShadowMode::Module => self + .visible + .get(name) + .or_else(|| BUILTIN_SCOPE.get(name)) + .copied() + .unwrap_or_else(PerNs::none), BuiltinShadowMode::Other => { let item = self.visible.get(name).copied(); if let Some(def) = item { if let Some(ModuleDefId::ModuleId(_)) = def.take_types() { - return BUILTIN_SCOPE.get(name).copied().or(item); + return BUILTIN_SCOPE + .get(name) + .copied() + .or(item) + .unwrap_or_else(PerNs::none); } } - item.or_else(|| BUILTIN_SCOPE.get(name).copied()) + item.or_else(|| BUILTIN_SCOPE.get(name).copied()).unwrap_or_else(PerNs::none) } } } diff --git a/crates/ra_hir_def/src/nameres/path_resolution.rs b/crates/ra_hir_def/src/nameres/path_resolution.rs index 9b85ae0181..695014c7bb 100644 --- a/crates/ra_hir_def/src/nameres/path_resolution.rs +++ b/crates/ra_hir_def/src/nameres/path_resolution.rs @@ -180,13 +180,7 @@ impl CrateDefMap { } // Since it is a qualified path here, it should not contains legacy macros - match self[module.local_id].scope.get(&segment, prefer_module(i)) { - Some(def) => def, - _ => { - log::debug!("path segment {:?} not found", segment); - return ResolvePathResult::empty(ReachedFixedPoint::No); - } - } + self[module.local_id].scope.get(&segment, prefer_module(i)) } ModuleDefId::AdtId(AdtId::EnumId(e)) => { // enum variant @@ -243,7 +237,7 @@ impl CrateDefMap { // - std prelude let from_legacy_macro = self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros); - let from_scope = self[module].scope.get(name, shadow).unwrap_or_else(PerNs::none); + let from_scope = self[module].scope.get(name, shadow); let from_extern_prelude = self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it)); let from_prelude = self.resolve_in_prelude(db, name, shadow); @@ -256,7 +250,7 @@ impl CrateDefMap { name: &Name, shadow: BuiltinShadowMode, ) -> PerNs { - let from_crate_root = self[self.root].scope.get(name, shadow).unwrap_or_else(PerNs::none); + let from_crate_root = self[self.root].scope.get(name, shadow); let from_extern_prelude = self.resolve_name_in_extern_prelude(name); from_crate_root.or(from_extern_prelude) @@ -277,7 +271,7 @@ impl CrateDefMap { keep = db.crate_def_map(prelude.krate); &keep }; - def_map[prelude.local_id].scope.get(name, shadow).unwrap_or_else(PerNs::none) + def_map[prelude.local_id].scope.get(name, shadow) } else { PerNs::none() } From e424545c0f5cbaf135c52764169ea20df7d07d35 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Dec 2019 20:12:23 +0100 Subject: [PATCH 307/312] Rudimentary name resolution for local items --- crates/ra_hir_def/src/body/lower.rs | 32 ++++-- crates/ra_hir_def/src/item_scope.rs | 8 +- crates/ra_hir_def/src/nameres/collector.rs | 2 +- crates/ra_hir_def/src/resolver.rs | 103 ++++++++++++------ crates/ra_hir_ty/src/tests/simple.rs | 12 +- .../ra_ide/src/completion/complete_scope.rs | 37 +++++++ 6 files changed, 145 insertions(+), 49 deletions(-) diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 7549240505..5323af0972 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs @@ -494,45 +494,57 @@ where fn collect_block_items(&mut self, block: &ast::Block) { let container = ContainerId::DefWithBodyId(self.def); for item in block.items() { - let def: ModuleDefId = match item { + let (def, name): (ModuleDefId, Option) = match item { ast::ModuleItem::FnDef(def) => { let ast_id = self.expander.ast_id(&def); - FunctionLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + FunctionLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::TypeAliasDef(def) => { let ast_id = self.expander.ast_id(&def); - TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + TypeAliasLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::ConstDef(def) => { let ast_id = self.expander.ast_id(&def); - ConstLoc { container: container.into(), ast_id }.intern(self.db).into() + ( + ConstLoc { container: container.into(), ast_id }.intern(self.db).into(), + def.name(), + ) } ast::ModuleItem::StaticDef(def) => { let ast_id = self.expander.ast_id(&def); - StaticLoc { container, ast_id }.intern(self.db).into() + (StaticLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::StructDef(def) => { let ast_id = self.expander.ast_id(&def); - StructLoc { container, ast_id }.intern(self.db).into() + (StructLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::EnumDef(def) => { let ast_id = self.expander.ast_id(&def); - EnumLoc { container, ast_id }.intern(self.db).into() + (EnumLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::UnionDef(def) => { let ast_id = self.expander.ast_id(&def); - UnionLoc { container, ast_id }.intern(self.db).into() + (UnionLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::TraitDef(def) => { let ast_id = self.expander.ast_id(&def); - TraitLoc { container, ast_id }.intern(self.db).into() + (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) } ast::ModuleItem::ImplBlock(_) | ast::ModuleItem::UseItem(_) | ast::ModuleItem::ExternCrateItem(_) | ast::ModuleItem::Module(_) => continue, }; - self.body.item_scope.define_def(def) + self.body.item_scope.define_def(def); + if let Some(name) = name { + self.body.item_scope.push_res(name.as_name(), def.into()); + } } } diff --git a/crates/ra_hir_def/src/item_scope.rs b/crates/ra_hir_def/src/item_scope.rs index e8ddcc3c27..b0288ee8db 100644 --- a/crates/ra_hir_def/src/item_scope.rs +++ b/crates/ra_hir_def/src/item_scope.rs @@ -51,6 +51,12 @@ impl ItemScope { self.visible.iter().chain(BUILTIN_SCOPE.iter()).map(|(n, def)| (n, *def)) } + pub fn entries_without_primitives<'a>( + &'a self, + ) -> impl Iterator + 'a { + self.visible.iter().map(|(n, def)| (n, *def)) + } + pub fn declarations(&self) -> impl Iterator + '_ { self.defs.iter().copied() } @@ -118,7 +124,7 @@ impl ItemScope { self.legacy_macros.insert(name, mac); } - pub(crate) fn push_res(&mut self, name: Name, def: &PerNs) -> bool { + pub(crate) fn push_res(&mut self, name: Name, def: PerNs) -> bool { let mut changed = false; let existing = self.visible.entry(name.clone()).or_default(); diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 4f1fd48018..b9f40d3dd9 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs @@ -446,7 +446,7 @@ where let scope = &mut self.def_map.modules[module_id].scope; let mut changed = false; for (name, res) in resolutions { - changed |= scope.push_res(name.clone(), res); + changed |= scope.push_res(name.clone(), *res); } if !changed { diff --git a/crates/ra_hir_def/src/resolver.rs b/crates/ra_hir_def/src/resolver.rs index e70049617d..cf3c33d788 100644 --- a/crates/ra_hir_def/src/resolver.rs +++ b/crates/ra_hir_def/src/resolver.rs @@ -10,6 +10,7 @@ use rustc_hash::FxHashSet; use crate::{ body::scope::{ExprScopes, ScopeId}, + body::Body, builtin_type::BuiltinType, db::DefDatabase, expr::{ExprId, PatId}, @@ -55,6 +56,8 @@ enum Scope { AdtScope(AdtId), /// Local bindings ExprScope(ExprScope), + /// Temporary hack to support local items. + LocalItemsScope(Arc), } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -149,7 +152,13 @@ impl Resolver { for scope in self.scopes.iter().rev() { match scope { Scope::ExprScope(_) => continue, - Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue, + Scope::GenericParams { .. } + | Scope::ImplBlockScope(_) + | Scope::LocalItemsScope(_) + if skip_to_mod => + { + continue + } Scope::GenericParams { params, def } => { if let Some(local_id) = params.find_by_name(first_name) { @@ -179,25 +188,35 @@ impl Resolver { &path, BuiltinShadowMode::Other, ); - let res = match module_def.take_types()? { - ModuleDefId::AdtId(it) => TypeNs::AdtId(it), - ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), - - ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), - ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), - - ModuleDefId::TraitId(it) => TypeNs::TraitId(it), - - ModuleDefId::FunctionId(_) - | ModuleDefId::ConstId(_) - | ModuleDefId::StaticId(_) - | ModuleDefId::ModuleId(_) => return None, - }; + let res = to_type_ns(module_def)?; return Some((res, idx)); } + Scope::LocalItemsScope(body) => { + let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); + if let Some(res) = to_type_ns(def) { + return Some((res, None)); + } + } } } - None + return None; + fn to_type_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_types()? { + ModuleDefId::AdtId(it) => TypeNs::AdtId(it), + ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it), + + ModuleDefId::TypeAliasId(it) => TypeNs::TypeAliasId(it), + ModuleDefId::BuiltinType(it) => TypeNs::BuiltinType(it), + + ModuleDefId::TraitId(it) => TypeNs::TraitId(it), + + ModuleDefId::FunctionId(_) + | ModuleDefId::ConstId(_) + | ModuleDefId::StaticId(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) + } } pub fn resolve_path_in_type_ns_fully( @@ -227,6 +246,7 @@ impl Resolver { | Scope::ExprScope(_) | Scope::GenericParams { .. } | Scope::ImplBlockScope(_) + | Scope::LocalItemsScope(_) if skip_to_mod => { continue @@ -276,20 +296,7 @@ impl Resolver { ); return match idx { None => { - let value = match module_def.take_values()? { - ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), - ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), - ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), - ModuleDefId::ConstId(it) => ValueNs::ConstId(it), - ModuleDefId::StaticId(it) => ValueNs::StaticId(it), - - ModuleDefId::AdtId(AdtId::EnumId(_)) - | ModuleDefId::AdtId(AdtId::UnionId(_)) - | ModuleDefId::TraitId(_) - | ModuleDefId::TypeAliasId(_) - | ModuleDefId::BuiltinType(_) - | ModuleDefId::ModuleId(_) => return None, - }; + let value = to_value_ns(module_def)?; Some(ResolveValueResult::ValueNs(value)) } Some(idx) => { @@ -309,9 +316,33 @@ impl Resolver { } }; } + Scope::LocalItemsScope(body) => { + let def = body.item_scope.get(first_name, BuiltinShadowMode::Other); + if let Some(res) = to_value_ns(def) { + return Some(ResolveValueResult::ValueNs(res)); + } + } } } - None + return None; + + fn to_value_ns(per_ns: PerNs) -> Option { + let res = match per_ns.take_values()? { + ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it), + ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it), + ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it), + ModuleDefId::ConstId(it) => ValueNs::ConstId(it), + ModuleDefId::StaticId(it) => ValueNs::StaticId(it), + + ModuleDefId::AdtId(AdtId::EnumId(_)) + | ModuleDefId::AdtId(AdtId::UnionId(_)) + | ModuleDefId::TraitId(_) + | ModuleDefId::TypeAliasId(_) + | ModuleDefId::BuiltinType(_) + | ModuleDefId::ModuleId(_) => return None, + }; + Some(res) + } } pub fn resolve_path_in_value_ns_fully( @@ -429,6 +460,11 @@ impl Scope { }); } } + Scope::LocalItemsScope(body) => { + body.item_scope.entries_without_primitives().for_each(|(name, def)| { + f(name.clone(), ScopeDef::PerNs(def)); + }) + } Scope::GenericParams { params, def } => { for (local_id, param) in params.types.iter() { f( @@ -464,6 +500,7 @@ pub fn resolver_for_scope( scope_id: Option, ) -> Resolver { let mut r = owner.resolver(db); + r = r.push_local_items_scope(db.body(owner)); let scopes = db.expr_scopes(owner); let scope_chain = scopes.scope_chain(scope_id).collect::>(); for scope in scope_chain.into_iter().rev() { @@ -499,6 +536,10 @@ impl Resolver { self.push_scope(Scope::ModuleScope(ModuleItemMap { crate_def_map, module_id })) } + fn push_local_items_scope(self, body: Arc) -> Resolver { + self.push_scope(Scope::LocalItemsScope(body)) + } + fn push_expr_scope( self, owner: DefWithBodyId, diff --git a/crates/ra_hir_ty/src/tests/simple.rs b/crates/ra_hir_ty/src/tests/simple.rs index 6fe647a5e3..3e5e163e34 100644 --- a/crates/ra_hir_ty/src/tests/simple.rs +++ b/crates/ra_hir_ty/src/tests/simple.rs @@ -1512,8 +1512,8 @@ fn test() { [49; 50) '0': u32 [80; 83) '101': u32 [95; 213) '{ ...NST; }': () - [138; 139) 'x': {unknown} - [142; 153) 'LOCAL_CONST': {unknown} + [138; 139) 'x': u32 + [142; 153) 'LOCAL_CONST': u32 [163; 164) 'z': u32 [167; 179) 'GLOBAL_CONST': u32 [189; 191) 'id': u32 @@ -1541,10 +1541,10 @@ fn test() { [29; 32) '101': u32 [70; 73) '101': u32 [85; 280) '{ ...MUT; }': () - [173; 174) 'x': {unknown} - [177; 189) 'LOCAL_STATIC': {unknown} - [199; 200) 'y': {unknown} - [203; 219) 'LOCAL_...IC_MUT': {unknown} + [173; 174) 'x': u32 + [177; 189) 'LOCAL_STATIC': u32 + [199; 200) 'y': u32 + [203; 219) 'LOCAL_...IC_MUT': u32 [229; 230) 'z': u32 [233; 246) 'GLOBAL_STATIC': u32 [256; 257) 'w': u32 diff --git a/crates/ra_ide/src/completion/complete_scope.rs b/crates/ra_ide/src/completion/complete_scope.rs index d5739b58a6..458d7525ec 100644 --- a/crates/ra_ide/src/completion/complete_scope.rs +++ b/crates/ra_ide/src/completion/complete_scope.rs @@ -873,4 +873,41 @@ mod tests { "### ); } + + #[test] + fn completes_local_item() { + assert_debug_snapshot!( + do_reference_completion( + " + //- /main.rs + fn main() { + return f<|>; + fn frobnicate() {} + } + " + ), + @r###" + [ + CompletionItem { + label: "frobnicate()", + source_range: [23; 24), + delete: [23; 24), + insert: "frobnicate()$0", + kind: Function, + lookup: "frobnicate", + detail: "fn frobnicate()", + }, + CompletionItem { + label: "main()", + source_range: [23; 24), + delete: [23; 24), + insert: "main()$0", + kind: Function, + lookup: "main", + detail: "fn main()", + }, + ] + "### + ) + } } From 67a2555f6d4c3914742fd42645ca043cf56f358b Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 14:29:33 +0100 Subject: [PATCH 308/312] Update Chalk, clean up Chalk integration a bit --- Cargo.lock | 56 ++++----- crates/ra_hir_ty/Cargo.toml | 7 +- crates/ra_hir_ty/src/db.rs | 35 ++---- crates/ra_hir_ty/src/traits.rs | 6 +- crates/ra_hir_ty/src/traits/chalk.rs | 180 +++++++++++++-------------- 5 files changed, 131 insertions(+), 153 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55afcda7bf..7b19a06dc5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -128,7 +128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chalk-derive" version = "0.1.0" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -138,27 +138,27 @@ dependencies = [ [[package]] name = "chalk-engine" version = "0.9.0" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ - "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chalk-ir" version = "0.1.0" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chalk-macros" version = "0.1.1" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -166,24 +166,24 @@ dependencies = [ [[package]] name = "chalk-rust-ir" version = "0.1.0" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", ] [[package]] name = "chalk-solve" version = "0.1.0" -source = "git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb#151949dece8117d180b5d197a7afa968c3ba14bb" +source = "git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5#ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" dependencies = [ - "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -995,9 +995,9 @@ name = "ra_hir_ty" version = "0.1.0" dependencies = [ "arrayvec 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", - "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)", + "chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", + "chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)", "ena 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-intern 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1782,12 +1782,12 @@ dependencies = [ "checksum cargo_metadata 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46e3374c604fb39d1a2f35ed5e4a4e30e60d01fab49446e08f1b3e9a90aef202" "checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" -"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" -"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" -"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" -"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" -"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=151949dece8117d180b5d197a7afa968c3ba14bb)" = "" +"checksum chalk-derive 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" +"checksum chalk-engine 0.9.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" +"checksum chalk-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" +"checksum chalk-macros 0.1.1 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" +"checksum chalk-rust-ir 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" +"checksum chalk-solve 0.1.0 (git+https://github.com/rust-lang/chalk.git?rev=ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5)" = "" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index d277bf2bcd..60793db442 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml @@ -21,10 +21,9 @@ ra_prof = { path = "../ra_prof" } ra_syntax = { path = "../ra_syntax" } test_utils = { path = "../test_utils" } -# https://github.com/rust-lang/chalk/pull/294 -chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } -chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } -chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "151949dece8117d180b5d197a7afa968c3ba14bb" } +chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } +chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } +chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "ff65b5ac9860f3c36bd892c865ab23d5ff0bbae5" } lalrpop-intern = "0.15.1" diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 222a36a9f8..d52f65b836 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs @@ -10,7 +10,7 @@ use ra_db::{salsa, CrateId}; use crate::{ method_resolution::CrateImplBlocks, - traits::{AssocTyValue, Impl}, + traits::{chalk, AssocTyValue, Impl}, CallableDef, FnSig, GenericPredicate, InferenceResult, Substs, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, }; @@ -77,39 +77,24 @@ pub trait HirDatabase: DefDatabase { #[salsa::interned] fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> crate::traits::AssocTyValueId; - #[salsa::invoke(crate::traits::chalk::associated_ty_data_query)] - fn associated_ty_data( - &self, - id: chalk_ir::TypeId, - ) -> Arc>; + #[salsa::invoke(chalk::associated_ty_data_query)] + fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc; - #[salsa::invoke(crate::traits::chalk::trait_datum_query)] - fn trait_datum( - &self, - krate: CrateId, - trait_id: chalk_ir::TraitId, - ) -> Arc>; + #[salsa::invoke(chalk::trait_datum_query)] + fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc; - #[salsa::invoke(crate::traits::chalk::struct_datum_query)] - fn struct_datum( - &self, - krate: CrateId, - struct_id: chalk_ir::StructId, - ) -> Arc>; + #[salsa::invoke(chalk::struct_datum_query)] + fn struct_datum(&self, krate: CrateId, struct_id: chalk::StructId) -> Arc; #[salsa::invoke(crate::traits::chalk::impl_datum_query)] - fn impl_datum( - &self, - krate: CrateId, - impl_id: chalk_ir::ImplId, - ) -> Arc>; + fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc; #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] fn associated_ty_value( &self, krate: CrateId, - id: chalk_rust_ir::AssociatedTyValueId, - ) -> Arc>; + id: chalk::AssociatedTyValueId, + ) -> Arc; #[salsa::invoke(crate::traits::trait_solve_query)] fn trait_solve( diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index d49f8fb4b1..46e17f0b8d 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs @@ -209,9 +209,9 @@ fn solution_from_chalk( .parameters .into_iter() .map(|p| { - let ty = match p { - chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), - chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), + let ty = match p.ty() { + Some(ty) => from_chalk(db, ty.clone()), + None => unimplemented!(), }; ty }) diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 5eb032d86a..3a91a374d8 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -3,15 +3,9 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{ - cast::Cast, family::ChalkIr, Identifier, Parameter, PlaceholderIndex, TypeId, TypeKindId, - TypeName, UniverseIndex, -}; -use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; +use chalk_ir::{cast::Cast, family::ChalkIr, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; -use hir_def::{ - AssocContainerId, AssocItemId, GenericDefId, HasModule, ImplId, Lookup, TraitId, TypeAliasId, -}; +use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; use ra_db::{ salsa::{InternId, InternKey}, CrateId, @@ -23,9 +17,20 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; +pub type TypeFamily = chalk_ir::family::ChalkIr; // TODO use everywhere +pub type AssocTypeId = chalk_ir::AssocTypeId; +pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; +pub type TraitId = chalk_ir::TraitId; +pub type TraitDatum = chalk_rust_ir::TraitDatum; +pub type StructId = chalk_ir::StructId; +pub type StructDatum = chalk_rust_ir::StructDatum; +pub type ImplId = chalk_ir::ImplId; +pub type ImplDatum = chalk_rust_ir::ImplDatum; +pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; +pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue; + /// This represents a trait whose name we could not resolve. -const UNKNOWN_TRAIT: chalk_ir::TraitId = - chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); +const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); pub(super) trait ToChalk { type Chalk; @@ -53,7 +58,7 @@ impl ToChalk for Ty { _ => { // other TypeCtors get interned and turned into a chalk StructId let struct_id = apply_ty.ctor.to_chalk(db); - TypeName::TypeKindId(struct_id.into()) + TypeName::Struct(struct_id.into()) } }; let parameters = apply_ty.parameters.to_chalk(db); @@ -71,11 +76,13 @@ impl ToChalk for Ty { Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), Ty::Dyn(predicates) => { let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); - chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() + let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; + chalk_ir::TyData::Dyn(bounded_ty).intern() } Ty::Opaque(predicates) => { let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); - chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() + let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; + chalk_ir::TyData::Opaque(bounded_ty).intern() } Ty::Unknown => { let parameters = Vec::new(); @@ -87,10 +94,9 @@ impl ToChalk for Ty { fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk.data().clone() { chalk_ir::TyData::Apply(apply_ty) => { - // FIXME this is kind of hacky due to the fact that - // TypeName::Placeholder is a Ty::Param on our side + // TODO clean this up now that Placeholder isn't in TypeName anymore match apply_ty.name { - TypeName::TypeKindId(TypeKindId::StructId(struct_id)) => { + TypeName::Struct(struct_id) => { let ctor = from_chalk(db, struct_id); let parameters = from_chalk(db, apply_ty.parameters); Ty::Apply(ApplicationTy { ctor, parameters }) @@ -101,14 +107,12 @@ impl ToChalk for Ty { Ty::Apply(ApplicationTy { ctor, parameters }) } TypeName::Error => Ty::Unknown, - // FIXME handle TypeKindId::Trait/Type here - TypeName::TypeKindId(_) => unimplemented!(), - TypeName::Placeholder(idx) => { - assert_eq!(idx.ui, UniverseIndex::ROOT); - Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } - } } } + chalk_ir::TyData::Placeholder(idx) => { + assert_eq!(idx.ui, UniverseIndex::ROOT); + Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } + } chalk_ir::TyData::Projection(proj) => { let associated_ty = from_chalk(db, proj.associated_ty_id); let parameters = from_chalk(db, proj.parameters); @@ -118,15 +122,15 @@ impl ToChalk for Ty { chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, chalk_ir::TyData::Dyn(where_clauses) => { - assert_eq!(where_clauses.binders.len(), 1); + assert_eq!(where_clauses.bounds.binders.len(), 1); let predicates = - where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); + where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); Ty::Dyn(predicates) } chalk_ir::TyData::Opaque(where_clauses) => { - assert_eq!(where_clauses.binders.len(), 1); + assert_eq!(where_clauses.bounds.binders.len(), 1); let predicates = - where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); + where_clauses.bounds.value.into_iter().map(|c| from_chalk(db, c)).collect(); Ty::Opaque(predicates) } } @@ -143,9 +147,9 @@ impl ToChalk for Substs { fn from_chalk(db: &impl HirDatabase, parameters: Vec>) -> Substs { let tys = parameters .into_iter() - .map(|p| match p { - chalk_ir::Parameter(chalk_ir::ParameterKind::Ty(ty)) => from_chalk(db, ty), - chalk_ir::Parameter(chalk_ir::ParameterKind::Lifetime(_)) => unimplemented!(), + .map(|p| match p.ty() { + Some(ty) => from_chalk(db, ty.clone()), + None => unimplemented!(), }) .collect(); Substs(tys) @@ -168,65 +172,62 @@ impl ToChalk for TraitRef { } } -impl ToChalk for TraitId { - type Chalk = chalk_ir::TraitId; +impl ToChalk for hir_def::TraitId { + type Chalk = TraitId; - fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TraitId { + fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { chalk_ir::TraitId(id_to_chalk(self)) } - fn from_chalk(_db: &impl HirDatabase, trait_id: chalk_ir::TraitId) -> TraitId { + fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { id_from_chalk(trait_id.0) } } impl ToChalk for TypeCtor { - type Chalk = chalk_ir::StructId; + type Chalk = StructId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::StructId { + fn to_chalk(self, db: &impl HirDatabase) -> StructId { db.intern_type_ctor(self).into() } - fn from_chalk(db: &impl HirDatabase, struct_id: chalk_ir::StructId) -> TypeCtor { + fn from_chalk(db: &impl HirDatabase, struct_id: StructId) -> TypeCtor { db.lookup_intern_type_ctor(struct_id.into()) } } impl ToChalk for Impl { - type Chalk = chalk_ir::ImplId; + type Chalk = ImplId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ImplId { + fn to_chalk(self, db: &impl HirDatabase) -> ImplId { db.intern_chalk_impl(self).into() } - fn from_chalk(db: &impl HirDatabase, impl_id: chalk_ir::ImplId) -> Impl { + fn from_chalk(db: &impl HirDatabase, impl_id: ImplId) -> Impl { db.lookup_intern_chalk_impl(impl_id.into()) } } impl ToChalk for TypeAliasId { - type Chalk = chalk_ir::TypeId; + type Chalk = AssocTypeId; - fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { - chalk_ir::TypeId(id_to_chalk(self)) + fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { + chalk_ir::AssocTypeId(id_to_chalk(self)) } - fn from_chalk(_db: &impl HirDatabase, type_alias_id: chalk_ir::TypeId) -> TypeAliasId { + fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { id_from_chalk(type_alias_id.0) } } impl ToChalk for AssocTyValue { - type Chalk = chalk_rust_ir::AssociatedTyValueId; + type Chalk = AssociatedTyValueId; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { + fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValueId { db.intern_assoc_ty_value(self).into() } - fn from_chalk( - db: &impl HirDatabase, - assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, - ) -> AssocTyValue { + fn from_chalk(db: &impl HirDatabase, assoc_ty_value_id: AssociatedTyValueId) -> AssocTyValue { db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) } } @@ -468,28 +469,28 @@ impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> where DB: HirDatabase, { - fn associated_ty_data(&self, id: TypeId) -> Arc> { + fn associated_ty_data(&self, id: AssocTypeId) -> Arc { self.db.associated_ty_data(id) } - fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc> { + fn trait_datum(&self, trait_id: TraitId) -> Arc { self.db.trait_datum(self.krate, trait_id) } - fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc> { + fn struct_datum(&self, struct_id: StructId) -> Arc { self.db.struct_datum(self.krate, struct_id) } - fn impl_datum(&self, impl_id: chalk_ir::ImplId) -> Arc> { + fn impl_datum(&self, impl_id: ImplId) -> Arc { self.db.impl_datum(self.krate, impl_id) } fn impls_for_trait( &self, - trait_id: chalk_ir::TraitId, - parameters: &[Parameter], - ) -> Vec { + trait_id: TraitId, + parameters: &[Parameter], + ) -> Vec { debug!("impls_for_trait {:?}", trait_id); if trait_id == UNKNOWN_TRAIT { return Vec::new(); } - let trait_: TraitId = from_chalk(self.db, trait_id); + let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); let mut result: Vec<_> = self .db .impls_for_trait(self.krate, trait_.into()) @@ -508,39 +509,32 @@ where debug!("impls_for_trait returned {} impls", result.len()); result } - fn impl_provided_for( - &self, - auto_trait_id: chalk_ir::TraitId, - struct_id: chalk_ir::StructId, - ) -> bool { + fn impl_provided_for(&self, auto_trait_id: TraitId, struct_id: StructId) -> bool { debug!("impl_provided_for {:?}, {:?}", auto_trait_id, struct_id); false // FIXME } - fn type_name(&self, _id: TypeKindId) -> Identifier { - unimplemented!() - } - fn associated_ty_value( - &self, - id: chalk_rust_ir::AssociatedTyValueId, - ) -> Arc> { + fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate.into(), id) } fn custom_clauses(&self) -> Vec> { vec![] } - fn local_impls_to_coherence_check( - &self, - _trait_id: chalk_ir::TraitId, - ) -> Vec { + fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { // We don't do coherence checking (yet) unimplemented!() } + fn as_struct_id(&self, id: &TypeName) -> Option { + match id { + TypeName::Struct(struct_id) => Some(*struct_id), + _ => None, + } + } } pub(crate) fn associated_ty_data_query( db: &impl HirDatabase, - id: TypeId, -) -> Arc> { + id: AssocTypeId, +) -> Arc { debug!("associated_ty_data {:?}", id); let type_alias: TypeAliasId = from_chalk(db, id); let trait_ = match type_alias.lookup(db).container { @@ -565,8 +559,8 @@ pub(crate) fn associated_ty_data_query( pub(crate) fn trait_datum_query( db: &impl HirDatabase, krate: CrateId, - trait_id: chalk_ir::TraitId, -) -> Arc> { + trait_id: TraitId, +) -> Arc { debug!("trait_datum {:?}", trait_id); if trait_id == UNKNOWN_TRAIT { let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; @@ -586,7 +580,7 @@ pub(crate) fn trait_datum_query( associated_ty_ids: vec![], }); } - let trait_: TraitId = from_chalk(db, trait_id); + let trait_: hir_def::TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); let generic_params = generics(db, trait_.into()); @@ -616,8 +610,8 @@ pub(crate) fn trait_datum_query( pub(crate) fn struct_datum_query( db: &impl HirDatabase, krate: CrateId, - struct_id: chalk_ir::StructId, -) -> Arc> { + struct_id: StructId, +) -> Arc { debug!("struct_datum {:?}", struct_id); let type_ctor: TypeCtor = from_chalk(db, struct_id); debug!("struct {:?} = {:?}", struct_id, type_ctor); @@ -648,8 +642,8 @@ pub(crate) fn struct_datum_query( pub(crate) fn impl_datum_query( db: &impl HirDatabase, krate: CrateId, - impl_id: chalk_ir::ImplId, -) -> Arc> { + impl_id: ImplId, +) -> Arc { let _p = ra_prof::profile("impl_datum"); debug!("impl_datum {:?}", impl_id); let impl_: Impl = from_chalk(db, impl_id); @@ -663,9 +657,9 @@ pub(crate) fn impl_datum_query( fn impl_block_datum( db: &impl HirDatabase, krate: CrateId, - chalk_id: chalk_ir::ImplId, - impl_id: ImplId, -) -> Option>> { + chalk_id: ImplId, + impl_id: hir_def::ImplId, +) -> Option> { let trait_ref = db.impl_trait(impl_id)?; let impl_data = db.impl_data(impl_id); @@ -721,7 +715,7 @@ fn impl_block_datum( Some(Arc::new(impl_datum)) } -fn invalid_impl_datum() -> Arc> { +fn invalid_impl_datum() -> Arc { let trait_ref = chalk_ir::TraitRef { trait_id: UNKNOWN_TRAIT, parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], @@ -754,7 +748,7 @@ fn type_alias_associated_ty_value( db: &impl HirDatabase, _krate: CrateId, type_alias: TypeAliasId, -) -> Arc> { +) -> Arc { let type_alias_data = db.type_alias_data(type_alias); let impl_id = match type_alias.lookup(db).container { AssocContainerId::ImplId(it) => it, @@ -786,25 +780,25 @@ fn id_to_chalk(salsa_id: T) -> chalk_ir::RawId { chalk_ir::RawId { index: salsa_id.as_intern_id().as_u32() } } -impl From for crate::TypeCtorId { - fn from(struct_id: chalk_ir::StructId) -> Self { +impl From for crate::TypeCtorId { + fn from(struct_id: StructId) -> Self { id_from_chalk(struct_id.0) } } -impl From for chalk_ir::StructId { +impl From for StructId { fn from(type_ctor_id: crate::TypeCtorId) -> Self { chalk_ir::StructId(id_to_chalk(type_ctor_id)) } } -impl From for crate::traits::GlobalImplId { - fn from(impl_id: chalk_ir::ImplId) -> Self { +impl From for crate::traits::GlobalImplId { + fn from(impl_id: ImplId) -> Self { id_from_chalk(impl_id.0) } } -impl From for chalk_ir::ImplId { +impl From for ImplId { fn from(impl_id: crate::traits::GlobalImplId) -> Self { chalk_ir::ImplId(id_to_chalk(impl_id)) } From 6b5efe5bdab160278469417734f4bb619c7bac61 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 14:46:15 +0100 Subject: [PATCH 309/312] Refactor Chalk integration some more --- crates/ra_hir_ty/src/traits.rs | 14 +-- crates/ra_hir_ty/src/traits/chalk.rs | 148 ++++++++++++++------------- 2 files changed, 83 insertions(+), 79 deletions(-) diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 46e17f0b8d..fbab609251 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs @@ -1,7 +1,7 @@ //! Trait solving using Chalk. use std::sync::{Arc, Mutex}; -use chalk_ir::{cast::Cast, family::ChalkIr}; +use chalk_ir::cast::Cast; use hir_def::{expr::ExprId, DefWithBodyId, ImplId, TraitId, TypeAliasId}; use log::debug; use ra_db::{impl_intern_key, salsa, CrateId}; @@ -12,7 +12,7 @@ use crate::db::HirDatabase; use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; -use self::chalk::{from_chalk, ToChalk}; +use self::chalk::{from_chalk, ToChalk, TypeFamily}; pub(crate) mod chalk; mod builtin; @@ -20,7 +20,7 @@ mod builtin; #[derive(Debug, Clone)] pub struct TraitSolver { krate: CrateId, - inner: Arc>>, + inner: Arc>>, } /// We need eq for salsa @@ -36,8 +36,8 @@ impl TraitSolver { fn solve( &self, db: &impl HirDatabase, - goal: &chalk_ir::UCanonical>>, - ) -> Option> { + goal: &chalk_ir::UCanonical>>, + ) -> Option> { let context = ChalkContext { db, krate: self.krate }; debug!("solve goal: {:?}", goal); let mut solver = match self.inner.lock() { @@ -201,9 +201,9 @@ pub(crate) fn trait_solve_query( fn solution_from_chalk( db: &impl HirDatabase, - solution: chalk_solve::Solution, + solution: chalk_solve::Solution, ) -> Solution { - let convert_subst = |subst: chalk_ir::Canonical>| { + let convert_subst = |subst: chalk_ir::Canonical>| { let value = subst .value .parameters diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 3a91a374d8..d53d3fdebd 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use log::debug; -use chalk_ir::{cast::Cast, family::ChalkIr, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; +use chalk_ir::{cast::Cast, Parameter, PlaceholderIndex, TypeName, UniverseIndex}; use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; use ra_db::{ @@ -17,7 +17,7 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; -pub type TypeFamily = chalk_ir::family::ChalkIr; // TODO use everywhere +pub type TypeFamily = chalk_ir::family::ChalkIr; pub type AssocTypeId = chalk_ir::AssocTypeId; pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; pub type TraitId = chalk_ir::TraitId; @@ -46,21 +46,11 @@ where } impl ToChalk for Ty { - type Chalk = chalk_ir::Ty; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { + type Chalk = chalk_ir::Ty; + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Ty { match self { Ty::Apply(apply_ty) => { - let name = match apply_ty.ctor { - TypeCtor::AssociatedType(type_alias) => { - let type_id = type_alias.to_chalk(db); - TypeName::AssociatedType(type_id) - } - _ => { - // other TypeCtors get interned and turned into a chalk StructId - let struct_id = apply_ty.ctor.to_chalk(db); - TypeName::Struct(struct_id.into()) - } - }; + let name = apply_ty.ctor.to_chalk(db); let parameters = apply_ty.parameters.to_chalk(db); chalk_ir::ApplicationTy { name, parameters }.cast().intern() } @@ -70,7 +60,8 @@ impl ToChalk for Ty { chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() } Ty::Param { idx, .. } => { - PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::() + PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize } + .to_ty::() } Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), @@ -91,24 +82,16 @@ impl ToChalk for Ty { } } } - fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { + fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty) -> Self { match chalk.data().clone() { - chalk_ir::TyData::Apply(apply_ty) => { - // TODO clean this up now that Placeholder isn't in TypeName anymore - match apply_ty.name { - TypeName::Struct(struct_id) => { - let ctor = from_chalk(db, struct_id); - let parameters = from_chalk(db, apply_ty.parameters); - Ty::Apply(ApplicationTy { ctor, parameters }) - } - TypeName::AssociatedType(type_id) => { - let ctor = TypeCtor::AssociatedType(from_chalk(db, type_id)); - let parameters = from_chalk(db, apply_ty.parameters); - Ty::Apply(ApplicationTy { ctor, parameters }) - } - TypeName::Error => Ty::Unknown, + chalk_ir::TyData::Apply(apply_ty) => match apply_ty.name { + TypeName::Error => Ty::Unknown, + _ => { + let ctor = from_chalk(db, apply_ty.name); + let parameters = from_chalk(db, apply_ty.parameters); + Ty::Apply(ApplicationTy { ctor, parameters }) } - } + }, chalk_ir::TyData::Placeholder(idx) => { assert_eq!(idx.ui, UniverseIndex::ROOT); Ty::Param { idx: idx.idx as u32, name: crate::Name::missing() } @@ -138,13 +121,16 @@ impl ToChalk for Ty { } impl ToChalk for Substs { - type Chalk = Vec>; + type Chalk = Vec>; - fn to_chalk(self, db: &impl HirDatabase) -> Vec> { + fn to_chalk(self, db: &impl HirDatabase) -> Vec> { self.iter().map(|ty| ty.clone().to_chalk(db).cast()).collect() } - fn from_chalk(db: &impl HirDatabase, parameters: Vec>) -> Substs { + fn from_chalk( + db: &impl HirDatabase, + parameters: Vec>, + ) -> Substs { let tys = parameters .into_iter() .map(|p| match p.ty() { @@ -157,15 +143,15 @@ impl ToChalk for Substs { } impl ToChalk for TraitRef { - type Chalk = chalk_ir::TraitRef; + type Chalk = chalk_ir::TraitRef; - fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { + fn to_chalk(self: TraitRef, db: &impl HirDatabase) -> chalk_ir::TraitRef { let trait_id = self.trait_.to_chalk(db); let parameters = self.substs.to_chalk(db); chalk_ir::TraitRef { trait_id, parameters } } - fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { + fn from_chalk(db: &impl HirDatabase, trait_ref: chalk_ir::TraitRef) -> Self { let trait_ = from_chalk(db, trait_ref.trait_id); let substs = from_chalk(db, trait_ref.parameters); TraitRef { trait_, substs } @@ -185,14 +171,31 @@ impl ToChalk for hir_def::TraitId { } impl ToChalk for TypeCtor { - type Chalk = StructId; + type Chalk = TypeName; - fn to_chalk(self, db: &impl HirDatabase) -> StructId { - db.intern_type_ctor(self).into() + fn to_chalk(self, db: &impl HirDatabase) -> TypeName { + match self { + TypeCtor::AssociatedType(type_alias) => { + let type_id = type_alias.to_chalk(db); + TypeName::AssociatedType(type_id) + } + _ => { + // other TypeCtors get interned and turned into a chalk StructId + let struct_id = db.intern_type_ctor(self).into(); + TypeName::Struct(struct_id) + } + } } - fn from_chalk(db: &impl HirDatabase, struct_id: StructId) -> TypeCtor { - db.lookup_intern_type_ctor(struct_id.into()) + fn from_chalk(db: &impl HirDatabase, type_name: TypeName) -> TypeCtor { + match type_name { + TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), + TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), + TypeName::Error => { + // this should not be reached, since we don't represent TypeName::Error with TypeCtor + unreachable!() + } + } } } @@ -233,9 +236,9 @@ impl ToChalk for AssocTyValue { } impl ToChalk for GenericPredicate { - type Chalk = chalk_ir::QuantifiedWhereClause; + type Chalk = chalk_ir::QuantifiedWhereClause; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::QuantifiedWhereClause { match self { GenericPredicate::Implemented(trait_ref) => { make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) @@ -259,7 +262,7 @@ impl ToChalk for GenericPredicate { fn from_chalk( db: &impl HirDatabase, - where_clause: chalk_ir::QuantifiedWhereClause, + where_clause: chalk_ir::QuantifiedWhereClause, ) -> GenericPredicate { match where_clause.value { chalk_ir::WhereClause::Implemented(tr) => { @@ -279,9 +282,9 @@ impl ToChalk for GenericPredicate { } impl ToChalk for ProjectionTy { - type Chalk = chalk_ir::ProjectionTy; + type Chalk = chalk_ir::ProjectionTy; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { chalk_ir::ProjectionTy { associated_ty_id: self.associated_ty.to_chalk(db), parameters: self.parameters.to_chalk(db), @@ -290,7 +293,7 @@ impl ToChalk for ProjectionTy { fn from_chalk( db: &impl HirDatabase, - projection_ty: chalk_ir::ProjectionTy, + projection_ty: chalk_ir::ProjectionTy, ) -> ProjectionTy { ProjectionTy { associated_ty: from_chalk(db, projection_ty.associated_ty_id), @@ -300,31 +303,31 @@ impl ToChalk for ProjectionTy { } impl ToChalk for super::ProjectionPredicate { - type Chalk = chalk_ir::Normalize; + type Chalk = chalk_ir::Normalize; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Normalize { chalk_ir::Normalize { projection: self.projection_ty.to_chalk(db), ty: self.ty.to_chalk(db), } } - fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { + fn from_chalk(_db: &impl HirDatabase, _normalize: chalk_ir::Normalize) -> Self { unimplemented!() } } impl ToChalk for Obligation { - type Chalk = chalk_ir::DomainGoal; + type Chalk = chalk_ir::DomainGoal; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::DomainGoal { match self { Obligation::Trait(tr) => tr.to_chalk(db).cast(), Obligation::Projection(pr) => pr.to_chalk(db).cast(), } } - fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { + fn from_chalk(_db: &impl HirDatabase, _goal: chalk_ir::DomainGoal) -> Self { unimplemented!() } } @@ -348,16 +351,17 @@ where } impl ToChalk for Arc { - type Chalk = chalk_ir::Environment; + type Chalk = chalk_ir::Environment; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment { + fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::Environment { let mut clauses = Vec::new(); for pred in &self.predicates { if pred.is_error() { // for env, we just ignore errors continue; } - let program_clause: chalk_ir::ProgramClause = pred.clone().to_chalk(db).cast(); + let program_clause: chalk_ir::ProgramClause = + pred.clone().to_chalk(db).cast(); clauses.push(program_clause.into_from_env_clause()); } chalk_ir::Environment::new().add_clauses(clauses) @@ -365,7 +369,7 @@ impl ToChalk for Arc { fn from_chalk( _db: &impl HirDatabase, - _env: chalk_ir::Environment, + _env: chalk_ir::Environment, ) -> Arc { unimplemented!() } @@ -373,7 +377,7 @@ impl ToChalk for Arc { impl ToChalk for super::InEnvironment where - T::Chalk: chalk_ir::family::HasTypeFamily, + T::Chalk: chalk_ir::family::HasTypeFamily, { type Chalk = chalk_ir::InEnvironment; @@ -396,9 +400,9 @@ where } impl ToChalk for builtin::BuiltinImplData { - type Chalk = chalk_rust_ir::ImplDatum; + type Chalk = ImplDatum; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::ImplDatum { + fn to_chalk(self, db: &impl HirDatabase) -> ImplDatum { let impl_type = chalk_rust_ir::ImplType::External; let where_clauses = self.where_clauses.into_iter().map(|w| w.to_chalk(db)).collect(); @@ -414,15 +418,15 @@ impl ToChalk for builtin::BuiltinImplData { } } - fn from_chalk(_db: &impl HirDatabase, _data: chalk_rust_ir::ImplDatum) -> Self { + fn from_chalk(_db: &impl HirDatabase, _data: ImplDatum) -> Self { unimplemented!() } } impl ToChalk for builtin::BuiltinImplAssocTyValueData { - type Chalk = chalk_rust_ir::AssociatedTyValue; + type Chalk = AssociatedTyValue; - fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValue { + fn to_chalk(self, db: &impl HirDatabase) -> AssociatedTyValue { let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: self.value.to_chalk(db) }; chalk_rust_ir::AssociatedTyValue { @@ -434,7 +438,7 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData { fn from_chalk( _db: &impl HirDatabase, - _data: chalk_rust_ir::AssociatedTyValue, + _data: AssociatedTyValue, ) -> builtin::BuiltinImplAssocTyValueData { unimplemented!() } @@ -451,7 +455,7 @@ fn convert_where_clauses( db: &impl HirDatabase, def: GenericDefId, substs: &Substs, -) -> Vec> { +) -> Vec> { let generic_predicates = db.generic_predicates(def); let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { @@ -465,7 +469,7 @@ fn convert_where_clauses( result } -impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> +impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> where DB: HirDatabase, { @@ -516,7 +520,7 @@ where fn associated_ty_value(&self, id: AssociatedTyValueId) -> Arc { self.db.associated_ty_value(self.krate.into(), id) } - fn custom_clauses(&self) -> Vec> { + fn custom_clauses(&self) -> Vec> { vec![] } fn local_impls_to_coherence_check(&self, _trait_id: TraitId) -> Vec { @@ -613,7 +617,7 @@ pub(crate) fn struct_datum_query( struct_id: StructId, ) -> Arc { debug!("struct_datum {:?}", struct_id); - let type_ctor: TypeCtor = from_chalk(db, struct_id); + let type_ctor: TypeCtor = from_chalk(db, TypeName::Struct(struct_id)); debug!("struct {:?} = {:?}", struct_id, type_ctor); let num_params = type_ctor.num_ty_params(db); let upstream = type_ctor.krate(db) != Some(krate); @@ -733,8 +737,8 @@ fn invalid_impl_datum() -> Arc { pub(crate) fn associated_ty_value_query( db: &impl HirDatabase, krate: CrateId, - id: chalk_rust_ir::AssociatedTyValueId, -) -> Arc> { + id: AssociatedTyValueId, +) -> Arc { let data: AssocTyValue = from_chalk(db, id); match data { AssocTyValue::TypeAlias(type_alias) => { From 4053fcfca0e33f133c53fa755c1b1bcc0b4c11bb Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 15:00:44 +0100 Subject: [PATCH 310/312] Introduce our own Chalk TypeFamily, instead of using ChalkIr It's not very different, except we can directly use Salsa IDs instead of casting them. This means we need to refactor the handling of errors to get rid of UNKNOWN_TRAIT though. --- .../ra_hir_ty/src/tests/method_resolution.rs | 4 +- crates/ra_hir_ty/src/traits.rs | 4 +- crates/ra_hir_ty/src/traits/builtin.rs | 49 ++++-- crates/ra_hir_ty/src/traits/chalk.rs | 156 ++++++++++-------- 4 files changed, 126 insertions(+), 87 deletions(-) diff --git a/crates/ra_hir_ty/src/tests/method_resolution.rs b/crates/ra_hir_ty/src/tests/method_resolution.rs index 45164c9e96..ce9a06fde4 100644 --- a/crates/ra_hir_ty/src/tests/method_resolution.rs +++ b/crates/ra_hir_ty/src/tests/method_resolution.rs @@ -865,7 +865,7 @@ mod foo { #[test] fn method_resolution_where_clause_for_unknown_trait() { - // The blanket impl shouldn't apply because we can't even resolve UnknownTrait + // The blanket impl currently applies because we ignore the unresolved where clause let t = type_at( r#" //- /main.rs @@ -875,7 +875,7 @@ impl Trait for T where T: UnknownTrait {} fn test() { (&S).foo()<|>; } "#, ); - assert_eq!(t, "{unknown}"); + assert_eq!(t, "u128"); } #[test] diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index fbab609251..c4dc857bc7 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs @@ -291,7 +291,7 @@ impl FnTrait { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ClosureFnTraitImplData { def: DefWithBodyId, expr: ExprId, @@ -300,7 +300,7 @@ pub struct ClosureFnTraitImplData { /// An impl. Usually this comes from an impl block, but some built-in types get /// synthetic impls. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum Impl { /// A normal impl from an impl block. ImplBlock(ImplId), diff --git a/crates/ra_hir_ty/src/traits/builtin.rs b/crates/ra_hir_ty/src/traits/builtin.rs index cd587a3382..dd41176f0d 100644 --- a/crates/ra_hir_ty/src/traits/builtin.rs +++ b/crates/ra_hir_ty/src/traits/builtin.rs @@ -28,24 +28,24 @@ pub(super) fn get_builtin_impls( trait_: TraitId, mut callback: impl FnMut(Impl), ) { + // Note: since impl_datum needs to be infallible, we need to make sure here + // that we have all prerequisites to build the respective impls. if let Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { def, expr }, .. }) = ty { for &fn_trait in [super::FnTrait::FnOnce, super::FnTrait::FnMut, super::FnTrait::Fn].iter() { if let Some(actual_trait) = get_fn_trait(db, krate, fn_trait) { if trait_ == actual_trait { let impl_ = super::ClosureFnTraitImplData { def: *def, expr: *expr, fn_trait }; - callback(Impl::ClosureFnTraitImpl(impl_)); + if check_closure_fn_trait_impl_prerequisites(db, krate, impl_) { + callback(Impl::ClosureFnTraitImpl(impl_)); + } } } } } } -pub(super) fn impl_datum( - db: &impl HirDatabase, - krate: CrateId, - impl_: Impl, -) -> Option { +pub(super) fn impl_datum(db: &impl HirDatabase, krate: CrateId, impl_: Impl) -> BuiltinImplData { match impl_ { Impl::ImplBlock(_) => unreachable!(), Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), @@ -65,21 +65,38 @@ pub(super) fn associated_ty_value( } } +fn check_closure_fn_trait_impl_prerequisites( + db: &impl HirDatabase, + krate: CrateId, + data: super::ClosureFnTraitImplData, +) -> bool { + // the respective Fn/FnOnce/FnMut trait needs to exist + if get_fn_trait(db, krate, data.fn_trait).is_none() { + return false; + } + + // FIXME: there are more assumptions that we should probably check here: + // the traits having no type params, FnOnce being a supertrait + + // the FnOnce trait needs to exist and have an assoc type named Output + let fn_once_trait = match get_fn_trait(db, krate, super::FnTrait::FnOnce) { + Some(t) => t, + None => return false, + }; + db.trait_data(fn_once_trait).associated_type_by_name(&name![Output]).is_some() +} + fn closure_fn_trait_impl_datum( db: &impl HirDatabase, krate: CrateId, data: super::ClosureFnTraitImplData, -) -> Option { +) -> BuiltinImplData { // for some closure |X, Y| -> Z: // impl Fn<(T, U)> for closure V> { Output = V } - let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait - - // validate FnOnce trait, since we need it in the assoc ty value definition - // and don't want to return a valid value only to find out later that FnOnce - // is broken - let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; - let _output = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; + let trait_ = get_fn_trait(db, krate, data.fn_trait) // get corresponding fn trait + // the existence of the Fn trait has been checked before + .expect("fn trait for closure impl missing"); let num_args: u16 = match &db.body(data.def.into())[data.expr] { Expr::Lambda { args, .. } => args.len() as u16, @@ -107,12 +124,12 @@ fn closure_fn_trait_impl_datum( let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()); - Some(BuiltinImplData { + BuiltinImplData { num_vars: num_args as usize + 1, trait_ref, where_clauses: Vec::new(), assoc_ty_values: vec![output_ty_id], - }) + } } fn closure_fn_trait_output_assoc_ty_value( diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index d53d3fdebd..9e38337e56 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -1,5 +1,5 @@ //! Conversion code from/to Chalk. -use std::sync::Arc; +use std::{fmt, sync::Arc}; use log::debug; @@ -17,7 +17,73 @@ use crate::{ ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk, }; -pub type TypeFamily = chalk_ir::family::ChalkIr; +#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] +pub struct TypeFamily {} + +impl chalk_ir::family::TypeFamily for TypeFamily { + type InternedType = Box>; + type InternedLifetime = chalk_ir::LifetimeData; + type InternedParameter = chalk_ir::ParameterData; + type DefId = InternId; + + // FIXME: implement these + fn debug_struct_id( + _type_kind_id: chalk_ir::StructId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_trait_id( + _type_kind_id: chalk_ir::TraitId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_assoc_type_id( + _id: chalk_ir::AssocTypeId, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn debug_projection( + _projection: &chalk_ir::ProjectionTy, + _fmt: &mut fmt::Formatter<'_>, + ) -> Option { + None + } + + fn intern_ty(ty: chalk_ir::TyData) -> Box> { + Box::new(ty) + } + + fn ty_data(ty: &Box>) -> &chalk_ir::TyData { + ty + } + + fn intern_lifetime(lifetime: chalk_ir::LifetimeData) -> chalk_ir::LifetimeData { + lifetime + } + + fn lifetime_data(lifetime: &chalk_ir::LifetimeData) -> &chalk_ir::LifetimeData { + lifetime + } + + fn intern_parameter(parameter: chalk_ir::ParameterData) -> chalk_ir::ParameterData { + parameter + } + + fn parameter_data(parameter: &chalk_ir::ParameterData) -> &chalk_ir::ParameterData { + parameter + } +} + +impl chalk_ir::family::HasTypeFamily for TypeFamily { + type TypeFamily = Self; +} + pub type AssocTypeId = chalk_ir::AssocTypeId; pub type AssociatedTyDatum = chalk_rust_ir::AssociatedTyDatum; pub type TraitId = chalk_ir::TraitId; @@ -29,9 +95,6 @@ pub type ImplDatum = chalk_rust_ir::ImplDatum; pub type AssociatedTyValueId = chalk_rust_ir::AssociatedTyValueId; pub type AssociatedTyValue = chalk_rust_ir::AssociatedTyValue; -/// This represents a trait whose name we could not resolve. -const UNKNOWN_TRAIT: TraitId = chalk_ir::TraitId(chalk_ir::RawId { index: u32::max_value() }); - pub(super) trait ToChalk { type Chalk; fn to_chalk(self, db: &impl HirDatabase) -> Self::Chalk; @@ -162,11 +225,11 @@ impl ToChalk for hir_def::TraitId { type Chalk = TraitId; fn to_chalk(self, _db: &impl HirDatabase) -> TraitId { - chalk_ir::TraitId(id_to_chalk(self)) + chalk_ir::TraitId(self.as_intern_id()) } fn from_chalk(_db: &impl HirDatabase, trait_id: TraitId) -> hir_def::TraitId { - id_from_chalk(trait_id.0) + InternKey::from_intern_id(trait_id.0) } } @@ -215,11 +278,11 @@ impl ToChalk for TypeAliasId { type Chalk = AssocTypeId; fn to_chalk(self, _db: &impl HirDatabase) -> AssocTypeId { - chalk_ir::AssocTypeId(id_to_chalk(self)) + chalk_ir::AssocTypeId(self.as_intern_id()) } fn from_chalk(_db: &impl HirDatabase, type_alias_id: AssocTypeId) -> TypeAliasId { - id_from_chalk(type_alias_id.0) + InternKey::from_intern_id(type_alias_id.0) } } @@ -250,13 +313,7 @@ impl ToChalk for GenericPredicate { }), 0, ), - GenericPredicate::Error => { - let impossible_trait_ref = chalk_ir::TraitRef { - trait_id: UNKNOWN_TRAIT, - parameters: vec![Ty::Unknown.to_chalk(db).cast()], - }; - make_binders(chalk_ir::WhereClause::Implemented(impossible_trait_ref), 0) - } + GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), } } @@ -266,10 +323,6 @@ impl ToChalk for GenericPredicate { ) -> GenericPredicate { match where_clause.value { chalk_ir::WhereClause::Implemented(tr) => { - if tr.trait_id == UNKNOWN_TRAIT { - // FIXME we need an Error enum on the Chalk side to avoid this - return GenericPredicate::Error; - } GenericPredicate::Implemented(from_chalk(db, tr)) } chalk_ir::WhereClause::ProjectionEq(projection_eq) => { @@ -460,9 +513,8 @@ fn convert_where_clauses( let mut result = Vec::with_capacity(generic_predicates.len()); for pred in generic_predicates.iter() { if pred.is_error() { - // HACK: Return just the single predicate (which is always false - // anyway), otherwise Chalk can easily get into slow situations - return vec![pred.clone().subst(substs).to_chalk(db)]; + // skip errored predicates completely + continue; } result.push(pred.clone().subst(substs).to_chalk(db)); } @@ -491,10 +543,11 @@ where parameters: &[Parameter], ) -> Vec { debug!("impls_for_trait {:?}", trait_id); - if trait_id == UNKNOWN_TRAIT { - return Vec::new(); - } let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); + + // Note: Since we're using impls_for_trait, only impls where the trait + // can be resolved should ever reach Chalk. `impl_datum` relies on that + // and will panic if the trait can't be resolved. let mut result: Vec<_> = self .db .impls_for_trait(self.krate, trait_.into()) @@ -566,24 +619,6 @@ pub(crate) fn trait_datum_query( trait_id: TraitId, ) -> Arc { debug!("trait_datum {:?}", trait_id); - if trait_id == UNKNOWN_TRAIT { - let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; - - let flags = chalk_rust_ir::TraitFlags { - auto: false, - marker: false, - upstream: true, - fundamental: false, - non_enumerable: true, - coinductive: false, - }; - return Arc::new(TraitDatum { - id: trait_id, - binders: make_binders(trait_datum_bound, 1), - flags, - associated_ty_ids: vec![], - }); - } let trait_: hir_def::TraitId = from_chalk(db, trait_id); let trait_data = db.trait_data(trait_); debug!("trait {:?} = {:?}", trait_id, trait_data.name); @@ -653,9 +688,8 @@ pub(crate) fn impl_datum_query( let impl_: Impl = from_chalk(db, impl_id); match impl_ { Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), - _ => builtin::impl_datum(db, krate, impl_).map(|d| Arc::new(d.to_chalk(db))), + _ => Arc::new(builtin::impl_datum(db, krate, impl_).to_chalk(db)), } - .unwrap_or_else(invalid_impl_datum) } fn impl_block_datum( @@ -663,8 +697,11 @@ fn impl_block_datum( krate: CrateId, chalk_id: ImplId, impl_id: hir_def::ImplId, -) -> Option> { - let trait_ref = db.impl_trait(impl_id)?; +) -> Arc { + let trait_ref = db + .impl_trait(impl_id) + // ImplIds for impls where the trait ref can't be resolved should never reach Chalk + .expect("invalid impl passed to Chalk"); let impl_data = db.impl_data(impl_id); let generic_params = generics(db, impl_id.into()); @@ -716,21 +753,6 @@ fn impl_block_datum( polarity, associated_ty_value_ids, }; - Some(Arc::new(impl_datum)) -} - -fn invalid_impl_datum() -> Arc { - let trait_ref = chalk_ir::TraitRef { - trait_id: UNKNOWN_TRAIT, - parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], - }; - let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; - let impl_datum = ImplDatum { - binders: make_binders(impl_datum_bound, 1), - impl_type: chalk_rust_ir::ImplType::External, - polarity: chalk_rust_ir::Polarity::Positive, - associated_ty_value_ids: Vec::new(), - }; Arc::new(impl_datum) } @@ -786,25 +808,25 @@ fn id_to_chalk(salsa_id: T) -> chalk_ir::RawId { impl From for crate::TypeCtorId { fn from(struct_id: StructId) -> Self { - id_from_chalk(struct_id.0) + InternKey::from_intern_id(struct_id.0) } } impl From for StructId { fn from(type_ctor_id: crate::TypeCtorId) -> Self { - chalk_ir::StructId(id_to_chalk(type_ctor_id)) + chalk_ir::StructId(type_ctor_id.as_intern_id()) } } impl From for crate::traits::GlobalImplId { fn from(impl_id: ImplId) -> Self { - id_from_chalk(impl_id.0) + InternKey::from_intern_id(impl_id.0) } } impl From for ImplId { fn from(impl_id: crate::traits::GlobalImplId) -> Self { - chalk_ir::ImplId(id_to_chalk(impl_id)) + chalk_ir::ImplId(impl_id.as_intern_id()) } } From 1f7f4578f72721c1b0e17e8405f986fd2ce89aaf Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Sat, 21 Dec 2019 19:15:06 +0100 Subject: [PATCH 311/312] Filter out error predicates in type bounds as well --- crates/ra_hir_ty/src/tests/traits.rs | 17 +++++++++++++++++ crates/ra_hir_ty/src/traits/chalk.rs | 14 ++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 76e2198b66..ae316922bd 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs @@ -958,6 +958,23 @@ fn test() { ); } +#[test] +fn error_bound_chalk() { + let t = type_at( + r#" +//- /main.rs +trait Trait { + fn foo(&self) -> u32 {} +} + +fn test(x: (impl Trait + UnknownTrait)) { + x.foo()<|>; +} +"#, + ); + assert_eq!(t, "u32"); +} + #[test] fn assoc_type_bindings() { assert_snapshot!( diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 9e38337e56..555930c9bf 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs @@ -129,12 +129,22 @@ impl ToChalk for Ty { Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), Ty::Dyn(predicates) => { - let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); + let where_clauses = predicates + .iter() + .filter(|p| !p.is_error()) + .cloned() + .map(|p| p.to_chalk(db)) + .collect(); let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Dyn(bounded_ty).intern() } Ty::Opaque(predicates) => { - let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); + let where_clauses = predicates + .iter() + .filter(|p| !p.is_error()) + .cloned() + .map(|p| p.to_chalk(db)) + .collect(); let bounded_ty = chalk_ir::BoundedTy { bounds: make_binders(where_clauses, 1) }; chalk_ir::TyData::Opaque(bounded_ty).intern() } From 700e74df4ab8d6c043eec524e993f721f13d2180 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Mon, 23 Dec 2019 11:02:54 +0100 Subject: [PATCH 312/312] Bump lsp-types to 0.66.0 (fixes #2651) --- Cargo.lock | 6 +++--- crates/ra_lsp_server/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55afcda7bf..09ed2d6ba9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.65.0" +version = "0.66.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1050,7 +1050,7 @@ dependencies = [ "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lsp-types 0.66.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "ra_ide 0.1.0", "ra_prof 0.1.0", @@ -1842,7 +1842,7 @@ dependencies = [ "checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lsp-server 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0ba36405bd742139ab79c246ca5adb7fde2fe1a0f495e2c8e2f607b607dedb12" -"checksum lsp-types 0.65.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1fe9e427e63e6172699737b47f1044bcade7046e2404d59ebd90c459da47cd2b" +"checksum lsp-types 0.66.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a2dddfe2791cbf4b5eff5a581e45becf47a24b128a62de80e7cc135bf50064" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index e826c10ef0..60cbc38a95 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0.34" serde = { version = "1.0.83", features = ["derive"] } crossbeam-channel = "0.4" log = "0.4.3" -lsp-types = { version = "0.65.0", features = ["proposed"] } +lsp-types = { version = "0.66.0", features = ["proposed"] } rustc-hash = "1.0" parking_lot = "0.10.0" jod-thread = "0.1.0"