diff options
26 files changed, 1143 insertions, 464 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 5d8cf57b6..8f1ed1086 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | expr::{Body, BodySourceMap}, | 11 | expr::{Body, BodySourceMap}, |
12 | ty::InferenceResult, | 12 | ty::InferenceResult, |
13 | adt::{EnumVariantId, StructFieldId, VariantDef}, | 13 | adt::{EnumVariantId, StructFieldId, VariantDef}, |
14 | generics::GenericParams, | 14 | generics::HasGenericParams, |
15 | docs::{Documentation, Docs, docs_from_ast}, | 15 | docs::{Documentation, Docs, docs_from_ast}, |
16 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId}, | 16 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeAliasId}, |
17 | impl_block::ImplBlock, | 17 | impl_block::ImplBlock, |
@@ -189,12 +189,12 @@ impl Module { | |||
189 | } | 189 | } |
190 | } | 190 | } |
191 | 191 | ||
192 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 192 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { |
193 | let def_map = db.crate_def_map(self.krate); | 193 | let def_map = db.crate_def_map(self.krate); |
194 | Resolver::default().push_module_scope(def_map, self.module_id) | 194 | Resolver::default().push_module_scope(def_map, self.module_id) |
195 | } | 195 | } |
196 | 196 | ||
197 | pub fn declarations(self, db: &impl HirDatabase) -> Vec<ModuleDef> { | 197 | pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { |
198 | let def_map = db.crate_def_map(self.krate); | 198 | let def_map = db.crate_def_map(self.krate); |
199 | def_map[self.module_id] | 199 | def_map[self.module_id] |
200 | .scope | 200 | .scope |
@@ -299,10 +299,6 @@ impl Struct { | |||
299 | .map(|(id, _)| StructField { parent: (*self).into(), id }) | 299 | .map(|(id, _)| StructField { parent: (*self).into(), id }) |
300 | } | 300 | } |
301 | 301 | ||
302 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
303 | db.generic_params((*self).into()) | ||
304 | } | ||
305 | |||
306 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 302 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
307 | db.type_for_def((*self).into(), Namespace::Types) | 303 | db.type_for_def((*self).into(), Namespace::Types) |
308 | } | 304 | } |
@@ -363,10 +359,6 @@ impl Enum { | |||
363 | .map(|(id, _)| EnumVariant { parent: *self, id }) | 359 | .map(|(id, _)| EnumVariant { parent: *self, id }) |
364 | } | 360 | } |
365 | 361 | ||
366 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
367 | db.generic_params((*self).into()) | ||
368 | } | ||
369 | |||
370 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 362 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
371 | db.type_for_def((*self).into(), Namespace::Types) | 363 | db.type_for_def((*self).into(), Namespace::Types) |
372 | } | 364 | } |
@@ -537,24 +529,32 @@ impl Function { | |||
537 | db.infer((*self).into()) | 529 | db.infer((*self).into()) |
538 | } | 530 | } |
539 | 531 | ||
540 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
541 | db.generic_params((*self).into()) | ||
542 | } | ||
543 | |||
544 | /// The containing impl block, if this is a method. | 532 | /// The containing impl block, if this is a method. |
545 | pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { | 533 | pub fn impl_block(&self, db: &impl DefDatabase) -> Option<ImplBlock> { |
546 | let module_impls = db.impls_in_module(self.module(db)); | 534 | let module_impls = db.impls_in_module(self.module(db)); |
547 | ImplBlock::containing(module_impls, (*self).into()) | 535 | ImplBlock::containing(module_impls, (*self).into()) |
548 | } | 536 | } |
549 | 537 | ||
538 | /// The containing trait, if this is a trait method definition. | ||
539 | pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> { | ||
540 | db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) | ||
541 | } | ||
542 | |||
543 | pub fn container(&self, db: &impl DefDatabase) -> Option<Container> { | ||
544 | if let Some(impl_block) = self.impl_block(db) { | ||
545 | Some(impl_block.into()) | ||
546 | } else if let Some(trait_) = self.parent_trait(db) { | ||
547 | Some(trait_.into()) | ||
548 | } else { | ||
549 | None | ||
550 | } | ||
551 | } | ||
552 | |||
550 | // FIXME: move to a more general type for 'body-having' items | 553 | // FIXME: move to a more general type for 'body-having' items |
551 | /// Builds a resolver for code inside this item. | 554 | /// Builds a resolver for code inside this item. |
552 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 555 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { |
553 | // take the outer scope... | 556 | // take the outer scope... |
554 | let r = self | 557 | let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db)); |
555 | .impl_block(db) | ||
556 | .map(|ib| ib.resolver(db)) | ||
557 | .unwrap_or_else(|| self.module(db).resolver(db)); | ||
558 | // ...and add generic params, if present | 558 | // ...and add generic params, if present |
559 | let p = self.generic_params(db); | 559 | let p = self.generic_params(db); |
560 | let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; | 560 | let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; |
@@ -684,10 +684,6 @@ impl Trait { | |||
684 | self.id.module(db) | 684 | self.id.module(db) |
685 | } | 685 | } |
686 | 686 | ||
687 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
688 | db.generic_params((*self).into()) | ||
689 | } | ||
690 | |||
691 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 687 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
692 | self.trait_data(db).name().clone() | 688 | self.trait_data(db).name().clone() |
693 | } | 689 | } |
@@ -699,6 +695,14 @@ impl Trait { | |||
699 | pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { | 695 | pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { |
700 | db.trait_data(self) | 696 | db.trait_data(self) |
701 | } | 697 | } |
698 | |||
699 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | ||
700 | let r = self.module(db).resolver(db); | ||
701 | // add generic params, if present | ||
702 | let p = self.generic_params(db); | ||
703 | let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r }; | ||
704 | r | ||
705 | } | ||
702 | } | 706 | } |
703 | 707 | ||
704 | impl Docs for Trait { | 708 | impl Docs for Trait { |
@@ -717,10 +721,6 @@ impl TypeAlias { | |||
717 | self.id.source(db) | 721 | self.id.source(db) |
718 | } | 722 | } |
719 | 723 | ||
720 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
721 | db.generic_params((*self).into()) | ||
722 | } | ||
723 | |||
724 | pub fn module(&self, db: &impl DefDatabase) -> Module { | 724 | pub fn module(&self, db: &impl DefDatabase) -> Module { |
725 | self.id.module(db) | 725 | self.id.module(db) |
726 | } | 726 | } |
@@ -731,6 +731,21 @@ impl TypeAlias { | |||
731 | ImplBlock::containing(module_impls, (*self).into()) | 731 | ImplBlock::containing(module_impls, (*self).into()) |
732 | } | 732 | } |
733 | 733 | ||
734 | /// The containing trait, if this is a trait method definition. | ||
735 | pub fn parent_trait(&self, db: &impl DefDatabase) -> Option<Trait> { | ||
736 | db.trait_items_index(self.module(db)).get_parent_trait((*self).into()) | ||
737 | } | ||
738 | |||
739 | pub fn container(&self, db: &impl DefDatabase) -> Option<Container> { | ||
740 | if let Some(impl_block) = self.impl_block(db) { | ||
741 | Some(impl_block.into()) | ||
742 | } else if let Some(trait_) = self.parent_trait(db) { | ||
743 | Some(trait_.into()) | ||
744 | } else { | ||
745 | None | ||
746 | } | ||
747 | } | ||
748 | |||
734 | pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> { | 749 | pub fn type_ref(self, db: &impl DefDatabase) -> Arc<TypeRef> { |
735 | db.type_alias_ref(self) | 750 | db.type_alias_ref(self) |
736 | } | 751 | } |
@@ -754,3 +769,18 @@ impl Docs for TypeAlias { | |||
754 | docs_from_ast(&*self.source(db).1) | 769 | docs_from_ast(&*self.source(db).1) |
755 | } | 770 | } |
756 | } | 771 | } |
772 | |||
773 | pub enum Container { | ||
774 | Trait(Trait), | ||
775 | ImplBlock(ImplBlock), | ||
776 | } | ||
777 | impl_froms!(Container: Trait, ImplBlock); | ||
778 | |||
779 | impl Container { | ||
780 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | ||
781 | match self { | ||
782 | Container::Trait(trait_) => trait_.resolver(db), | ||
783 | Container::ImplBlock(impl_block) => impl_block.resolver(db), | ||
784 | } | ||
785 | } | ||
786 | } | ||
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index e23e2bb2b..18627bbc2 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -53,6 +53,9 @@ pub trait DefDatabase: SourceDatabase { | |||
53 | #[salsa::invoke(crate::traits::TraitData::trait_data_query)] | 53 | #[salsa::invoke(crate::traits::TraitData::trait_data_query)] |
54 | fn trait_data(&self, t: Trait) -> Arc<TraitData>; | 54 | fn trait_data(&self, t: Trait) -> Arc<TraitData>; |
55 | 55 | ||
56 | #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)] | ||
57 | fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex; | ||
58 | |||
56 | #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] | 59 | #[salsa::invoke(crate::source_id::AstIdMap::ast_id_map_query)] |
57 | fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; | 60 | fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; |
58 | 61 | ||
@@ -128,8 +131,8 @@ pub trait HirDatabase: DefDatabase { | |||
128 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] | 131 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] |
129 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; | 132 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; |
130 | 133 | ||
131 | #[salsa::invoke(crate::ty::method_resolution::implements)] | 134 | #[salsa::invoke(crate::ty::traits::implements)] |
132 | fn implements(&self, trait_ref: TraitRef) -> bool; | 135 | fn implements(&self, trait_ref: TraitRef) -> Option<crate::ty::traits::Solution>; |
133 | } | 136 | } |
134 | 137 | ||
135 | #[test] | 138 | #[test] |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 84fe94289..5625c2459 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock | 12 | Name, AsName, Function, Struct, Enum, Trait, TypeAlias, ImplBlock, Container |
13 | }; | 13 | }; |
14 | 14 | ||
15 | /// Data about a generic parameter (to a function, struct, impl, ...). | 15 | /// Data about a generic parameter (to a function, struct, impl, ...). |
@@ -27,6 +27,7 @@ pub struct GenericParams { | |||
27 | pub(crate) params: Vec<GenericParam>, | 27 | pub(crate) params: Vec<GenericParam>, |
28 | } | 28 | } |
29 | 29 | ||
30 | // FIXME: consts can have type parameters from their parents (i.e. associated consts of traits) | ||
30 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | 31 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] |
31 | pub enum GenericDef { | 32 | pub enum GenericDef { |
32 | Function(Function), | 33 | Function(Function), |
@@ -45,18 +46,22 @@ impl GenericParams { | |||
45 | ) -> Arc<GenericParams> { | 46 | ) -> Arc<GenericParams> { |
46 | let mut generics = GenericParams::default(); | 47 | let mut generics = GenericParams::default(); |
47 | let parent = match def { | 48 | let parent = match def { |
48 | GenericDef::Function(it) => it.impl_block(db), | 49 | GenericDef::Function(it) => it.container(db).map(GenericDef::from), |
49 | GenericDef::TypeAlias(it) => it.impl_block(db), | 50 | GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from), |
50 | GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, | 51 | GenericDef::Struct(_) | GenericDef::Enum(_) | GenericDef::Trait(_) => None, |
51 | GenericDef::ImplBlock(_) => None, | 52 | GenericDef::ImplBlock(_) => None, |
52 | }; | 53 | }; |
53 | generics.parent_params = parent.map(|p| p.generic_params(db)); | 54 | generics.parent_params = parent.map(|p| db.generic_params(p)); |
54 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; | 55 | let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; |
55 | match def { | 56 | match def { |
56 | GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), | 57 | GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), |
57 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), | 58 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), |
58 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), | 59 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), |
59 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1, start), | 60 | GenericDef::Trait(it) => { |
61 | // traits get the Self type as an implicit first type parameter | ||
62 | generics.params.push(GenericParam { idx: start, name: Name::self_type() }); | ||
63 | generics.fill(&*it.source(db).1, start + 1); | ||
64 | } | ||
60 | GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), | 65 | GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), |
61 | GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), | 66 | GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), |
62 | } | 67 | } |
@@ -104,3 +109,25 @@ impl GenericParams { | |||
104 | vec | 109 | vec |
105 | } | 110 | } |
106 | } | 111 | } |
112 | |||
113 | impl From<Container> for GenericDef { | ||
114 | fn from(c: Container) -> Self { | ||
115 | match c { | ||
116 | Container::Trait(trait_) => trait_.into(), | ||
117 | Container::ImplBlock(impl_block) => impl_block.into(), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | pub trait HasGenericParams { | ||
123 | fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams>; | ||
124 | } | ||
125 | |||
126 | impl<T> HasGenericParams for T | ||
127 | where | ||
128 | T: Into<GenericDef>, | ||
129 | { | ||
130 | fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> { | ||
131 | db.generic_params(self.into()) | ||
132 | } | ||
133 | } | ||
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index b306874cc..a8a466e43 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -9,16 +9,15 @@ use ra_syntax::{ | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | Const, TypeAlias, Function, HirFileId, | 11 | Const, TypeAlias, Function, HirFileId, |
12 | HirDatabase, DefDatabase, | 12 | HirDatabase, DefDatabase, TraitRef, |
13 | ModuleDef, Trait, Resolution, | ||
14 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
15 | ids::LocationCtx, | 14 | ids::LocationCtx, |
16 | resolve::Resolver, | 15 | resolve::Resolver, |
17 | ty::Ty, generics::GenericParams, | 16 | ty::Ty, |
17 | generics::HasGenericParams, | ||
18 | code_model_api::{Module, ModuleSource} | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | use crate::code_model_api::{Module, ModuleSource}; | ||
21 | |||
22 | #[derive(Debug, Default, PartialEq, Eq)] | 21 | #[derive(Debug, Default, PartialEq, Eq)] |
23 | pub struct ImplSourceMap { | 22 | pub struct ImplSourceMap { |
24 | map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>, | 23 | map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>, |
@@ -73,7 +72,7 @@ impl ImplBlock { | |||
73 | self.module | 72 | self.module |
74 | } | 73 | } |
75 | 74 | ||
76 | pub fn target_trait_ref(&self, db: &impl DefDatabase) -> Option<TypeRef> { | 75 | pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { |
77 | db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() | 76 | db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned() |
78 | } | 77 | } |
79 | 78 | ||
@@ -85,27 +84,16 @@ impl ImplBlock { | |||
85 | Ty::from_hir(db, &self.resolver(db), &self.target_type(db)) | 84 | Ty::from_hir(db, &self.resolver(db), &self.target_type(db)) |
86 | } | 85 | } |
87 | 86 | ||
88 | pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> { | 87 | pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> { |
89 | if let Some(TypeRef::Path(path)) = self.target_trait_ref(db) { | 88 | let target_ty = self.target_ty(db); |
90 | let resolver = self.resolver(db); | 89 | TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty)) |
91 | if let Some(Resolution::Def(ModuleDef::Trait(tr))) = | ||
92 | resolver.resolve_path(db, &path).take_types() | ||
93 | { | ||
94 | return Some(tr); | ||
95 | } | ||
96 | } | ||
97 | None | ||
98 | } | 90 | } |
99 | 91 | ||
100 | pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> { | 92 | pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> { |
101 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() | 93 | db.impls_in_module(self.module).impls[self.impl_id].items().to_vec() |
102 | } | 94 | } |
103 | 95 | ||
104 | pub fn generic_params(&self, db: &impl DefDatabase) -> Arc<GenericParams> { | 96 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { |
105 | db.generic_params((*self).into()) | ||
106 | } | ||
107 | |||
108 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
109 | let r = self.module().resolver(db); | 97 | let r = self.module().resolver(db); |
110 | // add generic params, if present | 98 | // add generic params, if present |
111 | let p = self.generic_params(db); | 99 | let p = self.generic_params(db); |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index a9db23060..9292de1b5 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -61,12 +61,13 @@ pub use self::{ | |||
61 | source_id::{AstIdMap, ErasedFileAstId}, | 61 | source_id::{AstIdMap, ErasedFileAstId}, |
62 | ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc}, | 62 | ids::{HirFileId, MacroDefId, MacroCallId, MacroCallLoc}, |
63 | nameres::{PerNs, Namespace, ImportId}, | 63 | nameres::{PerNs, Namespace, ImportId}, |
64 | ty::{Ty, ApplicationTy, TypeCtor, Substs, display::HirDisplay, CallableDef}, | 64 | ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef}, |
65 | impl_block::{ImplBlock, ImplItem}, | 65 | impl_block::{ImplBlock, ImplItem}, |
66 | docs::{Docs, Documentation}, | 66 | docs::{Docs, Documentation}, |
67 | adt::AdtDef, | 67 | adt::AdtDef, |
68 | expr::ExprScopes, | 68 | expr::ExprScopes, |
69 | resolve::Resolution, | 69 | resolve::Resolution, |
70 | generics::{GenericParams, GenericParam, HasGenericParams}, | ||
70 | source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax}, | 71 | source_binder::{SourceAnalyzer, PathResolution, ScopeEntryWithSyntax}, |
71 | }; | 72 | }; |
72 | 73 | ||
@@ -78,5 +79,5 @@ pub use self::code_model_api::{ | |||
78 | Function, FnSignature, | 79 | Function, FnSignature, |
79 | StructField, FieldSource, | 80 | StructField, FieldSource, |
80 | Static, Const, ConstSignature, | 81 | Static, Const, ConstSignature, |
81 | Trait, TypeAlias, | 82 | Trait, TypeAlias, Container, |
82 | }; | 83 | }; |
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs index 725bdd5cb..15f0977b7 100644 --- a/crates/ra_hir/src/traits.rs +++ b/crates/ra_hir/src/traits.rs | |||
@@ -1,10 +1,11 @@ | |||
1 | //! HIR for trait definitions. | 1 | //! HIR for trait definitions. |
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | use rustc_hash::FxHashMap; | ||
4 | 5 | ||
5 | use ra_syntax::ast::{self, NameOwner}; | 6 | use ra_syntax::ast::{self, NameOwner}; |
6 | 7 | ||
7 | use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName}; | 8 | use crate::{Function, Const, TypeAlias, Name, DefDatabase, Trait, ids::LocationCtx, name::AsName, Module}; |
8 | 9 | ||
9 | #[derive(Debug, Clone, PartialEq, Eq)] | 10 | #[derive(Debug, Clone, PartialEq, Eq)] |
10 | pub struct TraitData { | 11 | pub struct TraitData { |
@@ -49,4 +50,34 @@ pub enum TraitItem { | |||
49 | TypeAlias(TypeAlias), | 50 | TypeAlias(TypeAlias), |
50 | // Existential | 51 | // Existential |
51 | } | 52 | } |
53 | // FIXME: not every function, ... is actually a trait item. maybe we should make | ||
54 | // sure that you can only turn actual trait items into TraitItems. This would | ||
55 | // require not implementing From, and instead having some checked way of | ||
56 | // casting them. | ||
52 | impl_froms!(TraitItem: Function, Const, TypeAlias); | 57 | impl_froms!(TraitItem: Function, Const, TypeAlias); |
58 | |||
59 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
60 | pub struct TraitItemsIndex { | ||
61 | traits_by_def: FxHashMap<TraitItem, Trait>, | ||
62 | } | ||
63 | |||
64 | impl TraitItemsIndex { | ||
65 | pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex { | ||
66 | let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() }; | ||
67 | for decl in module.declarations(db) { | ||
68 | match decl { | ||
69 | crate::ModuleDef::Trait(tr) => { | ||
70 | for item in tr.trait_data(db).items() { | ||
71 | index.traits_by_def.insert(*item, tr); | ||
72 | } | ||
73 | } | ||
74 | _ => {} | ||
75 | } | ||
76 | } | ||
77 | index | ||
78 | } | ||
79 | |||
80 | pub(crate) fn get_parent_trait(&self, item: TraitItem) -> Option<Trait> { | ||
81 | self.traits_by_def.get(&item).cloned() | ||
82 | } | ||
83 | } | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index ecf13fbc3..12e10c751 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -5,6 +5,7 @@ mod autoderef; | |||
5 | pub(crate) mod primitive; | 5 | pub(crate) mod primitive; |
6 | #[cfg(test)] | 6 | #[cfg(test)] |
7 | mod tests; | 7 | mod tests; |
8 | pub(crate) mod traits; | ||
8 | pub(crate) mod method_resolution; | 9 | pub(crate) mod method_resolution; |
9 | mod op; | 10 | mod op; |
10 | mod lower; | 11 | mod lower; |
@@ -145,6 +146,10 @@ impl Substs { | |||
145 | Substs(Arc::new([ty])) | 146 | Substs(Arc::new([ty])) |
146 | } | 147 | } |
147 | 148 | ||
149 | pub fn prefix(&self, n: usize) -> Substs { | ||
150 | Substs(self.0.iter().cloned().take(n).collect::<Vec<_>>().into()) | ||
151 | } | ||
152 | |||
148 | pub fn iter(&self) -> impl Iterator<Item = &Ty> { | 153 | pub fn iter(&self) -> impl Iterator<Item = &Ty> { |
149 | self.0.iter() | 154 | self.0.iter() |
150 | } | 155 | } |
@@ -170,6 +175,12 @@ impl Substs { | |||
170 | } | 175 | } |
171 | } | 176 | } |
172 | 177 | ||
178 | impl From<Vec<Ty>> for Substs { | ||
179 | fn from(v: Vec<Ty>) -> Self { | ||
180 | Substs(v.into()) | ||
181 | } | ||
182 | } | ||
183 | |||
173 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 184 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
174 | /// Name to be bikeshedded: TraitBound? TraitImplements? | 185 | /// Name to be bikeshedded: TraitBound? TraitImplements? |
175 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 186 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -210,6 +221,14 @@ impl FnSig { | |||
210 | &self.params_and_return[self.params_and_return.len() - 1] | 221 | &self.params_and_return[self.params_and_return.len() - 1] |
211 | } | 222 | } |
212 | 223 | ||
224 | /// Applies the given substitutions to all types in this signature and | ||
225 | /// returns the result. | ||
226 | pub fn subst(&self, substs: &Substs) -> FnSig { | ||
227 | let result: Vec<_> = | ||
228 | self.params_and_return.iter().map(|ty| ty.clone().subst(substs)).collect(); | ||
229 | FnSig { params_and_return: result.into() } | ||
230 | } | ||
231 | |||
213 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 232 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
214 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 233 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
215 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); | 234 | let mut v: Vec<_> = self.params_and_return.iter().cloned().collect(); |
@@ -309,6 +328,20 @@ impl Ty { | |||
309 | } | 328 | } |
310 | } | 329 | } |
311 | 330 | ||
331 | fn callable_sig(&self, db: &impl HirDatabase) -> Option<FnSig> { | ||
332 | match self { | ||
333 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
334 | TypeCtor::FnPtr => Some(FnSig::from_fn_ptr_substs(&a_ty.parameters)), | ||
335 | TypeCtor::FnDef(def) => { | ||
336 | let sig = db.callable_item_signature(def); | ||
337 | Some(sig.subst(&a_ty.parameters)) | ||
338 | } | ||
339 | _ => None, | ||
340 | }, | ||
341 | _ => None, | ||
342 | } | ||
343 | } | ||
344 | |||
312 | /// If this is a type with type parameters (an ADT or function), replaces | 345 | /// If this is a type with type parameters (an ADT or function), replaces |
313 | /// the `Substs` for these type parameters with the given ones. (So e.g. if | 346 | /// the `Substs` for these type parameters with the given ones. (So e.g. if |
314 | /// `self` is `Option<_>` and the substs contain `u32`, we'll have | 347 | /// `self` is `Option<_>` and the substs contain `u32`, we'll have |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 28947be51..651a78fe5 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -20,9 +20,9 @@ use std::sync::Arc; | |||
20 | use std::mem; | 20 | use std::mem; |
21 | 21 | ||
22 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; | 22 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; |
23 | use ra_arena::map::ArenaMap; | ||
24 | use rustc_hash::FxHashMap; | 23 | use rustc_hash::FxHashMap; |
25 | 24 | ||
25 | use ra_arena::map::ArenaMap; | ||
26 | use test_utils::tested_by; | 26 | use test_utils::tested_by; |
27 | 27 | ||
28 | use crate::{ | 28 | use crate::{ |
@@ -33,15 +33,18 @@ use crate::{ | |||
33 | ImplItem, | 33 | ImplItem, |
34 | type_ref::{TypeRef, Mutability}, | 34 | type_ref::{TypeRef, Mutability}, |
35 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, | 35 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat,Array, self}, |
36 | generics::GenericParams, | 36 | generics::{GenericParams, HasGenericParams}, |
37 | path::{GenericArgs, GenericArg}, | 37 | path::{GenericArgs, GenericArg}, |
38 | adt::VariantDef, | 38 | adt::VariantDef, |
39 | resolve::{Resolver, Resolution}, | 39 | resolve::{Resolver, Resolution}, |
40 | nameres::Namespace, | 40 | nameres::Namespace, |
41 | ty::infer::diagnostics::InferenceDiagnostic, | ||
42 | diagnostics::DiagnosticSink, | 41 | diagnostics::DiagnosticSink, |
43 | }; | 42 | }; |
44 | use super::{Ty, TypableDef, Substs, primitive, op, FnSig, ApplicationTy, TypeCtor}; | 43 | use super::{ |
44 | Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef, | ||
45 | traits::{ Solution, Obligation, Guidance}, | ||
46 | }; | ||
47 | use self::diagnostics::InferenceDiagnostic; | ||
45 | 48 | ||
46 | /// The entry point of type inference. | 49 | /// The entry point of type inference. |
47 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { | 50 | pub fn infer(db: &impl HirDatabase, def: DefWithBody) -> Arc<InferenceResult> { |
@@ -153,6 +156,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
153 | body: Arc<Body>, | 156 | body: Arc<Body>, |
154 | resolver: Resolver, | 157 | resolver: Resolver, |
155 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 158 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
159 | obligations: Vec<Obligation>, | ||
156 | method_resolutions: FxHashMap<ExprId, Function>, | 160 | method_resolutions: FxHashMap<ExprId, Function>, |
157 | field_resolutions: FxHashMap<ExprId, StructField>, | 161 | field_resolutions: FxHashMap<ExprId, StructField>, |
158 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, | 162 | assoc_resolutions: FxHashMap<ExprOrPatId, ImplItem>, |
@@ -173,6 +177,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
173 | type_of_pat: ArenaMap::default(), | 177 | type_of_pat: ArenaMap::default(), |
174 | diagnostics: Vec::default(), | 178 | diagnostics: Vec::default(), |
175 | var_unification_table: InPlaceUnificationTable::new(), | 179 | var_unification_table: InPlaceUnificationTable::new(), |
180 | obligations: Vec::default(), | ||
176 | return_ty: Ty::Unknown, // set in collect_fn_signature | 181 | return_ty: Ty::Unknown, // set in collect_fn_signature |
177 | db, | 182 | db, |
178 | body, | 183 | body, |
@@ -181,6 +186,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
181 | } | 186 | } |
182 | 187 | ||
183 | fn resolve_all(mut self) -> InferenceResult { | 188 | fn resolve_all(mut self) -> InferenceResult { |
189 | // FIXME resolve obligations as well (use Guidance if necessary) | ||
184 | let mut tv_stack = Vec::new(); | 190 | let mut tv_stack = Vec::new(); |
185 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); | 191 | let mut expr_types = mem::replace(&mut self.type_of_expr, ArenaMap::default()); |
186 | for ty in expr_types.values_mut() { | 192 | for ty in expr_types.values_mut() { |
@@ -311,11 +317,49 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
311 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) | 317 | ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) |
312 | } | 318 | } |
313 | 319 | ||
320 | fn resolve_obligations_as_possible(&mut self) { | ||
321 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | ||
322 | for obligation in obligations { | ||
323 | // FIXME resolve types in the obligation first | ||
324 | let (solution, var_mapping) = match &obligation { | ||
325 | Obligation::Trait(tr) => { | ||
326 | let (tr, var_mapping) = super::traits::canonicalize(tr.clone()); | ||
327 | (self.db.implements(tr), var_mapping) | ||
328 | } | ||
329 | }; | ||
330 | match solution { | ||
331 | Some(Solution::Unique(substs)) => { | ||
332 | for (i, subst) in substs.0.iter().enumerate() { | ||
333 | let uncanonical = var_mapping[i]; | ||
334 | // FIXME the subst may contain type variables, which would need to be mapped back as well | ||
335 | self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst); | ||
336 | } | ||
337 | } | ||
338 | Some(Solution::Ambig(Guidance::Definite(substs))) => { | ||
339 | for (i, subst) in substs.0.iter().enumerate() { | ||
340 | let uncanonical = var_mapping[i]; | ||
341 | // FIXME the subst may contain type variables, which would need to be mapped back as well | ||
342 | self.unify(&Ty::Infer(InferTy::TypeVar(uncanonical)), subst); | ||
343 | } | ||
344 | self.obligations.push(obligation); | ||
345 | } | ||
346 | Some(_) => { | ||
347 | self.obligations.push(obligation); | ||
348 | } | ||
349 | None => { | ||
350 | // FIXME obligation cannot be fulfilled => diagnostic | ||
351 | } | ||
352 | } | ||
353 | } | ||
354 | } | ||
355 | |||
314 | /// Resolves the type as far as currently possible, replacing type variables | 356 | /// Resolves the type as far as currently possible, replacing type variables |
315 | /// by their known types. All types returned by the infer_* functions should | 357 | /// by their known types. All types returned by the infer_* functions should |
316 | /// be resolved as far as possible, i.e. contain no type variables with | 358 | /// be resolved as far as possible, i.e. contain no type variables with |
317 | /// known type. | 359 | /// known type. |
318 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { | 360 | fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { |
361 | self.resolve_obligations_as_possible(); | ||
362 | |||
319 | ty.fold(&mut |ty| match ty { | 363 | ty.fold(&mut |ty| match ty { |
320 | Ty::Infer(tv) => { | 364 | Ty::Infer(tv) => { |
321 | let inner = tv.to_inner(); | 365 | let inner = tv.to_inner(); |
@@ -420,6 +464,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
420 | for segment in &path.segments[remaining_index..] { | 464 | for segment in &path.segments[remaining_index..] { |
421 | let ty = match resolved { | 465 | let ty = match resolved { |
422 | Resolution::Def(def) => { | 466 | Resolution::Def(def) => { |
467 | // FIXME resolve associated items from traits as well | ||
423 | let typable: Option<TypableDef> = def.into(); | 468 | let typable: Option<TypableDef> = def.into(); |
424 | let typable = typable?; | 469 | let typable = typable?; |
425 | 470 | ||
@@ -709,13 +754,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
709 | fn substs_for_method_call( | 754 | fn substs_for_method_call( |
710 | &mut self, | 755 | &mut self, |
711 | def_generics: Option<Arc<GenericParams>>, | 756 | def_generics: Option<Arc<GenericParams>>, |
712 | generic_args: &Option<GenericArgs>, | 757 | generic_args: Option<&GenericArgs>, |
758 | receiver_ty: &Ty, | ||
713 | ) -> Substs { | 759 | ) -> Substs { |
714 | let (parent_param_count, param_count) = | 760 | let (parent_param_count, param_count) = |
715 | def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); | 761 | def_generics.as_ref().map_or((0, 0), |g| (g.count_parent_params(), g.params.len())); |
716 | let mut substs = Vec::with_capacity(parent_param_count + param_count); | 762 | let mut substs = Vec::with_capacity(parent_param_count + param_count); |
717 | for _ in 0..parent_param_count { | 763 | // Parent arguments are unknown, except for the receiver type |
718 | substs.push(Ty::Unknown); | 764 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { |
765 | for param in &parent_generics.params { | ||
766 | if param.name.as_known_name() == Some(crate::KnownName::SelfType) { | ||
767 | substs.push(receiver_ty.clone()); | ||
768 | } else { | ||
769 | substs.push(Ty::Unknown); | ||
770 | } | ||
771 | } | ||
719 | } | 772 | } |
720 | // handle provided type arguments | 773 | // handle provided type arguments |
721 | if let Some(generic_args) = generic_args { | 774 | if let Some(generic_args) = generic_args { |
@@ -737,6 +790,83 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
737 | Substs(substs.into()) | 790 | Substs(substs.into()) |
738 | } | 791 | } |
739 | 792 | ||
793 | fn register_obligations_for_call(&mut self, callable_ty: &Ty) { | ||
794 | match callable_ty { | ||
795 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
796 | TypeCtor::FnDef(def) => { | ||
797 | // add obligation for trait implementation, if this is a trait method | ||
798 | // FIXME also register obligations from where clauses from the trait or impl and method | ||
799 | match def { | ||
800 | CallableDef::Function(f) => { | ||
801 | if let Some(trait_) = f.parent_trait(self.db) { | ||
802 | // construct a TraitDef | ||
803 | let substs = a_ty.parameters.prefix( | ||
804 | trait_.generic_params(self.db).count_params_including_parent(), | ||
805 | ); | ||
806 | self.obligations | ||
807 | .push(Obligation::Trait(TraitRef { trait_, substs })); | ||
808 | } | ||
809 | } | ||
810 | CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {} | ||
811 | } | ||
812 | } | ||
813 | _ => {} | ||
814 | }, | ||
815 | _ => {} | ||
816 | } | ||
817 | } | ||
818 | |||
819 | fn infer_method_call( | ||
820 | &mut self, | ||
821 | tgt_expr: ExprId, | ||
822 | receiver: ExprId, | ||
823 | args: &[ExprId], | ||
824 | method_name: &Name, | ||
825 | generic_args: Option<&GenericArgs>, | ||
826 | ) -> Ty { | ||
827 | let receiver_ty = self.infer_expr(receiver, &Expectation::none()); | ||
828 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver); | ||
829 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | ||
830 | Some((ty, func)) => { | ||
831 | self.write_method_resolution(tgt_expr, func); | ||
832 | ( | ||
833 | ty, | ||
834 | self.db.type_for_def(func.into(), Namespace::Values), | ||
835 | Some(func.generic_params(self.db)), | ||
836 | ) | ||
837 | } | ||
838 | None => (receiver_ty, Ty::Unknown, None), | ||
839 | }; | ||
840 | let substs = | ||
841 | self.substs_for_method_call(def_generics.clone(), generic_args, &derefed_receiver_ty); | ||
842 | let method_ty = method_ty.apply_substs(substs); | ||
843 | let method_ty = self.insert_type_vars(method_ty); | ||
844 | self.register_obligations_for_call(&method_ty); | ||
845 | let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { | ||
846 | Some(sig) => { | ||
847 | if !sig.params().is_empty() { | ||
848 | (sig.params()[0].clone(), sig.params()[1..].to_vec(), sig.ret().clone()) | ||
849 | } else { | ||
850 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | ||
851 | } | ||
852 | } | ||
853 | None => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
854 | }; | ||
855 | // Apply autoref so the below unification works correctly | ||
856 | // FIXME: return correct autorefs from lookup_method | ||
857 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | ||
858 | Some((_, mutability)) => Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty), | ||
859 | _ => derefed_receiver_ty, | ||
860 | }; | ||
861 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
862 | |||
863 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
864 | for (arg, param) in args.iter().zip(param_iter) { | ||
865 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
866 | } | ||
867 | ret_ty | ||
868 | } | ||
869 | |||
740 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 870 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
741 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 871 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
742 | let ty = match &body[tgt_expr] { | 872 | let ty = match &body[tgt_expr] { |
@@ -793,102 +923,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
793 | } | 923 | } |
794 | Expr::Call { callee, args } => { | 924 | Expr::Call { callee, args } => { |
795 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 925 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
796 | let (param_tys, ret_ty) = match &callee_ty { | 926 | let (param_tys, ret_ty) = match callee_ty.callable_sig(self.db) { |
797 | Ty::Apply(a_ty) => match a_ty.ctor { | 927 | Some(sig) => (sig.params().to_vec(), sig.ret().clone()), |
798 | TypeCtor::FnPtr => { | 928 | None => { |
799 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); | 929 | // Not callable |
800 | (sig.params().to_vec(), sig.ret().clone()) | 930 | // FIXME: report an error |
801 | } | ||
802 | TypeCtor::FnDef(def) => { | ||
803 | let sig = self.db.callable_item_signature(def); | ||
804 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); | ||
805 | let param_tys = sig | ||
806 | .params() | ||
807 | .iter() | ||
808 | .map(|ty| ty.clone().subst(&a_ty.parameters)) | ||
809 | .collect(); | ||
810 | (param_tys, ret_ty) | ||
811 | } | ||
812 | _ => (Vec::new(), Ty::Unknown), | ||
813 | }, | ||
814 | _ => { | ||
815 | // not callable | ||
816 | // FIXME report an error? | ||
817 | (Vec::new(), Ty::Unknown) | 931 | (Vec::new(), Ty::Unknown) |
818 | } | 932 | } |
819 | }; | 933 | }; |
934 | // FIXME register obligations from where clauses from the function | ||
820 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | 935 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
821 | for (arg, param) in args.iter().zip(param_iter) { | 936 | for (arg, param) in args.iter().zip(param_iter) { |
822 | self.infer_expr(*arg, &Expectation::has_type(param)); | 937 | self.infer_expr(*arg, &Expectation::has_type(param)); |
823 | } | 938 | } |
824 | ret_ty | 939 | ret_ty |
825 | } | 940 | } |
826 | Expr::MethodCall { receiver, args, method_name, generic_args } => { | 941 | Expr::MethodCall { receiver, args, method_name, generic_args } => self |
827 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 942 | .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), |
828 | let resolved = | ||
829 | receiver_ty.clone().lookup_method(self.db, method_name, &self.resolver); | ||
830 | let (derefed_receiver_ty, method_ty, def_generics) = match resolved { | ||
831 | Some((ty, func)) => { | ||
832 | self.write_method_resolution(tgt_expr, func); | ||
833 | ( | ||
834 | ty, | ||
835 | self.db.type_for_def(func.into(), Namespace::Values), | ||
836 | Some(func.generic_params(self.db)), | ||
837 | ) | ||
838 | } | ||
839 | None => (receiver_ty, Ty::Unknown, None), | ||
840 | }; | ||
841 | let substs = self.substs_for_method_call(def_generics, generic_args); | ||
842 | let method_ty = method_ty.apply_substs(substs); | ||
843 | let method_ty = self.insert_type_vars(method_ty); | ||
844 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | ||
845 | Ty::Apply(a_ty) => match a_ty.ctor { | ||
846 | TypeCtor::FnPtr => { | ||
847 | let sig = FnSig::from_fn_ptr_substs(&a_ty.parameters); | ||
848 | if !sig.params().is_empty() { | ||
849 | ( | ||
850 | sig.params()[0].clone(), | ||
851 | sig.params()[1..].to_vec(), | ||
852 | sig.ret().clone(), | ||
853 | ) | ||
854 | } else { | ||
855 | (Ty::Unknown, Vec::new(), sig.ret().clone()) | ||
856 | } | ||
857 | } | ||
858 | TypeCtor::FnDef(def) => { | ||
859 | let sig = self.db.callable_item_signature(def); | ||
860 | let ret_ty = sig.ret().clone().subst(&a_ty.parameters); | ||
861 | |||
862 | if !sig.params().is_empty() { | ||
863 | let mut params_iter = sig | ||
864 | .params() | ||
865 | .iter() | ||
866 | .map(|ty| ty.clone().subst(&a_ty.parameters)); | ||
867 | let receiver_ty = params_iter.next().unwrap(); | ||
868 | (receiver_ty, params_iter.collect(), ret_ty) | ||
869 | } else { | ||
870 | (Ty::Unknown, Vec::new(), ret_ty) | ||
871 | } | ||
872 | } | ||
873 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
874 | }, | ||
875 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
876 | }; | ||
877 | // Apply autoref so the below unification works correctly | ||
878 | let actual_receiver_ty = match expected_receiver_ty.as_reference() { | ||
879 | Some((_, mutability)) => { | ||
880 | Ty::apply_one(TypeCtor::Ref(mutability), derefed_receiver_ty) | ||
881 | } | ||
882 | _ => derefed_receiver_ty, | ||
883 | }; | ||
884 | self.unify(&expected_receiver_ty, &actual_receiver_ty); | ||
885 | |||
886 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); | ||
887 | for (arg, param) in args.iter().zip(param_iter) { | ||
888 | self.infer_expr(*arg, &Expectation::has_type(param)); | ||
889 | } | ||
890 | ret_ty | ||
891 | } | ||
892 | Expr::Match { expr, arms } => { | 943 | Expr::Match { expr, arms } => { |
893 | let expected = if expected.ty == Ty::Unknown { | 944 | let expected = if expected.ty == Ty::Unknown { |
894 | Expectation::has_type(self.new_type_var()) | 945 | Expectation::has_type(self.new_type_var()) |
@@ -1180,7 +1231,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1180 | 1231 | ||
1181 | /// The ID of a type variable. | 1232 | /// The ID of a type variable. |
1182 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | 1233 | #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] |
1183 | pub struct TypeVarId(u32); | 1234 | pub struct TypeVarId(pub(super) u32); |
1184 | 1235 | ||
1185 | impl UnifyKey for TypeVarId { | 1236 | impl UnifyKey for TypeVarId { |
1186 | type Value = TypeVarValue; | 1237 | type Value = TypeVarValue; |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 003a89f0d..7fac084ce 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -5,6 +5,7 @@ | |||
5 | //! - Building the type for an item: This happens through the `type_for_def` query. | 5 | //! - Building the type for an item: This happens through the `type_for_def` query. |
6 | //! | 6 | //! |
7 | //! This usually involves resolving names, collecting generic arguments etc. | 7 | //! This usually involves resolving names, collecting generic arguments etc. |
8 | use std::iter; | ||
8 | 9 | ||
9 | use crate::{ | 10 | use crate::{ |
10 | Function, Struct, StructField, Enum, EnumVariant, Path, | 11 | Function, Struct, StructField, Enum, EnumVariant, Path, |
@@ -15,11 +16,11 @@ use crate::{ | |||
15 | name::KnownName, | 16 | name::KnownName, |
16 | nameres::Namespace, | 17 | nameres::Namespace, |
17 | resolve::{Resolver, Resolution}, | 18 | resolve::{Resolver, Resolution}, |
18 | path::{ PathSegment, GenericArg}, | 19 | path::{PathSegment, GenericArg}, |
19 | generics::GenericParams, | 20 | generics::{GenericParams, HasGenericParams}, |
20 | adt::VariantDef, | 21 | adt::VariantDef, Trait |
21 | }; | 22 | }; |
22 | use super::{Ty, primitive, FnSig, Substs, TypeCtor}; | 23 | use super::{Ty, primitive, FnSig, Substs, TypeCtor, TraitRef}; |
23 | 24 | ||
24 | impl Ty { | 25 | impl Ty { |
25 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { | 26 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
@@ -115,7 +116,6 @@ impl Ty { | |||
115 | segment: &PathSegment, | 116 | segment: &PathSegment, |
116 | resolved: TypableDef, | 117 | resolved: TypableDef, |
117 | ) -> Substs { | 118 | ) -> Substs { |
118 | let mut substs = Vec::new(); | ||
119 | let def_generics = match resolved { | 119 | let def_generics = match resolved { |
120 | TypableDef::Function(func) => func.generic_params(db), | 120 | TypableDef::Function(func) => func.generic_params(db), |
121 | TypableDef::Struct(s) => s.generic_params(db), | 121 | TypableDef::Struct(s) => s.generic_params(db), |
@@ -124,28 +124,7 @@ impl Ty { | |||
124 | TypableDef::TypeAlias(t) => t.generic_params(db), | 124 | TypableDef::TypeAlias(t) => t.generic_params(db), |
125 | TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), | 125 | TypableDef::Const(_) | TypableDef::Static(_) => GenericParams::default().into(), |
126 | }; | 126 | }; |
127 | let parent_param_count = def_generics.count_parent_params(); | 127 | substs_from_path_segment(db, resolver, segment, &def_generics, false) |
128 | substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); | ||
129 | if let Some(generic_args) = &segment.args_and_bindings { | ||
130 | // if args are provided, it should be all of them, but we can't rely on that | ||
131 | let param_count = def_generics.params.len(); | ||
132 | for arg in generic_args.args.iter().take(param_count) { | ||
133 | match arg { | ||
134 | GenericArg::Type(type_ref) => { | ||
135 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
136 | substs.push(ty); | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | // add placeholders for args that were not provided | ||
142 | // FIXME: handle defaults | ||
143 | let supplied_params = substs.len(); | ||
144 | for _ in supplied_params..def_generics.count_params_including_parent() { | ||
145 | substs.push(Ty::Unknown); | ||
146 | } | ||
147 | assert_eq!(substs.len(), def_generics.count_params_including_parent()); | ||
148 | Substs(substs.into()) | ||
149 | } | 128 | } |
150 | 129 | ||
151 | /// Collect generic arguments from a path into a `Substs`. See also | 130 | /// Collect generic arguments from a path into a `Substs`. See also |
@@ -185,6 +164,82 @@ impl Ty { | |||
185 | } | 164 | } |
186 | } | 165 | } |
187 | 166 | ||
167 | pub(super) fn substs_from_path_segment( | ||
168 | db: &impl HirDatabase, | ||
169 | resolver: &Resolver, | ||
170 | segment: &PathSegment, | ||
171 | def_generics: &GenericParams, | ||
172 | add_self_param: bool, | ||
173 | ) -> Substs { | ||
174 | let mut substs = Vec::new(); | ||
175 | let parent_param_count = def_generics.count_parent_params(); | ||
176 | substs.extend(iter::repeat(Ty::Unknown).take(parent_param_count)); | ||
177 | if add_self_param { | ||
178 | // FIXME this add_self_param argument is kind of a hack: Traits have the | ||
179 | // Self type as an implicit first type parameter, but it can't be | ||
180 | // actually provided in the type arguments | ||
181 | // (well, actually sometimes it can, in the form of type-relative paths: `<Foo as Default>::default()`) | ||
182 | substs.push(Ty::Unknown); | ||
183 | } | ||
184 | if let Some(generic_args) = &segment.args_and_bindings { | ||
185 | // if args are provided, it should be all of them, but we can't rely on that | ||
186 | let self_param_correction = if add_self_param { 1 } else { 0 }; | ||
187 | let param_count = def_generics.params.len() - self_param_correction; | ||
188 | for arg in generic_args.args.iter().take(param_count) { | ||
189 | match arg { | ||
190 | GenericArg::Type(type_ref) => { | ||
191 | let ty = Ty::from_hir(db, resolver, type_ref); | ||
192 | substs.push(ty); | ||
193 | } | ||
194 | } | ||
195 | } | ||
196 | } | ||
197 | // add placeholders for args that were not provided | ||
198 | // FIXME: handle defaults | ||
199 | let supplied_params = substs.len(); | ||
200 | for _ in supplied_params..def_generics.count_params_including_parent() { | ||
201 | substs.push(Ty::Unknown); | ||
202 | } | ||
203 | assert_eq!(substs.len(), def_generics.count_params_including_parent()); | ||
204 | Substs(substs.into()) | ||
205 | } | ||
206 | |||
207 | impl TraitRef { | ||
208 | pub(crate) fn from_hir( | ||
209 | db: &impl HirDatabase, | ||
210 | resolver: &Resolver, | ||
211 | type_ref: &TypeRef, | ||
212 | explicit_self_ty: Option<Ty>, | ||
213 | ) -> Option<Self> { | ||
214 | let path = match type_ref { | ||
215 | TypeRef::Path(path) => path, | ||
216 | _ => return None, | ||
217 | }; | ||
218 | let resolved = match resolver.resolve_path(db, &path).take_types()? { | ||
219 | Resolution::Def(ModuleDef::Trait(tr)) => tr, | ||
220 | _ => return None, | ||
221 | }; | ||
222 | let mut substs = Self::substs_from_path(db, resolver, path, resolved); | ||
223 | if let Some(self_ty) = explicit_self_ty { | ||
224 | // FIXME this could be nicer | ||
225 | let mut substs_vec = substs.0.to_vec(); | ||
226 | substs_vec[0] = self_ty; | ||
227 | substs.0 = substs_vec.into(); | ||
228 | } | ||
229 | Some(TraitRef { trait_: resolved, substs }) | ||
230 | } | ||
231 | |||
232 | fn substs_from_path( | ||
233 | db: &impl HirDatabase, | ||
234 | resolver: &Resolver, | ||
235 | path: &Path, | ||
236 | resolved: Trait, | ||
237 | ) -> Substs { | ||
238 | let segment = path.segments.last().expect("path should have at least one segment"); | ||
239 | substs_from_path_segment(db, resolver, segment, &resolved.generic_params(db), true) | ||
240 | } | ||
241 | } | ||
242 | |||
188 | /// Build the declared type of an item. This depends on the namespace; e.g. for | 243 | /// Build the declared type of an item. This depends on the namespace; e.g. for |
189 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and | 244 | /// `struct Foo(usize)`, we have two types: The type of the struct itself, and |
190 | /// the constructor function `(usize) -> Foo` which lives in the values | 245 | /// the constructor function `(usize) -> Foo` which lives in the values |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index bb23246a6..6b7918187 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -10,10 +10,12 @@ use crate::{ | |||
10 | HirDatabase, Module, Crate, Name, Function, Trait, | 10 | HirDatabase, Module, Crate, Name, Function, Trait, |
11 | impl_block::{ImplId, ImplBlock, ImplItem}, | 11 | impl_block::{ImplId, ImplBlock, ImplItem}, |
12 | ty::{Ty, TypeCtor}, | 12 | ty::{Ty, TypeCtor}, |
13 | nameres::CrateModuleId, resolve::Resolver, traits::TraitItem | 13 | nameres::CrateModuleId, |
14 | 14 | resolve::Resolver, | |
15 | traits::TraitItem, | ||
16 | generics::HasGenericParams, | ||
15 | }; | 17 | }; |
16 | use super::{ TraitRef, Substs}; | 18 | use super::{TraitRef, Substs}; |
17 | 19 | ||
18 | /// This is used as a key for indexing impls. | 20 | /// This is used as a key for indexing impls. |
19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 21 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -72,9 +74,9 @@ impl CrateImplBlocks { | |||
72 | 74 | ||
73 | let target_ty = impl_block.target_ty(db); | 75 | let target_ty = impl_block.target_ty(db); |
74 | 76 | ||
75 | if let Some(tr) = impl_block.target_trait(db) { | 77 | if let Some(tr) = impl_block.target_trait_ref(db) { |
76 | self.impls_by_trait | 78 | self.impls_by_trait |
77 | .entry(tr) | 79 | .entry(tr.trait_) |
78 | .or_insert_with(Vec::new) | 80 | .or_insert_with(Vec::new) |
79 | .push((module.module_id, impl_id)); | 81 | .push((module.module_id, impl_id)); |
80 | } else { | 82 | } else { |
@@ -108,20 +110,6 @@ impl CrateImplBlocks { | |||
108 | } | 110 | } |
109 | } | 111 | } |
110 | 112 | ||
111 | /// Rudimentary check whether an impl exists for a given type and trait; this | ||
112 | /// will actually be done by chalk. | ||
113 | pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> bool { | ||
114 | // FIXME use all trait impls in the whole crate graph | ||
115 | let krate = trait_ref.trait_.module(db).krate(db); | ||
116 | let krate = match krate { | ||
117 | Some(krate) => krate, | ||
118 | None => return false, | ||
119 | }; | ||
120 | let crate_impl_blocks = db.impls_in_crate(krate); | ||
121 | let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_); | ||
122 | impl_blocks.any(|impl_block| &impl_block.target_ty(db) == trait_ref.self_ty()) | ||
123 | } | ||
124 | |||
125 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { | 113 | fn def_crate(db: &impl HirDatabase, ty: &Ty) -> Option<Crate> { |
126 | match ty { | 114 | match ty { |
127 | Ty::Apply(a_ty) => match a_ty.ctor { | 115 | Ty::Apply(a_ty) => match a_ty.ctor { |
@@ -142,6 +130,7 @@ impl Ty { | |||
142 | resolver: &Resolver, | 130 | resolver: &Resolver, |
143 | ) -> Option<(Ty, Function)> { | 131 | ) -> Option<(Ty, Function)> { |
144 | // FIXME: trait methods should be used before autoderefs | 132 | // FIXME: trait methods should be used before autoderefs |
133 | // (and we need to do autoderefs for trait method calls as well) | ||
145 | let inherent_method = self.clone().iterate_methods(db, |ty, f| { | 134 | let inherent_method = self.clone().iterate_methods(db, |ty, f| { |
146 | let sig = f.signature(db); | 135 | let sig = f.signature(db); |
147 | if sig.name() == name && sig.has_self_param() { | 136 | if sig.name() == name && sig.has_self_param() { |
@@ -174,22 +163,15 @@ impl Ty { | |||
174 | } | 163 | } |
175 | } | 164 | } |
176 | } | 165 | } |
177 | // FIXME: | ||
178 | // - we might not actually be able to determine fully that the type | ||
179 | // implements the trait here; it's enough if we (well, Chalk) determine | ||
180 | // that it's possible. | ||
181 | // - when the trait method is picked, we need to register an | ||
182 | // 'obligation' somewhere so that we later check that it's really | ||
183 | // implemented | ||
184 | // - both points go for additional requirements from where clauses as | ||
185 | // well (in fact, the 'implements' condition could just be considered a | ||
186 | // 'where Self: Trait' clause) | ||
187 | candidates.retain(|(t, _m)| { | 166 | candidates.retain(|(t, _m)| { |
188 | let trait_ref = TraitRef { trait_: *t, substs: Substs::single(self.clone()) }; | 167 | let trait_ref = |
189 | db.implements(trait_ref) | 168 | TraitRef { trait_: *t, substs: fresh_substs_for_trait(db, *t, self.clone()) }; |
169 | let (trait_ref, _) = super::traits::canonicalize(trait_ref); | ||
170 | db.implements(trait_ref).is_some() | ||
190 | }); | 171 | }); |
191 | // FIXME if there's multiple candidates here, that's an ambiguity error | 172 | // FIXME if there's multiple candidates here, that's an ambiguity error |
192 | let (_chosen_trait, chosen_method) = candidates.first()?; | 173 | let (_chosen_trait, chosen_method) = candidates.first()?; |
174 | // FIXME return correct receiver type | ||
193 | Some((self.clone(), *chosen_method)) | 175 | Some((self.clone(), *chosen_method)) |
194 | } | 176 | } |
195 | 177 | ||
@@ -252,3 +234,17 @@ impl Ty { | |||
252 | None | 234 | None |
253 | } | 235 | } |
254 | } | 236 | } |
237 | |||
238 | /// This creates Substs for a trait with the given Self type and type variables | ||
239 | /// for all other parameters. This is kind of a hack since these aren't 'real' | ||
240 | /// type variables; the resulting trait reference is just used for the | ||
241 | /// preliminary method candidate check. | ||
242 | fn fresh_substs_for_trait(db: &impl HirDatabase, tr: Trait, self_ty: Ty) -> Substs { | ||
243 | let mut substs = Vec::new(); | ||
244 | let generics = tr.generic_params(db); | ||
245 | substs.push(self_ty); | ||
246 | substs.extend(generics.params_including_parent().into_iter().skip(1).enumerate().map( | ||
247 | |(i, _p)| Ty::Infer(super::infer::InferTy::TypeVar(super::infer::TypeVarId(i as u32))), | ||
248 | )); | ||
249 | substs.into() | ||
250 | } | ||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index d7c2ca132..291bc9ae5 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -1926,8 +1926,8 @@ fn test() { | |||
1926 | } | 1926 | } |
1927 | "#), | 1927 | "#), |
1928 | @r###" | 1928 | @r###" |
1929 | [31; 35) 'self': &{unknown} | 1929 | [31; 35) 'self': &Self |
1930 | [110; 114) 'self': &{unknown} | 1930 | [110; 114) 'self': &Self |
1931 | [170; 228) '{ ...i128 }': () | 1931 | [170; 228) '{ ...i128 }': () |
1932 | [176; 178) 'S1': S1 | 1932 | [176; 178) 'S1': S1 |
1933 | [176; 187) 'S1.method()': u32 | 1933 | [176; 187) 'S1.method()': u32 |
@@ -1972,8 +1972,8 @@ mod bar_test { | |||
1972 | } | 1972 | } |
1973 | "#), | 1973 | "#), |
1974 | @r###" | 1974 | @r###" |
1975 | [63; 67) 'self': &{unknown} | 1975 | [63; 67) 'self': &Self |
1976 | [169; 173) 'self': &{unknown} | 1976 | [169; 173) 'self': &Self |
1977 | [300; 337) '{ ... }': () | 1977 | [300; 337) '{ ... }': () |
1978 | [310; 311) 'S': S | 1978 | [310; 311) 'S': S |
1979 | [310; 320) 'S.method()': u32 | 1979 | [310; 320) 'S.method()': u32 |
@@ -1998,10 +1998,45 @@ fn test() { | |||
1998 | } | 1998 | } |
1999 | "#), | 1999 | "#), |
2000 | @r###" | 2000 | @r###" |
2001 | [33; 37) 'self': &{unknown} | 2001 | [33; 37) 'self': &Self |
2002 | [92; 111) '{ ...d(); }': () | 2002 | [92; 111) '{ ...d(); }': () |
2003 | [98; 99) 'S': S | 2003 | [98; 99) 'S': S |
2004 | [98; 108) 'S.method()': {unknown}"### | 2004 | [98; 108) 'S.method()': u32"### |
2005 | ); | ||
2006 | } | ||
2007 | |||
2008 | #[test] | ||
2009 | fn infer_trait_method_generic_more_params() { | ||
2010 | // the trait implementation is intentionally incomplete -- it shouldn't matter | ||
2011 | assert_snapshot_matches!( | ||
2012 | infer(r#" | ||
2013 | trait Trait<T1, T2, T3> { | ||
2014 | fn method1(&self) -> (T1, T2, T3); | ||
2015 | fn method2(&self) -> (T3, T2, T1); | ||
2016 | } | ||
2017 | struct S1; | ||
2018 | impl Trait<u8, u16, u32> for S1 {} | ||
2019 | struct S2; | ||
2020 | impl<T> Trait<i8, i16, T> for S2 {} | ||
2021 | fn test() { | ||
2022 | S1.method1(); // u8, u16, u32 | ||
2023 | S1.method2(); // u32, u16, u8 | ||
2024 | S2.method1(); // i8, i16, {unknown} | ||
2025 | S2.method2(); // {unknown}, i16, i8 | ||
2026 | } | ||
2027 | "#), | ||
2028 | @r###" | ||
2029 | [43; 47) 'self': &Self | ||
2030 | [82; 86) 'self': &Self | ||
2031 | [210; 361) '{ ..., i8 }': () | ||
2032 | [216; 218) 'S1': S1 | ||
2033 | [216; 228) 'S1.method1()': (u8, u16, u32) | ||
2034 | [250; 252) 'S1': S1 | ||
2035 | [250; 262) 'S1.method2()': (u32, u16, u8) | ||
2036 | [284; 286) 'S2': S2 | ||
2037 | [284; 296) 'S2.method1()': (i8, i16, {unknown}) | ||
2038 | [324; 326) 'S2': S2 | ||
2039 | [324; 336) 'S2.method2()': ({unknown}, i16, i8)"### | ||
2005 | ); | 2040 | ); |
2006 | } | 2041 | } |
2007 | 2042 | ||
@@ -2020,7 +2055,7 @@ fn test() { | |||
2020 | } | 2055 | } |
2021 | "#), | 2056 | "#), |
2022 | @r###" | 2057 | @r###" |
2023 | [33; 37) 'self': &{unknown} | 2058 | [33; 37) 'self': &Self |
2024 | [102; 127) '{ ...d(); }': () | 2059 | [102; 127) '{ ...d(); }': () |
2025 | [108; 109) 'S': S<u32>(T) -> S<T> | 2060 | [108; 109) 'S': S<u32>(T) -> S<T> |
2026 | [108; 115) 'S(1u32)': S<u32> | 2061 | [108; 115) 'S(1u32)': S<u32> |
@@ -2168,7 +2203,7 @@ fn test() { | |||
2168 | } | 2203 | } |
2169 | "#), | 2204 | "#), |
2170 | @r###" | 2205 | @r###" |
2171 | [29; 33) 'self': {unknown} | 2206 | [29; 33) 'self': Self |
2172 | [107; 198) '{ ...(S); }': () | 2207 | [107; 198) '{ ...(S); }': () |
2173 | [117; 118) 'x': u32 | 2208 | [117; 118) 'x': u32 |
2174 | [126; 127) 'S': S | 2209 | [126; 127) 'S': S |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs new file mode 100644 index 000000000..f8c3958bd --- /dev/null +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -0,0 +1,112 @@ | |||
1 | //! Stuff that will probably mostly replaced by Chalk. | ||
2 | use std::collections::HashMap; | ||
3 | |||
4 | use crate::db::HirDatabase; | ||
5 | use super::{ TraitRef, Substs, infer::{ TypeVarId, InferTy}, Ty}; | ||
6 | |||
7 | // Copied (and simplified) from Chalk | ||
8 | |||
9 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
10 | /// A (possible) solution for a proposed goal. Usually packaged in a `Result`, | ||
11 | /// where `Err` represents definite *failure* to prove a goal. | ||
12 | pub enum Solution { | ||
13 | /// The goal indeed holds, and there is a unique value for all existential | ||
14 | /// variables. | ||
15 | Unique(Substs), | ||
16 | |||
17 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
18 | /// for type inference. | ||
19 | Ambig(Guidance), | ||
20 | } | ||
21 | |||
22 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
23 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
24 | /// solutions), we issue a set of *guidance* back to type inference. | ||
25 | pub enum Guidance { | ||
26 | /// The existential variables *must* have the given values if the goal is | ||
27 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
28 | /// actually hold. | ||
29 | Definite(Substs), | ||
30 | |||
31 | /// There are multiple plausible values for the existentials, but the ones | ||
32 | /// here are suggested as the preferred choice heuristically. These should | ||
33 | /// be used for inference fallback only. | ||
34 | Suggested(Substs), | ||
35 | |||
36 | /// There's no useful information to feed back to type inference | ||
37 | Unknown, | ||
38 | } | ||
39 | |||
40 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
41 | /// a certain type implements a certain trait. Proving the Obligation might | ||
42 | /// result in additional information about inference variables. | ||
43 | /// | ||
44 | /// This might be handled by Chalk when we integrate it? | ||
45 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
46 | pub enum Obligation { | ||
47 | /// Prove that a certain type implements a trait (the type is the `Self` type | ||
48 | /// parameter to the `TraitRef`). | ||
49 | Trait(TraitRef), | ||
50 | } | ||
51 | |||
52 | /// Rudimentary check whether an impl exists for a given type and trait; this | ||
53 | /// will actually be done by chalk. | ||
54 | pub(crate) fn implements(db: &impl HirDatabase, trait_ref: TraitRef) -> Option<Solution> { | ||
55 | // FIXME use all trait impls in the whole crate graph | ||
56 | let krate = trait_ref.trait_.module(db).krate(db); | ||
57 | let krate = match krate { | ||
58 | Some(krate) => krate, | ||
59 | None => return None, | ||
60 | }; | ||
61 | let crate_impl_blocks = db.impls_in_crate(krate); | ||
62 | let mut impl_blocks = crate_impl_blocks.lookup_impl_blocks_for_trait(&trait_ref.trait_); | ||
63 | impl_blocks | ||
64 | .find_map(|impl_block| unify_trait_refs(&trait_ref, &impl_block.target_trait_ref(db)?)) | ||
65 | } | ||
66 | |||
67 | pub(super) fn canonicalize(trait_ref: TraitRef) -> (TraitRef, Vec<TypeVarId>) { | ||
68 | let mut canonical = HashMap::new(); // mapping uncanonical -> canonical | ||
69 | let mut uncanonical = Vec::new(); // mapping canonical -> uncanonical (which is dense) | ||
70 | let mut substs = trait_ref.substs.0.to_vec(); | ||
71 | for ty in &mut substs { | ||
72 | ty.walk_mut(&mut |ty| match ty { | ||
73 | Ty::Infer(InferTy::TypeVar(tv)) => { | ||
74 | let tv: &mut TypeVarId = tv; | ||
75 | *tv = *canonical.entry(*tv).or_insert_with(|| { | ||
76 | let i = uncanonical.len(); | ||
77 | uncanonical.push(*tv); | ||
78 | TypeVarId(i as u32) | ||
79 | }); | ||
80 | } | ||
81 | _ => {} | ||
82 | }); | ||
83 | } | ||
84 | (TraitRef { substs: substs.into(), ..trait_ref }, uncanonical) | ||
85 | } | ||
86 | |||
87 | fn unify_trait_refs(tr1: &TraitRef, tr2: &TraitRef) -> Option<Solution> { | ||
88 | if tr1.trait_ != tr2.trait_ { | ||
89 | return None; | ||
90 | } | ||
91 | let mut solution_substs = Vec::new(); | ||
92 | for (t1, t2) in tr1.substs.0.iter().zip(tr2.substs.0.iter()) { | ||
93 | // this is very bad / hacky 'unification' logic, just enough to make the simple tests pass | ||
94 | match (t1, t2) { | ||
95 | (_, Ty::Infer(InferTy::TypeVar(_))) | (_, Ty::Unknown) | (_, Ty::Param { .. }) => { | ||
96 | // type variable (or similar) in the impl, we just assume it works | ||
97 | } | ||
98 | (Ty::Infer(InferTy::TypeVar(v1)), _) => { | ||
99 | // type variable in the query and fixed type in the impl, record its value | ||
100 | solution_substs.resize_with(v1.0 as usize + 1, || Ty::Unknown); | ||
101 | solution_substs[v1.0 as usize] = t2.clone(); | ||
102 | } | ||
103 | _ => { | ||
104 | // check that they're equal (actually we'd have to recurse etc.) | ||
105 | if t1 != t2 { | ||
106 | return None; | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | Some(Solution::Unique(solution_substs.into())) | ||
112 | } | ||
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 517dffbca..40a2bd148 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -104,7 +104,7 @@ pub(crate) fn reference_definition( | |||
104 | } | 104 | } |
105 | } | 105 | } |
106 | hir::PathResolution::AssocItem(assoc) => { | 106 | hir::PathResolution::AssocItem(assoc) => { |
107 | return Exact(NavigationTarget::from_impl_item(db, assoc)) | 107 | return Exact(NavigationTarget::from_impl_item(db, assoc)); |
108 | } | 108 | } |
109 | } | 109 | } |
110 | } | 110 | } |
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index a21ea4dbc..a530f3b03 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -39,7 +39,7 @@ pub enum ExpandError { | |||
39 | BindingError(String), | 39 | BindingError(String), |
40 | } | 40 | } |
41 | 41 | ||
42 | pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list}; | 42 | pub use crate::syntax_bridge::{ast_to_token_tree, token_tree_to_ast_item_list, syntax_node_to_token_tree}; |
43 | 43 | ||
44 | /// This struct contains AST for a single `macro_rules` definition. What might | 44 | /// This struct contains AST for a single `macro_rules` definition. What might |
45 | /// be very confusing is that AST has almost exactly the same shape as | 45 | /// be very confusing is that AST has almost exactly the same shape as |
@@ -189,9 +189,26 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
189 | rules.expand(&invocation_tt).unwrap() | 189 | rules.expand(&invocation_tt).unwrap() |
190 | } | 190 | } |
191 | 191 | ||
192 | pub(crate) fn expand_to_syntax( | ||
193 | rules: &MacroRules, | ||
194 | invocation: &str, | ||
195 | ) -> ra_syntax::TreeArc<ast::SourceFile> { | ||
196 | let expanded = expand(rules, invocation); | ||
197 | token_tree_to_ast_item_list(&expanded) | ||
198 | } | ||
199 | |||
192 | pub(crate) fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { | 200 | pub(crate) fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) { |
193 | let expanded = expand(rules, invocation); | 201 | let expanded = expand(rules, invocation); |
194 | assert_eq!(expanded.to_string(), expansion); | 202 | assert_eq!(expanded.to_string(), expansion); |
203 | |||
204 | let tree = token_tree_to_ast_item_list(&expanded); | ||
205 | |||
206 | // Eat all white space by parse it back and forth | ||
207 | let expansion = ast::SourceFile::parse(expansion); | ||
208 | let expansion = syntax_node_to_token_tree(expansion.syntax()).unwrap().0; | ||
209 | let file = token_tree_to_ast_item_list(&expansion); | ||
210 | |||
211 | assert_eq!(tree.syntax().debug_dump().trim(), file.syntax().debug_dump().trim()); | ||
195 | } | 212 | } |
196 | 213 | ||
197 | #[test] | 214 | #[test] |
@@ -288,6 +305,36 @@ impl_froms!(TokenTree: Leaf, Subtree); | |||
288 | } | 305 | } |
289 | 306 | ||
290 | #[test] | 307 | #[test] |
308 | fn test_match_group_pattern_with_multiple_defs() { | ||
309 | let rules = create_rules( | ||
310 | r#" | ||
311 | macro_rules! foo { | ||
312 | ($ ($ i:ident),*) => ( struct Bar { $ ( | ||
313 | fn $ i {} | ||
314 | )*} ); | ||
315 | } | ||
316 | "#, | ||
317 | ); | ||
318 | |||
319 | assert_expansion(&rules, "foo! { foo, bar }", "struct Bar {fn foo {} fn bar {}}"); | ||
320 | } | ||
321 | |||
322 | #[test] | ||
323 | fn test_match_group_pattern_with_multiple_statement() { | ||
324 | let rules = create_rules( | ||
325 | r#" | ||
326 | macro_rules! foo { | ||
327 | ($ ($ i:ident),*) => ( fn baz { $ ( | ||
328 | $ i (); | ||
329 | )*} ); | ||
330 | } | ||
331 | "#, | ||
332 | ); | ||
333 | |||
334 | assert_expansion(&rules, "foo! { foo, bar }", "fn baz {foo () ; bar () ;}"); | ||
335 | } | ||
336 | |||
337 | #[test] | ||
291 | fn expand_to_item_list() { | 338 | fn expand_to_item_list() { |
292 | let rules = create_rules( | 339 | let rules = create_rules( |
293 | " | 340 | " |
@@ -415,7 +462,7 @@ SOURCE_FILE@[0; 40) | |||
415 | assert_expansion( | 462 | assert_expansion( |
416 | &rules, | 463 | &rules, |
417 | "foo! { bar::<u8>::baz::<u8> }", | 464 | "foo! { bar::<u8>::baz::<u8> }", |
418 | "fn foo () {let a = bar ::< u8 > ::baz ::< u8 > ;}", | 465 | "fn foo () {let a = bar :: < u8 > :: baz :: < u8 > ;}", |
419 | ); | 466 | ); |
420 | } | 467 | } |
421 | 468 | ||
@@ -432,4 +479,107 @@ SOURCE_FILE@[0; 40) | |||
432 | ); | 479 | ); |
433 | assert_expansion(&rules, "foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); | 480 | assert_expansion(&rules, "foo! { foo, bar }", "fn foo () {let a = foo ; let b = bar ;}"); |
434 | } | 481 | } |
482 | |||
483 | #[test] | ||
484 | fn test_path_with_path() { | ||
485 | let rules = create_rules( | ||
486 | r#" | ||
487 | macro_rules! foo { | ||
488 | ($ i:path) => { | ||
489 | fn foo() { let a = $ i :: bar; } | ||
490 | } | ||
491 | } | ||
492 | "#, | ||
493 | ); | ||
494 | assert_expansion(&rules, "foo! { foo }", "fn foo () {let a = foo :: bar ;}"); | ||
495 | } | ||
496 | |||
497 | #[test] | ||
498 | fn test_expr() { | ||
499 | let rules = create_rules( | ||
500 | r#" | ||
501 | macro_rules! foo { | ||
502 | ($ i:expr) => { | ||
503 | fn bar() { $ i; } | ||
504 | } | ||
505 | } | ||
506 | "#, | ||
507 | ); | ||
508 | |||
509 | assert_expansion( | ||
510 | &rules, | ||
511 | "foo! { 2 + 2 * baz(3).quux() }", | ||
512 | "fn bar () {2 + 2 * baz (3) . quux () ;}", | ||
513 | ); | ||
514 | } | ||
515 | |||
516 | #[test] | ||
517 | fn test_expr_order() { | ||
518 | let rules = create_rules( | ||
519 | r#" | ||
520 | macro_rules! foo { | ||
521 | ($ i:expr) => { | ||
522 | fn bar() { $ i * 2; } | ||
523 | } | ||
524 | } | ||
525 | "#, | ||
526 | ); | ||
527 | |||
528 | assert_eq!( | ||
529 | expand_to_syntax(&rules, "foo! { 1 + 1 }").syntax().debug_dump().trim(), | ||
530 | r#"SOURCE_FILE@[0; 15) | ||
531 | FN_DEF@[0; 15) | ||
532 | FN_KW@[0; 2) "fn" | ||
533 | NAME@[2; 5) | ||
534 | IDENT@[2; 5) "bar" | ||
535 | PARAM_LIST@[5; 7) | ||
536 | L_PAREN@[5; 6) "(" | ||
537 | R_PAREN@[6; 7) ")" | ||
538 | BLOCK@[7; 15) | ||
539 | L_CURLY@[7; 8) "{" | ||
540 | EXPR_STMT@[8; 14) | ||
541 | BIN_EXPR@[8; 13) | ||
542 | BIN_EXPR@[8; 11) | ||
543 | LITERAL@[8; 9) | ||
544 | INT_NUMBER@[8; 9) "1" | ||
545 | PLUS@[9; 10) "+" | ||
546 | LITERAL@[10; 11) | ||
547 | INT_NUMBER@[10; 11) "1" | ||
548 | STAR@[11; 12) "*" | ||
549 | LITERAL@[12; 13) | ||
550 | INT_NUMBER@[12; 13) "2" | ||
551 | SEMI@[13; 14) ";" | ||
552 | R_CURLY@[14; 15) "}""#, | ||
553 | ); | ||
554 | } | ||
555 | |||
556 | #[test] | ||
557 | fn test_ty() { | ||
558 | let rules = create_rules( | ||
559 | r#" | ||
560 | macro_rules! foo { | ||
561 | ($ i:ty) => ( | ||
562 | fn bar() -> $ i { unimplemented!() } | ||
563 | ) | ||
564 | } | ||
565 | "#, | ||
566 | ); | ||
567 | assert_expansion( | ||
568 | &rules, | ||
569 | "foo! { Baz<u8> }", | ||
570 | "fn bar () -> Baz < u8 > {unimplemented ! ()}", | ||
571 | ); | ||
572 | } | ||
573 | |||
574 | #[test] | ||
575 | fn test_pat_() { | ||
576 | let rules = create_rules( | ||
577 | r#" | ||
578 | macro_rules! foo { | ||
579 | ($ i:pat) => { fn foo() { let $ i; } } | ||
580 | } | ||
581 | "#, | ||
582 | ); | ||
583 | assert_expansion(&rules, "foo! { (a, b) }", "fn foo () {let (a , b) ;}"); | ||
584 | } | ||
435 | } | 585 | } |
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs index ce41d7225..7a259f338 100644 --- a/crates/ra_mbe/src/mbe_expander.rs +++ b/crates/ra_mbe/src/mbe_expander.rs | |||
@@ -144,6 +144,19 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings, | |||
144 | input.eat_path().ok_or(ExpandError::UnexpectedToken)?.clone(); | 144 | input.eat_path().ok_or(ExpandError::UnexpectedToken)?.clone(); |
145 | res.inner.insert(text.clone(), Binding::Simple(path.into())); | 145 | res.inner.insert(text.clone(), Binding::Simple(path.into())); |
146 | } | 146 | } |
147 | "expr" => { | ||
148 | let expr = | ||
149 | input.eat_expr().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
150 | res.inner.insert(text.clone(), Binding::Simple(expr.into())); | ||
151 | } | ||
152 | "ty" => { | ||
153 | let ty = input.eat_ty().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
154 | res.inner.insert(text.clone(), Binding::Simple(ty.into())); | ||
155 | } | ||
156 | "pat" => { | ||
157 | let pat = input.eat_pat().ok_or(ExpandError::UnexpectedToken)?.clone(); | ||
158 | res.inner.insert(text.clone(), Binding::Simple(pat.into())); | ||
159 | } | ||
147 | _ => return Err(ExpandError::UnexpectedToken), | 160 | _ => return Err(ExpandError::UnexpectedToken), |
148 | } | 161 | } |
149 | } | 162 | } |
diff --git a/crates/ra_mbe/src/subtree_parser.rs b/crates/ra_mbe/src/subtree_parser.rs index ce39a40bb..13d5d2169 100644 --- a/crates/ra_mbe/src/subtree_parser.rs +++ b/crates/ra_mbe/src/subtree_parser.rs | |||
@@ -30,12 +30,23 @@ impl<'a> Parser<'a> { | |||
30 | self.parse(ra_parser::parse_path) | 30 | self.parse(ra_parser::parse_path) |
31 | } | 31 | } |
32 | 32 | ||
33 | pub fn parse_expr(self) -> Option<tt::TokenTree> { | ||
34 | self.parse(ra_parser::parse_expr) | ||
35 | } | ||
36 | |||
37 | pub fn parse_ty(self) -> Option<tt::TokenTree> { | ||
38 | self.parse(ra_parser::parse_ty) | ||
39 | } | ||
40 | |||
41 | pub fn parse_pat(self) -> Option<tt::TokenTree> { | ||
42 | self.parse(ra_parser::parse_pat) | ||
43 | } | ||
44 | |||
33 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> | 45 | fn parse<F>(self, f: F) -> Option<tt::TokenTree> |
34 | where | 46 | where |
35 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), | 47 | F: FnOnce(&dyn TokenSource, &mut dyn TreeSink), |
36 | { | 48 | { |
37 | let mut src = SubtreeTokenSource::new(self.subtree); | 49 | let mut src = SubtreeTokenSource::new(&self.subtree.token_trees[*self.cur_pos..]); |
38 | src.start_from_nth(*self.cur_pos); | ||
39 | let mut sink = OffsetTokenSink { token_pos: 0 }; | 50 | let mut sink = OffsetTokenSink { token_pos: 0 }; |
40 | 51 | ||
41 | f(&src, &mut sink); | 52 | f(&src, &mut sink); |
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 4b37c2bda..0a070b46a 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs | |||
@@ -2,6 +2,64 @@ use ra_parser::{TokenSource}; | |||
2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*}; | 2 | use ra_syntax::{classify_literal, SmolStr, SyntaxKind, SyntaxKind::*}; |
3 | use std::cell::{RefCell}; | 3 | use std::cell::{RefCell}; |
4 | 4 | ||
5 | // A Sequece of Token, | ||
6 | #[derive(Debug, Clone, Eq, PartialEq)] | ||
7 | pub(super) enum TokenSeq<'a> { | ||
8 | Subtree(&'a tt::Subtree), | ||
9 | Seq(&'a [tt::TokenTree]), | ||
10 | } | ||
11 | |||
12 | impl<'a> From<&'a tt::Subtree> for TokenSeq<'a> { | ||
13 | fn from(s: &'a tt::Subtree) -> TokenSeq<'a> { | ||
14 | TokenSeq::Subtree(s) | ||
15 | } | ||
16 | } | ||
17 | |||
18 | impl<'a> From<&'a [tt::TokenTree]> for TokenSeq<'a> { | ||
19 | fn from(s: &'a [tt::TokenTree]) -> TokenSeq<'a> { | ||
20 | TokenSeq::Seq(s) | ||
21 | } | ||
22 | } | ||
23 | |||
24 | enum DelimToken<'a> { | ||
25 | Delim(&'a tt::Delimiter, bool), | ||
26 | Token(&'a tt::TokenTree), | ||
27 | End, | ||
28 | } | ||
29 | |||
30 | impl<'a> TokenSeq<'a> { | ||
31 | fn get(&self, pos: usize) -> DelimToken<'a> { | ||
32 | match self { | ||
33 | TokenSeq::Subtree(subtree) => { | ||
34 | let len = subtree.token_trees.len() + 2; | ||
35 | match pos { | ||
36 | p if p >= len => DelimToken::End, | ||
37 | p if p == len - 1 => DelimToken::Delim(&subtree.delimiter, true), | ||
38 | 0 => DelimToken::Delim(&subtree.delimiter, false), | ||
39 | p => DelimToken::Token(&subtree.token_trees[p - 1]), | ||
40 | } | ||
41 | } | ||
42 | TokenSeq::Seq(tokens) => { | ||
43 | tokens.get(pos).map(DelimToken::Token).unwrap_or(DelimToken::End) | ||
44 | } | ||
45 | } | ||
46 | } | ||
47 | |||
48 | fn len(&self) -> usize { | ||
49 | match self { | ||
50 | TokenSeq::Subtree(subtree) => subtree.token_trees.len() + 2, | ||
51 | TokenSeq::Seq(tokens) => tokens.len(), | ||
52 | } | ||
53 | } | ||
54 | |||
55 | fn child_slice(&self) -> &[tt::TokenTree] { | ||
56 | match self { | ||
57 | TokenSeq::Subtree(subtree) => &subtree.token_trees, | ||
58 | TokenSeq::Seq(tokens) => &tokens, | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
5 | #[derive(Debug, Clone, Eq, PartialEq)] | 63 | #[derive(Debug, Clone, Eq, PartialEq)] |
6 | struct TtToken { | 64 | struct TtToken { |
7 | pub kind: SyntaxKind, | 65 | pub kind: SyntaxKind, |
@@ -12,29 +70,27 @@ struct TtToken { | |||
12 | 70 | ||
13 | #[derive(Debug, Clone, Eq, PartialEq)] | 71 | #[derive(Debug, Clone, Eq, PartialEq)] |
14 | enum WalkCursor { | 72 | enum WalkCursor { |
15 | DelimiterBegin(Option<TtToken>), | 73 | Token(usize, TtToken), |
16 | Token(usize, Option<TtToken>), | ||
17 | DelimiterEnd(Option<TtToken>), | ||
18 | Eof, | 74 | Eof, |
19 | } | 75 | } |
20 | 76 | ||
21 | #[derive(Debug)] | 77 | #[derive(Debug)] |
22 | struct SubTreeWalker<'a> { | 78 | struct SubTreeWalker<'a> { |
23 | pos: usize, | 79 | pos: usize, |
24 | stack: Vec<(&'a tt::Subtree, Option<usize>)>, | 80 | stack: Vec<(TokenSeq<'a>, usize)>, |
25 | cursor: WalkCursor, | 81 | cursor: WalkCursor, |
26 | last_steps: Vec<usize>, | 82 | last_steps: Vec<usize>, |
27 | subtree: &'a tt::Subtree, | 83 | ts: TokenSeq<'a>, |
28 | } | 84 | } |
29 | 85 | ||
30 | impl<'a> SubTreeWalker<'a> { | 86 | impl<'a> SubTreeWalker<'a> { |
31 | fn new(subtree: &tt::Subtree) -> SubTreeWalker { | 87 | fn new(ts: TokenSeq<'a>) -> SubTreeWalker { |
32 | let mut res = SubTreeWalker { | 88 | let mut res = SubTreeWalker { |
33 | pos: 0, | 89 | pos: 0, |
34 | stack: vec![], | 90 | stack: vec![], |
35 | cursor: WalkCursor::Eof, | 91 | cursor: WalkCursor::Eof, |
36 | last_steps: vec![], | 92 | last_steps: vec![], |
37 | subtree, | 93 | ts, |
38 | }; | 94 | }; |
39 | 95 | ||
40 | res.reset(); | 96 | res.reset(); |
@@ -47,209 +103,108 @@ impl<'a> SubTreeWalker<'a> { | |||
47 | 103 | ||
48 | fn reset(&mut self) { | 104 | fn reset(&mut self) { |
49 | self.pos = 0; | 105 | self.pos = 0; |
50 | self.stack = vec![(self.subtree, None)]; | 106 | self.stack = vec![]; |
51 | self.cursor = WalkCursor::DelimiterBegin(convert_delim(self.subtree.delimiter, false)); | ||
52 | self.last_steps = vec![]; | 107 | self.last_steps = vec![]; |
53 | 108 | ||
54 | while self.is_empty_delimiter() { | 109 | self.cursor = match self.ts.get(0) { |
55 | self.forward_unchecked(); | 110 | DelimToken::Token(token) => match token { |
56 | } | 111 | tt::TokenTree::Subtree(subtree) => { |
57 | } | 112 | let ts = TokenSeq::from(subtree); |
58 | 113 | self.stack.push((ts, 0)); | |
59 | // This funciton will fast forward the cursor, | 114 | WalkCursor::Token(0, convert_delim(subtree.delimiter, false)) |
60 | // Such that backward will stop at `start_pos` point | 115 | } |
61 | fn start_from_nth(&mut self, start_pos: usize) { | 116 | tt::TokenTree::Leaf(leaf) => { |
62 | self.reset(); | 117 | let next_tokens = self.ts.child_slice(); |
63 | self.pos = start_pos; | 118 | WalkCursor::Token(0, convert_leaf(&next_tokens, leaf)) |
64 | self.cursor = self.walk_token(start_pos, 0, false); | 119 | } |
65 | 120 | }, | |
66 | while self.is_empty_delimiter() { | 121 | DelimToken::Delim(delim, is_end) => { |
67 | self.forward_unchecked(); | 122 | assert!(!is_end); |
123 | WalkCursor::Token(0, convert_delim(*delim, false)) | ||
124 | } | ||
125 | DelimToken::End => WalkCursor::Eof, | ||
68 | } | 126 | } |
69 | } | 127 | } |
70 | 128 | ||
71 | fn current(&self) -> Option<&TtToken> { | 129 | fn current(&self) -> Option<&TtToken> { |
72 | match &self.cursor { | 130 | match &self.cursor { |
73 | WalkCursor::DelimiterBegin(t) => t.as_ref(), | 131 | WalkCursor::Token(_, t) => Some(t), |
74 | WalkCursor::Token(_, t) => t.as_ref(), | ||
75 | WalkCursor::DelimiterEnd(t) => t.as_ref(), | ||
76 | WalkCursor::Eof => None, | 132 | WalkCursor::Eof => None, |
77 | } | 133 | } |
78 | } | 134 | } |
79 | 135 | ||
80 | fn is_empty_delimiter(&self) -> bool { | 136 | fn top(&self) -> &TokenSeq { |
81 | match &self.cursor { | 137 | self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts) |
82 | WalkCursor::DelimiterBegin(None) => true, | ||
83 | WalkCursor::DelimiterEnd(None) => true, | ||
84 | _ => false, | ||
85 | } | ||
86 | } | 138 | } |
87 | 139 | ||
88 | /// Move cursor backward by 1 step with empty checking | 140 | /// Move cursor backward by 1 step |
89 | fn backward(&mut self) { | 141 | fn backward(&mut self) { |
90 | if self.last_steps.is_empty() { | 142 | if self.last_steps.is_empty() { |
91 | return; | 143 | return; |
92 | } | 144 | } |
145 | |||
93 | self.pos -= 1; | 146 | self.pos -= 1; |
94 | loop { | 147 | let last_step = self.last_steps.pop().unwrap(); |
95 | self.backward_unchecked(); | ||
96 | // Skip Empty delimiter | ||
97 | if self.last_steps.is_empty() || !self.is_empty_delimiter() { | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | 148 | ||
102 | // Move forward if it is empty delimiter | 149 | self.cursor = match self.cursor { |
103 | if self.last_steps.is_empty() { | 150 | WalkCursor::Token(idx, _) => self.walk_token(idx, last_step, true), |
104 | while self.is_empty_delimiter() { | 151 | WalkCursor::Eof => { |
105 | self.forward_unchecked(); | 152 | let len = self.top().len(); |
153 | self.walk_token(len, last_step, true) | ||
106 | } | 154 | } |
107 | } | 155 | } |
108 | } | 156 | } |
109 | 157 | ||
110 | /// Move cursor backward by 1 step without empty check | 158 | /// Move cursor forward by 1 step |
111 | /// | ||
112 | /// Depends on the current state of cursor: | ||
113 | /// | ||
114 | /// * Delimiter Begin => Pop the stack, goto last walking token (`walk_token`) | ||
115 | /// * Token => Goto prev token (`walk_token`) | ||
116 | /// * Delimiter End => Goto the last child token (`walk_token`) | ||
117 | /// * Eof => push the root subtree, and set it as Delimiter End | ||
118 | fn backward_unchecked(&mut self) { | ||
119 | if self.last_steps.is_empty() { | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | let last_step = self.last_steps.pop().unwrap(); | ||
124 | let do_walk_token = match self.cursor { | ||
125 | WalkCursor::DelimiterBegin(_) => None, | ||
126 | WalkCursor::Token(u, _) => Some(u), | ||
127 | WalkCursor::DelimiterEnd(_) => { | ||
128 | let (top, _) = self.stack.last().unwrap(); | ||
129 | Some(top.token_trees.len()) | ||
130 | } | ||
131 | WalkCursor::Eof => None, | ||
132 | }; | ||
133 | |||
134 | self.cursor = match do_walk_token { | ||
135 | Some(u) => self.walk_token(u, last_step, true), | ||
136 | None => match self.cursor { | ||
137 | WalkCursor::Eof => { | ||
138 | self.stack.push((self.subtree, None)); | ||
139 | WalkCursor::DelimiterEnd(convert_delim( | ||
140 | self.stack.last().unwrap().0.delimiter, | ||
141 | true, | ||
142 | )) | ||
143 | } | ||
144 | _ => { | ||
145 | let (_, last_top_cursor) = self.stack.pop().unwrap(); | ||
146 | assert!(!self.stack.is_empty()); | ||
147 | |||
148 | self.walk_token(last_top_cursor.unwrap(), last_step, true) | ||
149 | } | ||
150 | }, | ||
151 | }; | ||
152 | } | ||
153 | |||
154 | /// Move cursor forward by 1 step with empty checking | ||
155 | fn forward(&mut self) { | 159 | fn forward(&mut self) { |
156 | if self.is_eof() { | 160 | if self.is_eof() { |
157 | return; | 161 | return; |
158 | } | 162 | } |
159 | |||
160 | self.pos += 1; | 163 | self.pos += 1; |
161 | loop { | ||
162 | self.forward_unchecked(); | ||
163 | if !self.is_empty_delimiter() { | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /// Move cursor forward by 1 step without empty checking | ||
170 | /// | ||
171 | /// Depends on the current state of cursor: | ||
172 | /// | ||
173 | /// * Delimiter Begin => Goto the first child token (`walk_token`) | ||
174 | /// * Token => Goto next token (`walk_token`) | ||
175 | /// * Delimiter End => Pop the stack, goto last walking token (`walk_token`) | ||
176 | /// | ||
177 | fn forward_unchecked(&mut self) { | ||
178 | if self.is_eof() { | ||
179 | return; | ||
180 | } | ||
181 | 164 | ||
182 | let step = self.current().map(|x| x.n_tokens).unwrap_or(1); | 165 | let step = self.current().map(|x| x.n_tokens).unwrap_or(1); |
183 | self.last_steps.push(step); | 166 | self.last_steps.push(step); |
184 | 167 | ||
185 | let do_walk_token = match self.cursor { | 168 | if let WalkCursor::Token(u, _) = self.cursor { |
186 | WalkCursor::DelimiterBegin(_) => Some((0, 0)), | 169 | self.cursor = self.walk_token(u, step, false) |
187 | WalkCursor::Token(u, _) => Some((u, step)), | 170 | } |
188 | WalkCursor::DelimiterEnd(_) => None, | ||
189 | _ => unreachable!(), | ||
190 | }; | ||
191 | |||
192 | self.cursor = match do_walk_token { | ||
193 | Some((u, step)) => self.walk_token(u, step, false), | ||
194 | None => { | ||
195 | let (_, last_top_idx) = self.stack.pop().unwrap(); | ||
196 | match self.stack.last() { | ||
197 | Some(_) => self.walk_token(last_top_idx.unwrap(), 1, false), | ||
198 | None => WalkCursor::Eof, | ||
199 | } | ||
200 | } | ||
201 | }; | ||
202 | } | 171 | } |
203 | 172 | ||
204 | /// Traversal child token | 173 | /// Traversal child token |
205 | /// Depends on the new position, it returns: | ||
206 | /// | ||
207 | /// * new position < 0 => DelimiterBegin | ||
208 | /// * new position > token_tree.len() => DelimiterEnd | ||
209 | /// * if new position is a subtree, depends on traversal direction: | ||
210 | /// ** backward => DelimiterEnd | ||
211 | /// ** forward => DelimiterBegin | ||
212 | /// * if new psoition is a leaf, return walk_leaf() | ||
213 | fn walk_token(&mut self, pos: usize, offset: usize, backward: bool) -> WalkCursor { | 174 | fn walk_token(&mut self, pos: usize, offset: usize, backward: bool) -> WalkCursor { |
214 | let (top, _) = self.stack.last().unwrap(); | 175 | let top = self.stack.last().map(|(t, _)| t).unwrap_or(&self.ts); |
215 | 176 | ||
216 | if backward && pos < offset { | 177 | if backward && pos < offset { |
217 | return WalkCursor::DelimiterBegin(convert_delim( | 178 | let (_, last_idx) = self.stack.pop().unwrap(); |
218 | self.stack.last().unwrap().0.delimiter, | 179 | return self.walk_token(last_idx, offset, backward); |
219 | false, | ||
220 | )); | ||
221 | } | ||
222 | |||
223 | if !backward && pos + offset >= top.token_trees.len() { | ||
224 | return WalkCursor::DelimiterEnd(convert_delim( | ||
225 | self.stack.last().unwrap().0.delimiter, | ||
226 | true, | ||
227 | )); | ||
228 | } | 180 | } |
229 | 181 | ||
230 | let pos = if backward { pos - offset } else { pos + offset }; | 182 | let pos = if backward { pos - offset } else { pos + offset }; |
231 | 183 | ||
232 | match &top.token_trees[pos] { | 184 | match top.get(pos) { |
233 | tt::TokenTree::Subtree(subtree) => { | 185 | DelimToken::Token(token) => match token { |
234 | self.stack.push((subtree, Some(pos))); | 186 | tt::TokenTree::Subtree(subtree) => { |
235 | let delim = convert_delim(self.stack.last().unwrap().0.delimiter, backward); | 187 | let ts = TokenSeq::from(subtree); |
236 | if backward { | 188 | let new_idx = if backward { ts.len() - 1 } else { 0 }; |
237 | WalkCursor::DelimiterEnd(delim) | 189 | self.stack.push((ts, pos)); |
238 | } else { | 190 | WalkCursor::Token(new_idx, convert_delim(subtree.delimiter, backward)) |
239 | WalkCursor::DelimiterBegin(delim) | 191 | } |
192 | tt::TokenTree::Leaf(leaf) => { | ||
193 | let next_tokens = top.child_slice(); | ||
194 | WalkCursor::Token(pos, convert_leaf(&next_tokens[pos..], leaf)) | ||
240 | } | 195 | } |
196 | }, | ||
197 | DelimToken::Delim(delim, is_end) => { | ||
198 | WalkCursor::Token(pos, convert_delim(*delim, is_end)) | ||
241 | } | 199 | } |
242 | tt::TokenTree::Leaf(leaf) => WalkCursor::Token(pos, Some(self.walk_leaf(leaf, pos))), | 200 | DelimToken::End => { |
243 | } | 201 | // it is the top level |
244 | } | 202 | if let Some((_, last_idx)) = self.stack.pop() { |
245 | 203 | assert!(!backward); | |
246 | fn walk_leaf(&mut self, leaf: &tt::Leaf, pos: usize) -> TtToken { | 204 | self.walk_token(last_idx, offset, backward) |
247 | match leaf { | 205 | } else { |
248 | tt::Leaf::Literal(l) => convert_literal(l), | 206 | WalkCursor::Eof |
249 | tt::Leaf::Ident(ident) => convert_ident(ident), | 207 | } |
250 | tt::Leaf::Punct(punct) => { | ||
251 | let (top, _) = self.stack.last().unwrap(); | ||
252 | convert_punct(punct, top, pos) | ||
253 | } | 208 | } |
254 | } | 209 | } |
255 | } | 210 | } |
@@ -263,27 +218,20 @@ pub(crate) trait Querier { | |||
263 | #[derive(Debug)] | 218 | #[derive(Debug)] |
264 | pub(crate) struct WalkerOwner<'a> { | 219 | pub(crate) struct WalkerOwner<'a> { |
265 | walker: RefCell<SubTreeWalker<'a>>, | 220 | walker: RefCell<SubTreeWalker<'a>>, |
266 | offset: usize, | ||
267 | } | 221 | } |
268 | 222 | ||
269 | impl<'a> WalkerOwner<'a> { | 223 | impl<'a> WalkerOwner<'a> { |
270 | fn new(subtree: &'a tt::Subtree) -> Self { | 224 | fn new<I: Into<TokenSeq<'a>>>(ts: I) -> Self { |
271 | WalkerOwner { walker: RefCell::new(SubTreeWalker::new(subtree)), offset: 0 } | 225 | WalkerOwner { walker: RefCell::new(SubTreeWalker::new(ts.into())) } |
272 | } | 226 | } |
273 | 227 | ||
274 | fn get<'b>(&self, pos: usize) -> Option<TtToken> { | 228 | fn get<'b>(&self, pos: usize) -> Option<TtToken> { |
275 | self.set_walker_pos(pos); | 229 | self.set_pos(pos); |
276 | let walker = self.walker.borrow(); | 230 | let walker = self.walker.borrow(); |
277 | walker.current().cloned() | 231 | walker.current().cloned() |
278 | } | 232 | } |
279 | 233 | ||
280 | fn start_from_nth(&mut self, pos: usize) { | 234 | fn set_pos(&self, pos: usize) { |
281 | self.offset = pos; | ||
282 | self.walker.borrow_mut().start_from_nth(pos); | ||
283 | } | ||
284 | |||
285 | fn set_walker_pos(&self, mut pos: usize) { | ||
286 | pos += self.offset; | ||
287 | let mut walker = self.walker.borrow_mut(); | 235 | let mut walker = self.walker.borrow_mut(); |
288 | while pos > walker.pos && !walker.is_eof() { | 236 | while pos > walker.pos && !walker.is_eof() { |
289 | walker.forward(); | 237 | walker.forward(); |
@@ -294,19 +242,26 @@ impl<'a> WalkerOwner<'a> { | |||
294 | } | 242 | } |
295 | 243 | ||
296 | fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> { | 244 | fn collect_token_trees(&mut self, n: usize) -> Vec<&tt::TokenTree> { |
297 | self.start_from_nth(self.offset); | ||
298 | |||
299 | let mut res = vec![]; | 245 | let mut res = vec![]; |
300 | let mut walker = self.walker.borrow_mut(); | 246 | let mut walker = self.walker.borrow_mut(); |
247 | walker.reset(); | ||
301 | 248 | ||
302 | while walker.pos - self.offset < n { | 249 | while walker.pos < n { |
303 | if let WalkCursor::Token(u, tt) = &walker.cursor { | 250 | if let WalkCursor::Token(u, tt) = &walker.cursor { |
304 | if walker.stack.len() == 1 { | 251 | // We only collect the topmost child |
305 | // We only collect the topmost child | 252 | if walker.stack.len() == 0 { |
306 | res.push(&walker.stack[0].0.token_trees[*u]); | 253 | for i in 0..tt.n_tokens { |
307 | if let Some(tt) = tt { | 254 | if let DelimToken::Token(token) = walker.ts.get(u + i) { |
308 | for i in 0..tt.n_tokens - 1 { | 255 | res.push(token); |
309 | res.push(&walker.stack[0].0.token_trees[u + i]); | 256 | } |
257 | } | ||
258 | } else if walker.stack.len() == 1 { | ||
259 | if let DelimToken::Delim(_, is_end) = walker.top().get(*u) { | ||
260 | if !is_end { | ||
261 | let (_, last_idx) = &walker.stack[0]; | ||
262 | if let DelimToken::Token(token) = walker.ts.get(*last_idx) { | ||
263 | res.push(token); | ||
264 | } | ||
310 | } | 265 | } |
311 | } | 266 | } |
312 | } | 267 | } |
@@ -331,12 +286,8 @@ pub(crate) struct SubtreeTokenSource<'a> { | |||
331 | } | 286 | } |
332 | 287 | ||
333 | impl<'a> SubtreeTokenSource<'a> { | 288 | impl<'a> SubtreeTokenSource<'a> { |
334 | pub fn new(subtree: &tt::Subtree) -> SubtreeTokenSource { | 289 | pub fn new<I: Into<TokenSeq<'a>>>(ts: I) -> SubtreeTokenSource<'a> { |
335 | SubtreeTokenSource { walker: WalkerOwner::new(subtree) } | 290 | SubtreeTokenSource { walker: WalkerOwner::new(ts) } |
336 | } | ||
337 | |||
338 | pub fn start_from_nth(&mut self, n: usize) { | ||
339 | self.walker.start_from_nth(n); | ||
340 | } | 291 | } |
341 | 292 | ||
342 | pub fn querier<'b>(&'a self) -> &'b WalkerOwner<'a> | 293 | pub fn querier<'b>(&'a self) -> &'b WalkerOwner<'a> |
@@ -361,10 +312,16 @@ impl<'a> TokenSource for SubtreeTokenSource<'a> { | |||
361 | } | 312 | } |
362 | } | 313 | } |
363 | fn is_token_joint_to_next(&self, pos: usize) -> bool { | 314 | fn is_token_joint_to_next(&self, pos: usize) -> bool { |
364 | self.walker.get(pos).unwrap().is_joint_to_next | 315 | match self.walker.get(pos) { |
316 | Some(t) => t.is_joint_to_next, | ||
317 | _ => false, | ||
318 | } | ||
365 | } | 319 | } |
366 | fn is_keyword(&self, pos: usize, kw: &str) -> bool { | 320 | fn is_keyword(&self, pos: usize, kw: &str) -> bool { |
367 | self.walker.get(pos).unwrap().text == *kw | 321 | match self.walker.get(pos) { |
322 | Some(t) => t.text == *kw, | ||
323 | _ => false, | ||
324 | } | ||
368 | } | 325 | } |
369 | } | 326 | } |
370 | 327 | ||
@@ -467,18 +424,18 @@ where | |||
467 | None | 424 | None |
468 | } | 425 | } |
469 | 426 | ||
470 | fn convert_delim(d: tt::Delimiter, closing: bool) -> Option<TtToken> { | 427 | fn convert_delim(d: tt::Delimiter, closing: bool) -> TtToken { |
471 | let (kinds, texts) = match d { | 428 | let (kinds, texts) = match d { |
472 | tt::Delimiter::Parenthesis => ([L_PAREN, R_PAREN], "()"), | 429 | tt::Delimiter::Parenthesis => ([L_PAREN, R_PAREN], "()"), |
473 | tt::Delimiter::Brace => ([L_CURLY, R_CURLY], "{}"), | 430 | tt::Delimiter::Brace => ([L_CURLY, R_CURLY], "{}"), |
474 | tt::Delimiter::Bracket => ([L_BRACK, R_BRACK], "[]"), | 431 | tt::Delimiter::Bracket => ([L_BRACK, R_BRACK], "[]"), |
475 | tt::Delimiter::None => return None, | 432 | tt::Delimiter::None => ([L_DOLLAR, R_DOLLAR], ""), |
476 | }; | 433 | }; |
477 | 434 | ||
478 | let idx = closing as usize; | 435 | let idx = closing as usize; |
479 | let kind = kinds[idx]; | 436 | let kind = kinds[idx]; |
480 | let text = &texts[idx..texts.len() - (1 - idx)]; | 437 | let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" }; |
481 | Some(TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text), n_tokens: 1 }) | 438 | TtToken { kind, is_joint_to_next: false, text: SmolStr::new(text), n_tokens: 1 } |
482 | } | 439 | } |
483 | 440 | ||
484 | fn convert_literal(l: &tt::Literal) -> TtToken { | 441 | fn convert_literal(l: &tt::Literal) -> TtToken { |
@@ -495,8 +452,9 @@ fn convert_ident(ident: &tt::Ident) -> TtToken { | |||
495 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone(), n_tokens: 1 } | 452 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone(), n_tokens: 1 } |
496 | } | 453 | } |
497 | 454 | ||
498 | fn convert_punct(p: &tt::Punct, parent: &tt::Subtree, next: usize) -> TtToken { | 455 | fn convert_punct(p: &tt::Punct, next_tokens: &[tt::TokenTree]) -> TtToken { |
499 | let iter = parent.token_trees[next + 1..].iter(); | 456 | let mut iter = next_tokens.iter(); |
457 | iter.next(); | ||
500 | let mut peek = TokenPeek::new(iter); | 458 | let mut peek = TokenPeek::new(iter); |
501 | 459 | ||
502 | if let Some((kind, is_joint_to_next, text, size)) = convert_multi_char_punct(p, &mut peek) { | 460 | if let Some((kind, is_joint_to_next, text, size)) = convert_multi_char_punct(p, &mut peek) { |
@@ -519,3 +477,11 @@ fn convert_punct(p: &tt::Punct, parent: &tt::Subtree, next: usize) -> TtToken { | |||
519 | TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text, n_tokens: 1 } | 477 | TtToken { kind, is_joint_to_next: p.spacing == tt::Spacing::Joint, text, n_tokens: 1 } |
520 | } | 478 | } |
521 | } | 479 | } |
480 | |||
481 | fn convert_leaf(tokens: &[tt::TokenTree], leaf: &tt::Leaf) -> TtToken { | ||
482 | match leaf { | ||
483 | tt::Leaf::Literal(l) => convert_literal(l), | ||
484 | tt::Leaf::Ident(ident) => convert_ident(ident), | ||
485 | tt::Leaf::Punct(punct) => convert_punct(punct, tokens), | ||
486 | } | ||
487 | } | ||
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 19c17bd55..28ded7870 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -22,6 +22,14 @@ pub fn ast_to_token_tree(ast: &ast::TokenTree) -> Option<(tt::Subtree, TokenMap) | |||
22 | Some((tt, token_map)) | 22 | Some((tt, token_map)) |
23 | } | 23 | } |
24 | 24 | ||
25 | /// Convert the syntax node to a `TokenTree` (what macro | ||
26 | /// will consume). | ||
27 | pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> { | ||
28 | let mut token_map = TokenMap::default(); | ||
29 | let tt = convert_tt(&mut token_map, node.range().start(), node)?; | ||
30 | Some((tt, token_map)) | ||
31 | } | ||
32 | |||
25 | /// Parses the token tree (result of macro expansion) as a sequence of items | 33 | /// Parses the token tree (result of macro expansion) as a sequence of items |
26 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { | 34 | pub fn token_tree_to_ast_item_list(tt: &tt::Subtree) -> TreeArc<ast::SourceFile> { |
27 | let token_source = SubtreeTokenSource::new(tt); | 35 | let token_source = SubtreeTokenSource::new(tt); |
@@ -51,15 +59,17 @@ fn convert_tt( | |||
51 | ) -> Option<tt::Subtree> { | 59 | ) -> Option<tt::Subtree> { |
52 | let first_child = tt.first_child_or_token()?; | 60 | let first_child = tt.first_child_or_token()?; |
53 | let last_child = tt.last_child_or_token()?; | 61 | let last_child = tt.last_child_or_token()?; |
54 | let delimiter = match (first_child.kind(), last_child.kind()) { | 62 | let (delimiter, skip_first) = match (first_child.kind(), last_child.kind()) { |
55 | (L_PAREN, R_PAREN) => tt::Delimiter::Parenthesis, | 63 | (L_PAREN, R_PAREN) => (tt::Delimiter::Parenthesis, true), |
56 | (L_CURLY, R_CURLY) => tt::Delimiter::Brace, | 64 | (L_CURLY, R_CURLY) => (tt::Delimiter::Brace, true), |
57 | (L_BRACK, R_BRACK) => tt::Delimiter::Bracket, | 65 | (L_BRACK, R_BRACK) => (tt::Delimiter::Bracket, true), |
58 | _ => return None, | 66 | _ => (tt::Delimiter::None, false), |
59 | }; | 67 | }; |
68 | |||
60 | let mut token_trees = Vec::new(); | 69 | let mut token_trees = Vec::new(); |
61 | for child in tt.children_with_tokens().skip(1) { | 70 | for child in tt.children_with_tokens().skip(skip_first as usize) { |
62 | if child == first_child || child == last_child || child.kind().is_trivia() { | 71 | if (skip_first && (child == first_child || child == last_child)) || child.kind().is_trivia() |
72 | { | ||
63 | continue; | 73 | continue; |
64 | } | 74 | } |
65 | match child { | 75 | match child { |
@@ -127,6 +137,11 @@ impl<'a, Q: Querier> TtTreeSink<'a, Q> { | |||
127 | 137 | ||
128 | impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { | 138 | impl<'a, Q: Querier> TreeSink for TtTreeSink<'a, Q> { |
129 | fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { | 139 | fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { |
140 | if kind == L_DOLLAR || kind == R_DOLLAR { | ||
141 | self.token_pos += n_tokens as usize; | ||
142 | return; | ||
143 | } | ||
144 | |||
130 | for _ in 0..n_tokens { | 145 | for _ in 0..n_tokens { |
131 | self.buf += &self.src_querier.token(self.token_pos).1; | 146 | self.buf += &self.src_querier.token(self.token_pos).1; |
132 | self.token_pos += 1; | 147 | self.token_pos += 1; |
@@ -176,19 +191,19 @@ mod tests { | |||
176 | 191 | ||
177 | let query = tt_src.querier(); | 192 | let query = tt_src.querier(); |
178 | 193 | ||
179 | // [{] | 194 | // [${] |
180 | // [let] [a] [=] ['c'] [;] | 195 | // [let] [a] [=] ['c'] [;] |
181 | assert_eq!(query.token(1 + 3).1, "'c'"); | 196 | assert_eq!(query.token(2 + 3).1, "'c'"); |
182 | assert_eq!(query.token(1 + 3).0, CHAR); | 197 | assert_eq!(query.token(2 + 3).0, CHAR); |
183 | // [let] [c] [=] [1000] [;] | 198 | // [let] [c] [=] [1000] [;] |
184 | assert_eq!(query.token(1 + 5 + 3).1, "1000"); | 199 | assert_eq!(query.token(2 + 5 + 3).1, "1000"); |
185 | assert_eq!(query.token(1 + 5 + 3).0, INT_NUMBER); | 200 | assert_eq!(query.token(2 + 5 + 3).0, INT_NUMBER); |
186 | // [let] [f] [=] [12E+99_f64] [;] | 201 | // [let] [f] [=] [12E+99_f64] [;] |
187 | assert_eq!(query.token(1 + 10 + 3).1, "12E+99_f64"); | 202 | assert_eq!(query.token(2 + 10 + 3).1, "12E+99_f64"); |
188 | assert_eq!(query.token(1 + 10 + 3).0, FLOAT_NUMBER); | 203 | assert_eq!(query.token(2 + 10 + 3).0, FLOAT_NUMBER); |
189 | 204 | ||
190 | // [let] [s] [=] ["rust1"] [;] | 205 | // [let] [s] [=] ["rust1"] [;] |
191 | assert_eq!(query.token(1 + 15 + 3).1, "\"rust1\""); | 206 | assert_eq!(query.token(2 + 15 + 3).1, "\"rust1\""); |
192 | assert_eq!(query.token(1 + 15 + 3).0, STRING); | 207 | assert_eq!(query.token(2 + 15 + 3).0, STRING); |
193 | } | 208 | } |
194 | } | 209 | } |
diff --git a/crates/ra_mbe/src/tt_cursor.rs b/crates/ra_mbe/src/tt_cursor.rs index d29faa77c..f6cefe087 100644 --- a/crates/ra_mbe/src/tt_cursor.rs +++ b/crates/ra_mbe/src/tt_cursor.rs | |||
@@ -84,6 +84,21 @@ impl<'a> TtCursor<'a> { | |||
84 | parser.parse_path() | 84 | parser.parse_path() |
85 | } | 85 | } |
86 | 86 | ||
87 | pub(crate) fn eat_expr(&mut self) -> Option<tt::TokenTree> { | ||
88 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
89 | parser.parse_expr() | ||
90 | } | ||
91 | |||
92 | pub(crate) fn eat_ty(&mut self) -> Option<tt::TokenTree> { | ||
93 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
94 | parser.parse_ty() | ||
95 | } | ||
96 | |||
97 | pub(crate) fn eat_pat(&mut self) -> Option<tt::TokenTree> { | ||
98 | let parser = Parser::new(&mut self.pos, self.subtree); | ||
99 | parser.parse_pat() | ||
100 | } | ||
101 | |||
87 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { | 102 | pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ParseError> { |
88 | if self.at_char(char) { | 103 | if self.at_char(char) { |
89 | self.bump(); | 104 | self.bump(); |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index c5f510e6b..5a7a55141 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -53,6 +53,18 @@ pub(crate) fn path(p: &mut Parser) { | |||
53 | paths::type_path(p); | 53 | paths::type_path(p); |
54 | } | 54 | } |
55 | 55 | ||
56 | pub(crate) fn expr(p: &mut Parser) { | ||
57 | expressions::expr(p); | ||
58 | } | ||
59 | |||
60 | pub(crate) fn type_(p: &mut Parser) { | ||
61 | types::type_(p) | ||
62 | } | ||
63 | |||
64 | pub(crate) fn pattern(p: &mut Parser) { | ||
65 | patterns::pattern(p) | ||
66 | } | ||
67 | |||
56 | pub(crate) fn reparser( | 68 | pub(crate) fn reparser( |
57 | node: SyntaxKind, | 69 | node: SyntaxKind, |
58 | first_child: Option<SyntaxKind>, | 70 | first_child: Option<SyntaxKind>, |
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs index 9b38b0a31..295577325 100644 --- a/crates/ra_parser/src/grammar/expressions.rs +++ b/crates/ra_parser/src/grammar/expressions.rs | |||
@@ -8,17 +8,20 @@ const EXPR_FIRST: TokenSet = LHS_FIRST; | |||
8 | 8 | ||
9 | pub(super) fn expr(p: &mut Parser) -> BlockLike { | 9 | pub(super) fn expr(p: &mut Parser) -> BlockLike { |
10 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; | 10 | let r = Restrictions { forbid_structs: false, prefer_stmt: false }; |
11 | expr_bp(p, r, 1).1 | 11 | let mut dollar_lvl = 0; |
12 | expr_bp(p, r, 1, &mut dollar_lvl).1 | ||
12 | } | 13 | } |
13 | 14 | ||
14 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { | 15 | pub(super) fn expr_stmt(p: &mut Parser) -> (Option<CompletedMarker>, BlockLike) { |
15 | let r = Restrictions { forbid_structs: false, prefer_stmt: true }; | 16 | let r = Restrictions { forbid_structs: false, prefer_stmt: true }; |
16 | expr_bp(p, r, 1) | 17 | let mut dollar_lvl = 0; |
18 | expr_bp(p, r, 1, &mut dollar_lvl) | ||
17 | } | 19 | } |
18 | 20 | ||
19 | fn expr_no_struct(p: &mut Parser) { | 21 | fn expr_no_struct(p: &mut Parser) { |
20 | let r = Restrictions { forbid_structs: true, prefer_stmt: false }; | 22 | let r = Restrictions { forbid_structs: true, prefer_stmt: false }; |
21 | expr_bp(p, r, 1); | 23 | let mut dollar_lvl = 0; |
24 | expr_bp(p, r, 1, &mut dollar_lvl); | ||
22 | } | 25 | } |
23 | 26 | ||
24 | // test block | 27 | // test block |
@@ -206,8 +209,23 @@ fn current_op(p: &Parser) -> (u8, Op) { | |||
206 | } | 209 | } |
207 | 210 | ||
208 | // Parses expression with binding power of at least bp. | 211 | // Parses expression with binding power of at least bp. |
209 | fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, BlockLike) { | 212 | fn expr_bp( |
210 | let mut lhs = match lhs(p, r) { | 213 | p: &mut Parser, |
214 | r: Restrictions, | ||
215 | mut bp: u8, | ||
216 | dollar_lvl: &mut usize, | ||
217 | ) -> (Option<CompletedMarker>, BlockLike) { | ||
218 | // `newly_dollar_open` is a flag indicated that dollar is just closed after lhs, e.g. | ||
219 | // `$1$ + a` | ||
220 | // We use this flag to skip handling it. | ||
221 | let mut newly_dollar_open = false; | ||
222 | |||
223 | if p.at_l_dollar() { | ||
224 | *dollar_lvl += p.eat_l_dollars(); | ||
225 | newly_dollar_open = true; | ||
226 | } | ||
227 | |||
228 | let mut lhs = match lhs(p, r, dollar_lvl) { | ||
211 | Some((lhs, blocklike)) => { | 229 | Some((lhs, blocklike)) => { |
212 | // test stmt_bin_expr_ambiguity | 230 | // test stmt_bin_expr_ambiguity |
213 | // fn foo() { | 231 | // fn foo() { |
@@ -223,6 +241,15 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, | |||
223 | }; | 241 | }; |
224 | 242 | ||
225 | loop { | 243 | loop { |
244 | if *dollar_lvl > 0 && p.at_r_dollar() { | ||
245 | *dollar_lvl -= p.eat_r_dollars(*dollar_lvl); | ||
246 | if !newly_dollar_open { | ||
247 | // We "pump" bp for make it highest priority | ||
248 | bp = 255; | ||
249 | } | ||
250 | newly_dollar_open = false; | ||
251 | } | ||
252 | |||
226 | let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ; | 253 | let is_range = p.current() == DOTDOT || p.current() == DOTDOTEQ; |
227 | let (op_bp, op) = current_op(p); | 254 | let (op_bp, op) = current_op(p); |
228 | if op_bp < bp { | 255 | if op_bp < bp { |
@@ -235,7 +262,8 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, | |||
235 | p.bump_compound(kind, n); | 262 | p.bump_compound(kind, n); |
236 | } | 263 | } |
237 | } | 264 | } |
238 | expr_bp(p, r, op_bp + 1); | 265 | |
266 | expr_bp(p, r, op_bp + 1, dollar_lvl); | ||
239 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); | 267 | lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR }); |
240 | } | 268 | } |
241 | (Some(lhs), BlockLike::NotBlock) | 269 | (Some(lhs), BlockLike::NotBlock) |
@@ -244,7 +272,11 @@ fn expr_bp(p: &mut Parser, r: Restrictions, bp: u8) -> (Option<CompletedMarker>, | |||
244 | const LHS_FIRST: TokenSet = | 272 | const LHS_FIRST: TokenSet = |
245 | atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS]); | 273 | atom::ATOM_EXPR_FIRST.union(token_set![AMP, STAR, EXCL, DOTDOT, DOTDOTEQ, MINUS]); |
246 | 274 | ||
247 | fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> { | 275 | fn lhs( |
276 | p: &mut Parser, | ||
277 | r: Restrictions, | ||
278 | dollar_lvl: &mut usize, | ||
279 | ) -> Option<(CompletedMarker, BlockLike)> { | ||
248 | let m; | 280 | let m; |
249 | let kind = match p.current() { | 281 | let kind = match p.current() { |
250 | // test ref_expr | 282 | // test ref_expr |
@@ -275,7 +307,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> | |||
275 | m = p.start(); | 307 | m = p.start(); |
276 | p.bump(); | 308 | p.bump(); |
277 | if p.at_ts(EXPR_FIRST) { | 309 | if p.at_ts(EXPR_FIRST) { |
278 | expr_bp(p, r, 2); | 310 | expr_bp(p, r, 2, dollar_lvl); |
279 | } | 311 | } |
280 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); | 312 | return Some((m.complete(p, RANGE_EXPR), BlockLike::NotBlock)); |
281 | } | 313 | } |
@@ -287,7 +319,7 @@ fn lhs(p: &mut Parser, r: Restrictions) -> Option<(CompletedMarker, BlockLike)> | |||
287 | )); | 319 | )); |
288 | } | 320 | } |
289 | }; | 321 | }; |
290 | expr_bp(p, r, 255); | 322 | expr_bp(p, r, 255, dollar_lvl); |
291 | Some((m.complete(p, kind), BlockLike::NotBlock)) | 323 | Some((m.complete(p, kind), BlockLike::NotBlock)) |
292 | } | 324 | } |
293 | 325 | ||
diff --git a/crates/ra_parser/src/grammar/patterns.rs b/crates/ra_parser/src/grammar/patterns.rs index 9a307559b..03fa9b71e 100644 --- a/crates/ra_parser/src/grammar/patterns.rs +++ b/crates/ra_parser/src/grammar/patterns.rs | |||
@@ -5,7 +5,7 @@ pub(super) const PATTERN_FIRST: TokenSet = expressions::LITERAL_FIRST | |||
5 | .union(token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); | 5 | .union(token_set![REF_KW, MUT_KW, L_PAREN, L_BRACK, AMP, UNDERSCORE, MINUS]); |
6 | 6 | ||
7 | pub(super) fn pattern(p: &mut Parser) { | 7 | pub(super) fn pattern(p: &mut Parser) { |
8 | pattern_r(p, PAT_RECOVERY_SET) | 8 | pattern_r(p, PAT_RECOVERY_SET); |
9 | } | 9 | } |
10 | 10 | ||
11 | /// Parses a pattern list separated by pipes `|` | 11 | /// Parses a pattern list separated by pipes `|` |
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 3ceeeebd7..56755c394 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -53,20 +53,39 @@ pub trait TreeSink { | |||
53 | fn error(&mut self, error: ParseError); | 53 | fn error(&mut self, error: ParseError); |
54 | } | 54 | } |
55 | 55 | ||
56 | /// Parse given tokens into the given sink as a rust file. | 56 | fn parse_from_tokens<F>(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink, f: F) |
57 | pub fn parse(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 57 | where |
58 | F: FnOnce(&mut parser::Parser), | ||
59 | { | ||
58 | let mut p = parser::Parser::new(token_source); | 60 | let mut p = parser::Parser::new(token_source); |
59 | grammar::root(&mut p); | 61 | f(&mut p); |
60 | let events = p.finish(); | 62 | let events = p.finish(); |
61 | event::process(tree_sink, events); | 63 | event::process(tree_sink, events); |
62 | } | 64 | } |
63 | 65 | ||
66 | /// Parse given tokens into the given sink as a rust file. | ||
67 | pub fn parse(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
68 | parse_from_tokens(token_source, tree_sink, grammar::root); | ||
69 | } | ||
70 | |||
64 | /// Parse given tokens into the given sink as a path | 71 | /// Parse given tokens into the given sink as a path |
65 | pub fn parse_path(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | 72 | pub fn parse_path(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { |
66 | let mut p = parser::Parser::new(token_source); | 73 | parse_from_tokens(token_source, tree_sink, grammar::path); |
67 | grammar::path(&mut p); | 74 | } |
68 | let events = p.finish(); | 75 | |
69 | event::process(tree_sink, events); | 76 | /// Parse given tokens into the given sink as a expression |
77 | pub fn parse_expr(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
78 | parse_from_tokens(token_source, tree_sink, grammar::expr); | ||
79 | } | ||
80 | |||
81 | /// Parse given tokens into the given sink as a ty | ||
82 | pub fn parse_ty(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
83 | parse_from_tokens(token_source, tree_sink, grammar::type_); | ||
84 | } | ||
85 | |||
86 | /// Parse given tokens into the given sink as a pattern | ||
87 | pub fn parse_pat(token_source: &dyn TokenSource, tree_sink: &mut dyn TreeSink) { | ||
88 | parse_from_tokens(token_source, tree_sink, grammar::pattern); | ||
70 | } | 89 | } |
71 | 90 | ||
72 | /// A parsing function for a specific braced-block. | 91 | /// A parsing function for a specific braced-block. |
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs index 56f8b7126..71f1f8b30 100644 --- a/crates/ra_parser/src/parser.rs +++ b/crates/ra_parser/src/parser.rs | |||
@@ -45,8 +45,9 @@ impl<'t> Parser<'t> { | |||
45 | /// | 45 | /// |
46 | /// Useful for parsing things like `>>`. | 46 | /// Useful for parsing things like `>>`. |
47 | pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> { | 47 | pub(crate) fn current2(&self) -> Option<(SyntaxKind, SyntaxKind)> { |
48 | let c1 = self.token_source.token_kind(self.token_pos); | 48 | let c1 = self.nth(0); |
49 | let c2 = self.token_source.token_kind(self.token_pos + 1); | 49 | let c2 = self.nth(1); |
50 | |||
50 | if self.token_source.is_token_joint_to_next(self.token_pos) { | 51 | if self.token_source.is_token_joint_to_next(self.token_pos) { |
51 | Some((c1, c2)) | 52 | Some((c1, c2)) |
52 | } else { | 53 | } else { |
@@ -59,9 +60,9 @@ impl<'t> Parser<'t> { | |||
59 | /// | 60 | /// |
60 | /// Useful for parsing things like `=>>`. | 61 | /// Useful for parsing things like `=>>`. |
61 | pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> { | 62 | pub(crate) fn current3(&self) -> Option<(SyntaxKind, SyntaxKind, SyntaxKind)> { |
62 | let c1 = self.token_source.token_kind(self.token_pos); | 63 | let c1 = self.nth(0); |
63 | let c2 = self.token_source.token_kind(self.token_pos + 1); | 64 | let c2 = self.nth(1); |
64 | let c3 = self.token_source.token_kind(self.token_pos + 2); | 65 | let c3 = self.nth(2); |
65 | if self.token_source.is_token_joint_to_next(self.token_pos) | 66 | if self.token_source.is_token_joint_to_next(self.token_pos) |
66 | && self.token_source.is_token_joint_to_next(self.token_pos + 1) | 67 | && self.token_source.is_token_joint_to_next(self.token_pos + 1) |
67 | { | 68 | { |
@@ -77,7 +78,23 @@ impl<'t> Parser<'t> { | |||
77 | let steps = self.steps.get(); | 78 | let steps = self.steps.get(); |
78 | assert!(steps <= 10_000_000, "the parser seems stuck"); | 79 | assert!(steps <= 10_000_000, "the parser seems stuck"); |
79 | self.steps.set(steps + 1); | 80 | self.steps.set(steps + 1); |
80 | self.token_source.token_kind(self.token_pos + n) | 81 | |
82 | // It is beecause the Dollar will appear between nth | ||
83 | // Following code skips through it | ||
84 | let mut non_dollars_count = 0; | ||
85 | let mut i = 0; | ||
86 | |||
87 | loop { | ||
88 | let kind = self.token_source.token_kind(self.token_pos + i); | ||
89 | i += 1; | ||
90 | |||
91 | match kind { | ||
92 | EOF => return EOF, | ||
93 | SyntaxKind::L_DOLLAR | SyntaxKind::R_DOLLAR => {} | ||
94 | _ if non_dollars_count == n => return kind, | ||
95 | _ => non_dollars_count += 1, | ||
96 | } | ||
97 | } | ||
81 | } | 98 | } |
82 | 99 | ||
83 | /// Checks if the current token is `kind`. | 100 | /// Checks if the current token is `kind`. |
@@ -180,6 +197,7 @@ impl<'t> Parser<'t> { | |||
180 | } | 197 | } |
181 | 198 | ||
182 | fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { | 199 | fn do_bump(&mut self, kind: SyntaxKind, n_raw_tokens: u8) { |
200 | self.eat_dollars(); | ||
183 | self.token_pos += usize::from(n_raw_tokens); | 201 | self.token_pos += usize::from(n_raw_tokens); |
184 | self.push_event(Event::Token { kind, n_raw_tokens }); | 202 | self.push_event(Event::Token { kind, n_raw_tokens }); |
185 | } | 203 | } |
@@ -187,6 +205,66 @@ impl<'t> Parser<'t> { | |||
187 | fn push_event(&mut self, event: Event) { | 205 | fn push_event(&mut self, event: Event) { |
188 | self.events.push(event) | 206 | self.events.push(event) |
189 | } | 207 | } |
208 | |||
209 | fn eat_dollars(&mut self) { | ||
210 | loop { | ||
211 | match self.token_source.token_kind(self.token_pos) { | ||
212 | k @ SyntaxKind::L_DOLLAR | k @ SyntaxKind::R_DOLLAR => { | ||
213 | self.token_pos += 1; | ||
214 | self.push_event(Event::Token { kind: k, n_raw_tokens: 1 }); | ||
215 | } | ||
216 | _ => { | ||
217 | return; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | pub(crate) fn eat_l_dollars(&mut self) -> usize { | ||
224 | let mut ate_count = 0; | ||
225 | loop { | ||
226 | match self.token_source.token_kind(self.token_pos) { | ||
227 | k @ SyntaxKind::L_DOLLAR => { | ||
228 | self.token_pos += 1; | ||
229 | self.push_event(Event::Token { kind: k, n_raw_tokens: 1 }); | ||
230 | ate_count += 1; | ||
231 | } | ||
232 | _ => { | ||
233 | return ate_count; | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | } | ||
238 | |||
239 | pub(crate) fn eat_r_dollars(&mut self, max_count: usize) -> usize { | ||
240 | let mut ate_count = 0; | ||
241 | loop { | ||
242 | match self.token_source.token_kind(self.token_pos) { | ||
243 | k @ SyntaxKind::R_DOLLAR => { | ||
244 | self.token_pos += 1; | ||
245 | self.push_event(Event::Token { kind: k, n_raw_tokens: 1 }); | ||
246 | ate_count += 1; | ||
247 | |||
248 | if max_count >= ate_count { | ||
249 | return ate_count; | ||
250 | } | ||
251 | } | ||
252 | _ => { | ||
253 | return ate_count; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | pub(crate) fn at_l_dollar(&self) -> bool { | ||
260 | let kind = self.token_source.token_kind(self.token_pos); | ||
261 | (kind == SyntaxKind::L_DOLLAR) | ||
262 | } | ||
263 | |||
264 | pub(crate) fn at_r_dollar(&self) -> bool { | ||
265 | let kind = self.token_source.token_kind(self.token_pos); | ||
266 | (kind == SyntaxKind::R_DOLLAR) | ||
267 | } | ||
190 | } | 268 | } |
191 | 269 | ||
192 | /// See `Parser::start`. | 270 | /// See `Parser::start`. |
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs index b8350266f..498b0e164 100644 --- a/crates/ra_parser/src/syntax_kind/generated.rs +++ b/crates/ra_parser/src/syntax_kind/generated.rs | |||
@@ -120,6 +120,8 @@ pub enum SyntaxKind { | |||
120 | LIFETIME, | 120 | LIFETIME, |
121 | COMMENT, | 121 | COMMENT, |
122 | SHEBANG, | 122 | SHEBANG, |
123 | L_DOLLAR, | ||
124 | R_DOLLAR, | ||
123 | SOURCE_FILE, | 125 | SOURCE_FILE, |
124 | STRUCT_DEF, | 126 | STRUCT_DEF, |
125 | ENUM_DEF, | 127 | ENUM_DEF, |
@@ -477,6 +479,8 @@ impl SyntaxKind { | |||
477 | LIFETIME => &SyntaxInfo { name: "LIFETIME" }, | 479 | LIFETIME => &SyntaxInfo { name: "LIFETIME" }, |
478 | COMMENT => &SyntaxInfo { name: "COMMENT" }, | 480 | COMMENT => &SyntaxInfo { name: "COMMENT" }, |
479 | SHEBANG => &SyntaxInfo { name: "SHEBANG" }, | 481 | SHEBANG => &SyntaxInfo { name: "SHEBANG" }, |
482 | L_DOLLAR => &SyntaxInfo { name: "L_DOLLAR" }, | ||
483 | R_DOLLAR => &SyntaxInfo { name: "R_DOLLAR" }, | ||
480 | SOURCE_FILE => &SyntaxInfo { name: "SOURCE_FILE" }, | 484 | SOURCE_FILE => &SyntaxInfo { name: "SOURCE_FILE" }, |
481 | STRUCT_DEF => &SyntaxInfo { name: "STRUCT_DEF" }, | 485 | STRUCT_DEF => &SyntaxInfo { name: "STRUCT_DEF" }, |
482 | ENUM_DEF => &SyntaxInfo { name: "ENUM_DEF" }, | 486 | ENUM_DEF => &SyntaxInfo { name: "ENUM_DEF" }, |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 0a35e25d5..b41241287 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -118,6 +118,8 @@ Grammar( | |||
118 | "LIFETIME", | 118 | "LIFETIME", |
119 | "COMMENT", | 119 | "COMMENT", |
120 | "SHEBANG", | 120 | "SHEBANG", |
121 | "L_DOLLAR", | ||
122 | "R_DOLLAR", | ||
121 | ], | 123 | ], |
122 | nodes: [ | 124 | nodes: [ |
123 | "SOURCE_FILE", | 125 | "SOURCE_FILE", |