diff options
-rw-r--r-- | crates/hir_def/src/item_tree.rs | 12 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 9 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 31 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 3 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 23 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 19 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 38 | ||||
-rw-r--r-- | crates/mbe/src/expander.rs | 4 | ||||
-rw-r--r-- | crates/mbe/src/expander/matcher.rs | 272 | ||||
-rw-r--r-- | crates/mbe/src/expander/transcriber.rs | 12 | ||||
-rw-r--r-- | crates/rust-analyzer/build.rs | 5 | ||||
-rw-r--r-- | crates/tt/src/lib.rs | 47 | ||||
-rw-r--r-- | editors/code/src/commands.ts | 5 |
15 files changed, 329 insertions, 163 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 6bb334573..09bcb10dc 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -209,18 +209,6 @@ impl ItemTree { | |||
209 | } | 209 | } |
210 | } | 210 | } |
211 | 211 | ||
212 | pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source { | ||
213 | // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty | ||
214 | // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with). | ||
215 | let root = | ||
216 | db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree"); | ||
217 | |||
218 | let id = self[of.value].ast_id(); | ||
219 | let map = db.ast_id_map(of.file_id); | ||
220 | let ptr = map.get(id); | ||
221 | ptr.to_node(&root) | ||
222 | } | ||
223 | |||
224 | fn data(&self) -> &ItemTreeData { | 212 | fn data(&self) -> &ItemTreeData { |
225 | self.data.as_ref().expect("attempted to access data of empty ItemTree") | 213 | self.data.as_ref().expect("attempted to access data of empty ItemTree") |
226 | } | 214 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index eda982c85..10977761c 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -15,7 +15,7 @@ use rustc_hash::FxHashSet; | |||
15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; | 15 | use syntax::{algo, ast, AstNode, TextRange, TextSize}; |
16 | use test_utils::extract_annotations; | 16 | use test_utils::extract_annotations; |
17 | 17 | ||
18 | use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; | 18 | use crate::{db::DefDatabase, nameres::DefMap, src::HasSource, Lookup, ModuleDefId, ModuleId}; |
19 | 19 | ||
20 | #[salsa::database( | 20 | #[salsa::database( |
21 | base_db::SourceDatabaseExtStorage, | 21 | base_db::SourceDatabaseExtStorage, |
@@ -115,14 +115,9 @@ impl TestDB { | |||
115 | if file_id != position.file_id.into() { | 115 | if file_id != position.file_id.into() { |
116 | continue; | 116 | continue; |
117 | } | 117 | } |
118 | let root = self.parse_or_expand(file_id).unwrap(); | ||
119 | let ast_map = self.ast_id_map(file_id); | ||
120 | let item_tree = self.item_tree(file_id); | ||
121 | for decl in module.scope.declarations() { | 118 | for decl in module.scope.declarations() { |
122 | if let ModuleDefId::FunctionId(it) = decl { | 119 | if let ModuleDefId::FunctionId(it) = decl { |
123 | let ast = | 120 | let range = it.lookup(self).source(self).value.syntax().text_range(); |
124 | ast_map.get(item_tree[it.lookup(self).id.value].ast_id).to_node(&root); | ||
125 | let range = ast.syntax().text_range(); | ||
126 | 121 | ||
127 | if !range.contains(position.offset) { | 122 | if !range.contains(position.offset) { |
128 | continue; | 123 | continue; |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index cb6e23320..9086e6c17 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -340,6 +340,8 @@ fn parse_macro_with_arg( | |||
340 | None => return ExpandResult { value: None, err: result.err }, | 340 | None => return ExpandResult { value: None, err: result.err }, |
341 | }; | 341 | }; |
342 | 342 | ||
343 | log::debug!("expanded = {}", tt.as_debug_string()); | ||
344 | |||
343 | let fragment_kind = to_fragment_kind(db, macro_call_id); | 345 | let fragment_kind = to_fragment_kind(db, macro_call_id); |
344 | 346 | ||
345 | let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { | 347 | let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 5fa83567b..d84ec9b7a 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -8,7 +8,7 @@ | |||
8 | use std::{iter, sync::Arc}; | 8 | use std::{iter, sync::Arc}; |
9 | 9 | ||
10 | use base_db::CrateId; | 10 | use base_db::CrateId; |
11 | use chalk_ir::Mutability; | 11 | use chalk_ir::{cast::Cast, Mutability}; |
12 | use hir_def::{ | 12 | use hir_def::{ |
13 | adt::StructKind, | 13 | adt::StructKind, |
14 | builtin_type::BuiltinType, | 14 | builtin_type::BuiltinType, |
@@ -27,6 +27,7 @@ use stdx::impl_from; | |||
27 | 27 | ||
28 | use crate::{ | 28 | use crate::{ |
29 | db::HirDatabase, | 29 | db::HirDatabase, |
30 | traits::chalk::{Interner, ToChalk}, | ||
30 | utils::{ | 31 | utils::{ |
31 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, | 32 | all_super_trait_refs, associated_type_by_name_including_super_traits, generics, |
32 | make_mut_slice, variant_data, | 33 | make_mut_slice, variant_data, |
@@ -914,10 +915,21 @@ impl TraitEnvironment { | |||
914 | pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { | 915 | pub fn lower(db: &dyn HirDatabase, resolver: &Resolver) -> Arc<TraitEnvironment> { |
915 | let ctx = TyLoweringContext::new(db, &resolver) | 916 | let ctx = TyLoweringContext::new(db, &resolver) |
916 | .with_type_param_mode(TypeParamLoweringMode::Placeholder); | 917 | .with_type_param_mode(TypeParamLoweringMode::Placeholder); |
917 | let mut predicates = resolver | 918 | let mut traits_in_scope = Vec::new(); |
918 | .where_predicates_in_scope() | 919 | let mut clauses = Vec::new(); |
919 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) | 920 | for pred in resolver.where_predicates_in_scope() { |
920 | .collect::<Vec<_>>(); | 921 | for pred in GenericPredicate::from_where_predicate(&ctx, pred) { |
922 | if pred.is_error() { | ||
923 | continue; | ||
924 | } | ||
925 | if let GenericPredicate::Implemented(tr) = &pred { | ||
926 | traits_in_scope.push((tr.self_ty().clone(), tr.trait_)); | ||
927 | } | ||
928 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
929 | pred.clone().to_chalk(db).cast(&Interner); | ||
930 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
931 | } | ||
932 | } | ||
921 | 933 | ||
922 | if let Some(def) = resolver.generic_def() { | 934 | if let Some(def) = resolver.generic_def() { |
923 | let container: Option<AssocContainerId> = match def { | 935 | let container: Option<AssocContainerId> = match def { |
@@ -938,12 +950,15 @@ impl TraitEnvironment { | |||
938 | let substs = Substs::type_params(db, trait_id); | 950 | let substs = Substs::type_params(db, trait_id); |
939 | let trait_ref = TraitRef { trait_: trait_id, substs }; | 951 | let trait_ref = TraitRef { trait_: trait_id, substs }; |
940 | let pred = GenericPredicate::Implemented(trait_ref); | 952 | let pred = GenericPredicate::Implemented(trait_ref); |
941 | 953 | let program_clause: chalk_ir::ProgramClause<Interner> = | |
942 | predicates.push(pred); | 954 | pred.clone().to_chalk(db).cast(&Interner); |
955 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
943 | } | 956 | } |
944 | } | 957 | } |
945 | 958 | ||
946 | Arc::new(TraitEnvironment { predicates }) | 959 | let env = chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses); |
960 | |||
961 | Arc::new(TraitEnvironment { traits_from_clauses: traits_in_scope, env }) | ||
947 | } | 962 | } |
948 | } | 963 | } |
949 | 964 | ||
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index ccc12c075..d57c6de70 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -528,8 +528,7 @@ fn iterate_trait_method_candidates( | |||
528 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); | 528 | self_ty.value.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t)); |
529 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { | 529 | let env_traits = if let Ty::Placeholder(_) = self_ty.value { |
530 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope | 530 | // if we have `T: Trait` in the param env, the trait doesn't need to be in scope |
531 | env.trait_predicates_for_self_ty(&self_ty.value) | 531 | env.traits_in_scope_from_clauses(&self_ty.value) |
532 | .map(|tr| tr.trait_) | ||
533 | .flat_map(|t| all_super_traits(db.upcast(), t)) | 532 | .flat_map(|t| all_super_traits(db.upcast(), t)) |
534 | .collect() | 533 | .collect() |
535 | } else { | 534 | } else { |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index fc770ea60..0a4141e69 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -19,6 +19,7 @@ use hir_def::{ | |||
19 | item_scope::ItemScope, | 19 | item_scope::ItemScope, |
20 | keys, | 20 | keys, |
21 | nameres::DefMap, | 21 | nameres::DefMap, |
22 | src::HasSource, | ||
22 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 23 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, |
23 | }; | 24 | }; |
24 | use hir_expand::{db::AstDatabase, InFile}; | 25 | use hir_expand::{db::AstDatabase, InFile}; |
@@ -195,18 +196,15 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
195 | defs.sort_by_key(|def| match def { | 196 | defs.sort_by_key(|def| match def { |
196 | DefWithBodyId::FunctionId(it) => { | 197 | DefWithBodyId::FunctionId(it) => { |
197 | let loc = it.lookup(&db); | 198 | let loc = it.lookup(&db); |
198 | let tree = db.item_tree(loc.id.file_id); | 199 | loc.source(&db).value.syntax().text_range().start() |
199 | tree.source(&db, loc.id).syntax().text_range().start() | ||
200 | } | 200 | } |
201 | DefWithBodyId::ConstId(it) => { | 201 | DefWithBodyId::ConstId(it) => { |
202 | let loc = it.lookup(&db); | 202 | let loc = it.lookup(&db); |
203 | let tree = db.item_tree(loc.id.file_id); | 203 | loc.source(&db).value.syntax().text_range().start() |
204 | tree.source(&db, loc.id).syntax().text_range().start() | ||
205 | } | 204 | } |
206 | DefWithBodyId::StaticId(it) => { | 205 | DefWithBodyId::StaticId(it) => { |
207 | let loc = it.lookup(&db); | 206 | let loc = it.lookup(&db); |
208 | let tree = db.item_tree(loc.id.file_id); | 207 | loc.source(&db).value.syntax().text_range().start() |
209 | tree.source(&db, loc.id).syntax().text_range().start() | ||
210 | } | 208 | } |
211 | }); | 209 | }); |
212 | for def in defs { | 210 | for def in defs { |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index e4cdb6d53..27f350f70 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -38,22 +38,25 @@ fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { | |||
38 | /// fn foo<T: Default>(t: T) {} | 38 | /// fn foo<T: Default>(t: T) {} |
39 | /// ``` | 39 | /// ``` |
40 | /// we assume that `T: Default`. | 40 | /// we assume that `T: Default`. |
41 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 41 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
42 | pub struct TraitEnvironment { | 42 | pub struct TraitEnvironment { |
43 | pub predicates: Vec<GenericPredicate>, | 43 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, |
44 | // but for now it's too annoying... | ||
45 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, | ||
46 | pub(crate) env: chalk_ir::Environment<Interner>, | ||
44 | } | 47 | } |
45 | 48 | ||
46 | impl TraitEnvironment { | 49 | impl TraitEnvironment { |
47 | /// Returns trait refs with the given self type which are supposed to hold | 50 | pub(crate) fn traits_in_scope_from_clauses<'a>( |
48 | /// in this trait env. E.g. if we are in `foo<T: SomeTrait>()`, this will | ||
49 | /// find that `T: SomeTrait` if we call it for `T`. | ||
50 | pub(crate) fn trait_predicates_for_self_ty<'a>( | ||
51 | &'a self, | 51 | &'a self, |
52 | ty: &'a Ty, | 52 | ty: &'a Ty, |
53 | ) -> impl Iterator<Item = &'a TraitRef> + 'a { | 53 | ) -> impl Iterator<Item = TraitId> + 'a { |
54 | self.predicates.iter().filter_map(move |pred| match pred { | 54 | self.traits_from_clauses.iter().filter_map(move |(self_ty, trait_id)| { |
55 | GenericPredicate::Implemented(tr) if tr.self_ty() == ty => Some(tr), | 55 | if self_ty == ty { |
56 | _ => None, | 56 | Some(*trait_id) |
57 | } else { | ||
58 | None | ||
59 | } | ||
57 | }) | 60 | }) |
58 | } | 61 | } |
59 | } | 62 | } |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index 565672b6b..1a2a3a8c7 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -33,13 +33,13 @@ pub(super) mod tls; | |||
33 | mod interner; | 33 | mod interner; |
34 | mod mapping; | 34 | mod mapping; |
35 | 35 | ||
36 | pub(super) trait ToChalk { | 36 | pub(crate) trait ToChalk { |
37 | type Chalk; | 37 | type Chalk; |
38 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; | 38 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; |
39 | fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; | 39 | fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; |
40 | } | 40 | } |
41 | 41 | ||
42 | pub(super) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T | 42 | pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T |
43 | where | 43 | where |
44 | T: ToChalk<Chalk = ChalkT>, | 44 | T: ToChalk<Chalk = ChalkT>, |
45 | { | 45 | { |
@@ -487,19 +487,14 @@ pub(crate) fn struct_datum_query( | |||
487 | struct_id: AdtId, | 487 | struct_id: AdtId, |
488 | ) -> Arc<StructDatum> { | 488 | ) -> Arc<StructDatum> { |
489 | debug!("struct_datum {:?}", struct_id); | 489 | debug!("struct_datum {:?}", struct_id); |
490 | let type_ctor = Ty::Adt(struct_id, Substs::empty()); | ||
491 | let chalk_ir::AdtId(adt_id) = struct_id; | 490 | let chalk_ir::AdtId(adt_id) = struct_id; |
492 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | ||
493 | let num_params = generics(db.upcast(), adt_id.into()).len(); | 491 | let num_params = generics(db.upcast(), adt_id.into()).len(); |
494 | let upstream = adt_id.module(db.upcast()).krate() != krate; | 492 | let upstream = adt_id.module(db.upcast()).krate() != krate; |
495 | let where_clauses = type_ctor | 493 | let where_clauses = { |
496 | .as_generic_def() | 494 | let generic_params = generics(db.upcast(), adt_id.into()); |
497 | .map(|generic_def| { | 495 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
498 | let generic_params = generics(db.upcast(), generic_def); | 496 | convert_where_clauses(db, adt_id.into(), &bound_vars) |
499 | let bound_vars = Substs::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 497 | }; |
500 | convert_where_clauses(db, generic_def, &bound_vars) | ||
501 | }) | ||
502 | .unwrap_or_else(Vec::new); | ||
503 | let flags = rust_ir::AdtFlags { | 498 | let flags = rust_ir::AdtFlags { |
504 | upstream, | 499 | upstream, |
505 | // FIXME set fundamental and phantom_data flags correctly | 500 | // FIXME set fundamental and phantom_data flags correctly |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 3a08b67e9..b0415e8b0 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -17,7 +17,7 @@ use crate::{ | |||
17 | primitive::UintTy, | 17 | primitive::UintTy, |
18 | traits::{Canonical, Obligation}, | 18 | traits::{Canonical, Obligation}, |
19 | AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy, | 19 | AliasTy, CallableDefId, FnPointer, FnSig, GenericPredicate, InEnvironment, OpaqueTy, |
20 | OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitEnvironment, TraitRef, Ty, | 20 | OpaqueTyId, ProjectionPredicate, ProjectionTy, Scalar, Substs, TraitRef, Ty, |
21 | }; | 21 | }; |
22 | 22 | ||
23 | use super::interner::*; | 23 | use super::interner::*; |
@@ -536,31 +536,6 @@ where | |||
536 | } | 536 | } |
537 | } | 537 | } |
538 | 538 | ||
539 | impl ToChalk for Arc<TraitEnvironment> { | ||
540 | type Chalk = chalk_ir::Environment<Interner>; | ||
541 | |||
542 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Environment<Interner> { | ||
543 | let mut clauses = Vec::new(); | ||
544 | for pred in &self.predicates { | ||
545 | if pred.is_error() { | ||
546 | // for env, we just ignore errors | ||
547 | continue; | ||
548 | } | ||
549 | let program_clause: chalk_ir::ProgramClause<Interner> = | ||
550 | pred.clone().to_chalk(db).cast(&Interner); | ||
551 | clauses.push(program_clause.into_from_env_clause(&Interner)); | ||
552 | } | ||
553 | chalk_ir::Environment::new(&Interner).add_clauses(&Interner, clauses) | ||
554 | } | ||
555 | |||
556 | fn from_chalk( | ||
557 | _db: &dyn HirDatabase, | ||
558 | _env: chalk_ir::Environment<Interner>, | ||
559 | ) -> Arc<TraitEnvironment> { | ||
560 | unimplemented!() | ||
561 | } | ||
562 | } | ||
563 | |||
564 | impl<T: ToChalk> ToChalk for InEnvironment<T> | 539 | impl<T: ToChalk> ToChalk for InEnvironment<T> |
565 | where | 540 | where |
566 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | 541 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, |
@@ -569,19 +544,16 @@ where | |||
569 | 544 | ||
570 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | 545 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { |
571 | chalk_ir::InEnvironment { | 546 | chalk_ir::InEnvironment { |
572 | environment: self.environment.to_chalk(db), | 547 | environment: self.environment.env.clone(), |
573 | goal: self.value.to_chalk(db), | 548 | goal: self.value.to_chalk(db), |
574 | } | 549 | } |
575 | } | 550 | } |
576 | 551 | ||
577 | fn from_chalk( | 552 | fn from_chalk( |
578 | db: &dyn HirDatabase, | 553 | _db: &dyn HirDatabase, |
579 | in_env: chalk_ir::InEnvironment<T::Chalk>, | 554 | _in_env: chalk_ir::InEnvironment<T::Chalk>, |
580 | ) -> InEnvironment<T> { | 555 | ) -> InEnvironment<T> { |
581 | InEnvironment { | 556 | unimplemented!() |
582 | environment: from_chalk(db, in_env.environment), | ||
583 | value: from_chalk(db, in_env.goal), | ||
584 | } | ||
585 | } | 557 | } |
586 | } | 558 | } |
587 | 559 | ||
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs index 2efff8f52..3197c834c 100644 --- a/crates/mbe/src/expander.rs +++ b/crates/mbe/src/expander.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | mod matcher; | 5 | mod matcher; |
6 | mod transcriber; | 6 | mod transcriber; |
7 | 7 | ||
8 | use smallvec::SmallVec; | 8 | use rustc_hash::FxHashMap; |
9 | use syntax::SmolStr; | 9 | use syntax::SmolStr; |
10 | 10 | ||
11 | use crate::{ExpandError, ExpandResult}; | 11 | use crate::{ExpandError, ExpandResult}; |
@@ -96,7 +96,7 @@ pub(crate) fn expand_rules( | |||
96 | /// many is not a plain `usize`, but an `&[usize]`. | 96 | /// many is not a plain `usize`, but an `&[usize]`. |
97 | #[derive(Debug, Default, Clone, PartialEq, Eq)] | 97 | #[derive(Debug, Default, Clone, PartialEq, Eq)] |
98 | struct Bindings { | 98 | struct Bindings { |
99 | inner: SmallVec<[(SmolStr, Binding); 4]>, | 99 | inner: FxHashMap<SmolStr, Binding>, |
100 | } | 100 | } |
101 | 101 | ||
102 | #[derive(Debug, Clone, PartialEq, Eq)] | 102 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs index 9d3d28055..54db76d5d 100644 --- a/crates/mbe/src/expander/matcher.rs +++ b/crates/mbe/src/expander/matcher.rs | |||
@@ -59,6 +59,8 @@ | |||
59 | //! eof: [a $( a )* a b ·] | 59 | //! eof: [a $( a )* a b ·] |
60 | //! ``` | 60 | //! ``` |
61 | 61 | ||
62 | use std::rc::Rc; | ||
63 | |||
62 | use crate::{ | 64 | use crate::{ |
63 | expander::{Binding, Bindings, Fragment}, | 65 | expander::{Binding, Bindings, Fragment}, |
64 | parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, | 66 | parser::{Op, OpDelimited, OpDelimitedIter, RepeatKind, Separator}, |
@@ -76,43 +78,15 @@ impl Bindings { | |||
76 | // FIXME: Do we have a better way to represent an empty token ? | 78 | // FIXME: Do we have a better way to represent an empty token ? |
77 | // Insert an empty subtree for empty token | 79 | // Insert an empty subtree for empty token |
78 | let tt = tt::Subtree::default().into(); | 80 | let tt = tt::Subtree::default().into(); |
79 | self.inner.push((name.clone(), Binding::Fragment(Fragment::Tokens(tt)))); | 81 | self.inner.insert(name.clone(), Binding::Fragment(Fragment::Tokens(tt))); |
80 | } | 82 | } |
81 | 83 | ||
82 | fn push_empty(&mut self, name: &SmolStr) { | 84 | fn push_empty(&mut self, name: &SmolStr) { |
83 | self.inner.push((name.clone(), Binding::Empty)); | 85 | self.inner.insert(name.clone(), Binding::Empty); |
84 | } | ||
85 | |||
86 | fn push_nested(&mut self, idx: usize, nested: Bindings) -> Result<(), ExpandError> { | ||
87 | for (key, value) in nested.inner { | ||
88 | if self.get_mut(&key).is_none() { | ||
89 | self.inner.push((key.clone(), Binding::Nested(Vec::new()))); | ||
90 | } | ||
91 | match self.get_mut(&key) { | ||
92 | Some(Binding::Nested(it)) => { | ||
93 | // insert empty nested bindings before this one | ||
94 | while it.len() < idx { | ||
95 | it.push(Binding::Nested(vec![])); | ||
96 | } | ||
97 | it.push(value); | ||
98 | } | ||
99 | _ => { | ||
100 | return Err(ExpandError::BindingError(format!( | ||
101 | "could not find binding `{}`", | ||
102 | key | ||
103 | ))); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | Ok(()) | ||
108 | } | ||
109 | |||
110 | fn get_mut(&mut self, name: &str) -> Option<&mut Binding> { | ||
111 | self.inner.iter_mut().find_map(|(n, b)| if n == name { Some(b) } else { None }) | ||
112 | } | 86 | } |
113 | 87 | ||
114 | fn bindings(&self) -> impl Iterator<Item = &Binding> { | 88 | fn bindings(&self) -> impl Iterator<Item = &Binding> { |
115 | self.inner.iter().map(|(_, b)| b) | 89 | self.inner.values() |
116 | } | 90 | } |
117 | } | 91 | } |
118 | 92 | ||
@@ -163,6 +137,187 @@ pub(super) fn match_(pattern: &MetaTemplate, input: &tt::Subtree) -> Match { | |||
163 | } | 137 | } |
164 | 138 | ||
165 | #[derive(Debug, Clone)] | 139 | #[derive(Debug, Clone)] |
140 | enum BindingKind { | ||
141 | Empty(SmolStr), | ||
142 | Optional(SmolStr), | ||
143 | Fragment(SmolStr, Fragment), | ||
144 | Nested(usize, usize), | ||
145 | } | ||
146 | |||
147 | #[derive(Debug, Clone)] | ||
148 | struct BindingsIdx(usize, usize); | ||
149 | |||
150 | #[derive(Debug, Clone)] | ||
151 | enum LinkNode<T> { | ||
152 | Node(T), | ||
153 | Parent { idx: usize, len: usize }, | ||
154 | } | ||
155 | |||
156 | #[derive(Default)] | ||
157 | struct BindingsBuilder { | ||
158 | nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>, | ||
159 | nested: Vec<Vec<LinkNode<usize>>>, | ||
160 | } | ||
161 | |||
162 | impl BindingsBuilder { | ||
163 | fn alloc(&mut self) -> BindingsIdx { | ||
164 | let idx = self.nodes.len(); | ||
165 | self.nodes.push(Vec::with_capacity(8)); | ||
166 | let nidx = self.nested.len(); | ||
167 | self.nested.push(Vec::with_capacity(8)); | ||
168 | BindingsIdx(idx, nidx) | ||
169 | } | ||
170 | |||
171 | fn copy(&mut self, bindings: &BindingsIdx) -> BindingsIdx { | ||
172 | let idx = copy_parent(bindings.0, &mut self.nodes); | ||
173 | let nidx = copy_parent(bindings.1, &mut self.nested); | ||
174 | return BindingsIdx(idx, nidx); | ||
175 | |||
176 | fn copy_parent<T>(idx: usize, target: &mut Vec<Vec<LinkNode<T>>>) -> usize | ||
177 | where | ||
178 | T: Clone, | ||
179 | { | ||
180 | let new_idx = target.len(); | ||
181 | let len = target[idx].len(); | ||
182 | if len < 4 { | ||
183 | target.push(target[idx].clone()) | ||
184 | } else { | ||
185 | let mut item = Vec::with_capacity(8); | ||
186 | item.push(LinkNode::Parent { idx, len }); | ||
187 | target.push(item); | ||
188 | } | ||
189 | |||
190 | new_idx | ||
191 | } | ||
192 | } | ||
193 | |||
194 | fn push_empty(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { | ||
195 | self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Empty(var.clone())))); | ||
196 | } | ||
197 | |||
198 | fn push_optional(&mut self, idx: &mut BindingsIdx, var: &SmolStr) { | ||
199 | self.nodes[idx.0].push(LinkNode::Node(Rc::new(BindingKind::Optional(var.clone())))); | ||
200 | } | ||
201 | |||
202 | fn push_fragment(&mut self, idx: &mut BindingsIdx, var: &SmolStr, fragment: Fragment) { | ||
203 | self.nodes[idx.0] | ||
204 | .push(LinkNode::Node(Rc::new(BindingKind::Fragment(var.clone(), fragment)))); | ||
205 | } | ||
206 | |||
207 | fn push_nested(&mut self, parent: &mut BindingsIdx, child: &BindingsIdx) { | ||
208 | let BindingsIdx(idx, nidx) = self.copy(&child); | ||
209 | self.nodes[parent.0].push(LinkNode::Node(Rc::new(BindingKind::Nested(idx, nidx)))); | ||
210 | } | ||
211 | |||
212 | fn push_default(&mut self, idx: &mut BindingsIdx) { | ||
213 | self.nested[idx.1].push(LinkNode::Node(idx.0)); | ||
214 | let new_idx = self.nodes.len(); | ||
215 | self.nodes.push(Vec::with_capacity(8)); | ||
216 | idx.0 = new_idx; | ||
217 | } | ||
218 | |||
219 | fn build(self, idx: &BindingsIdx) -> Bindings { | ||
220 | let mut bindings = Bindings::default(); | ||
221 | self.build_recur(&mut bindings, self.nodes[idx.0].clone()); | ||
222 | bindings | ||
223 | } | ||
224 | |||
225 | fn build_recur(&self, bindings: &mut Bindings, nodes: Vec<LinkNode<Rc<BindingKind>>>) { | ||
226 | for cmd in self.flatten_nodes(nodes) { | ||
227 | match &*cmd { | ||
228 | BindingKind::Empty(name) => { | ||
229 | bindings.push_empty(name); | ||
230 | } | ||
231 | BindingKind::Optional(name) => { | ||
232 | bindings.push_optional(name); | ||
233 | } | ||
234 | BindingKind::Fragment(name, fragment) => { | ||
235 | bindings.inner.insert(name.clone(), Binding::Fragment(fragment.clone())); | ||
236 | } | ||
237 | BindingKind::Nested(idx, list) => { | ||
238 | let list = self.flatten_nested(*idx, *list); | ||
239 | |||
240 | for (idx, iter) in list.enumerate() { | ||
241 | for (key, value) in &iter.inner { | ||
242 | let bindings = bindings | ||
243 | .inner | ||
244 | .entry(key.clone()) | ||
245 | .or_insert_with(|| Binding::Nested(Vec::new())); | ||
246 | |||
247 | if let Binding::Nested(it) = bindings { | ||
248 | // insert empty nested bindings before this one | ||
249 | while it.len() < idx { | ||
250 | it.push(Binding::Nested(Vec::new())); | ||
251 | } | ||
252 | it.push(value.clone()); | ||
253 | } | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | |||
261 | fn flatten_nested_ref(&self, id: usize, len: usize) -> Vec<Vec<LinkNode<Rc<BindingKind>>>> { | ||
262 | self.nested[id] | ||
263 | .iter() | ||
264 | .take(len) | ||
265 | .map(|it| match it { | ||
266 | LinkNode::Node(id) => vec![self.nodes[*id].clone()], | ||
267 | LinkNode::Parent { idx, len } => self.flatten_nested_ref(*idx, *len), | ||
268 | }) | ||
269 | .flatten() | ||
270 | .collect() | ||
271 | } | ||
272 | |||
273 | fn flatten_nested<'a>( | ||
274 | &'a self, | ||
275 | idx: usize, | ||
276 | list: usize, | ||
277 | ) -> impl Iterator<Item = Bindings> + 'a { | ||
278 | let last = self.nodes[idx].clone(); | ||
279 | self.nested[list] | ||
280 | .iter() | ||
281 | .map(move |it| match *it { | ||
282 | LinkNode::Node(idx) => vec![self.nodes[idx].clone()], | ||
283 | LinkNode::Parent { idx, len } => self.flatten_nested_ref(idx, len), | ||
284 | }) | ||
285 | .flatten() | ||
286 | .chain(std::iter::once(last)) | ||
287 | .map(move |iter| { | ||
288 | let mut child_bindings = Bindings::default(); | ||
289 | self.build_recur(&mut child_bindings, iter); | ||
290 | child_bindings | ||
291 | }) | ||
292 | } | ||
293 | |||
294 | fn flatten_nodes_ref(&self, id: usize, len: usize) -> Vec<Rc<BindingKind>> { | ||
295 | self.nodes[id] | ||
296 | .iter() | ||
297 | .take(len) | ||
298 | .map(|it| match it { | ||
299 | LinkNode::Node(it) => vec![it.clone()], | ||
300 | LinkNode::Parent { idx, len } => self.flatten_nodes_ref(*idx, *len), | ||
301 | }) | ||
302 | .flatten() | ||
303 | .collect() | ||
304 | } | ||
305 | |||
306 | fn flatten_nodes<'a>( | ||
307 | &'a self, | ||
308 | nodes: Vec<LinkNode<Rc<BindingKind>>>, | ||
309 | ) -> impl Iterator<Item = Rc<BindingKind>> + 'a { | ||
310 | nodes | ||
311 | .into_iter() | ||
312 | .map(move |it| match it { | ||
313 | LinkNode::Node(it) => vec![it], | ||
314 | LinkNode::Parent { idx, len } => self.flatten_nodes_ref(idx, len), | ||
315 | }) | ||
316 | .flatten() | ||
317 | } | ||
318 | } | ||
319 | |||
320 | #[derive(Debug, Clone)] | ||
166 | struct MatchState<'t> { | 321 | struct MatchState<'t> { |
167 | /// The position of the "dot" in this matcher | 322 | /// The position of the "dot" in this matcher |
168 | dot: OpDelimitedIter<'t>, | 323 | dot: OpDelimitedIter<'t>, |
@@ -187,7 +342,7 @@ struct MatchState<'t> { | |||
187 | sep_parsed: Option<usize>, | 342 | sep_parsed: Option<usize>, |
188 | 343 | ||
189 | /// Matched meta variables bindings | 344 | /// Matched meta variables bindings |
190 | bindings: SmallVec<[Bindings; 4]>, | 345 | bindings: BindingsIdx, |
191 | 346 | ||
192 | /// Cached result of meta variable parsing | 347 | /// Cached result of meta variable parsing |
193 | meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, | 348 | meta_result: Option<(TtIter<'t>, ExpandResult<Option<Fragment>>)>, |
@@ -218,6 +373,7 @@ fn match_loop_inner<'t>( | |||
218 | src: TtIter<'t>, | 373 | src: TtIter<'t>, |
219 | stack: &[TtIter<'t>], | 374 | stack: &[TtIter<'t>], |
220 | res: &mut Match, | 375 | res: &mut Match, |
376 | bindings_builder: &mut BindingsBuilder, | ||
221 | cur_items: &mut SmallVec<[MatchState<'t>; 1]>, | 377 | cur_items: &mut SmallVec<[MatchState<'t>; 1]>, |
222 | bb_items: &mut SmallVec<[MatchState<'t>; 1]>, | 378 | bb_items: &mut SmallVec<[MatchState<'t>; 1]>, |
223 | next_items: &mut Vec<MatchState<'t>>, | 379 | next_items: &mut Vec<MatchState<'t>>, |
@@ -251,12 +407,10 @@ fn match_loop_inner<'t>( | |||
251 | if item.sep_parsed.is_none() { | 407 | if item.sep_parsed.is_none() { |
252 | // Get the `up` matcher | 408 | // Get the `up` matcher |
253 | let mut new_pos = *item.up.clone().unwrap(); | 409 | let mut new_pos = *item.up.clone().unwrap(); |
410 | new_pos.bindings = bindings_builder.copy(&new_pos.bindings); | ||
254 | // Add matches from this repetition to the `matches` of `up` | 411 | // Add matches from this repetition to the `matches` of `up` |
255 | if let Some(bindings) = new_pos.bindings.last_mut() { | 412 | bindings_builder.push_nested(&mut new_pos.bindings, &item.bindings); |
256 | for (i, b) in item.bindings.iter_mut().enumerate() { | 413 | |
257 | bindings.push_nested(i, b.clone()).unwrap(); | ||
258 | } | ||
259 | } | ||
260 | // Move the "dot" past the repetition in `up` | 414 | // Move the "dot" past the repetition in `up` |
261 | new_pos.dot.next(); | 415 | new_pos.dot.next(); |
262 | new_pos.is_error = new_pos.is_error || item.is_error; | 416 | new_pos.is_error = new_pos.is_error || item.is_error; |
@@ -280,7 +434,7 @@ fn match_loop_inner<'t>( | |||
280 | else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { | 434 | else if item.sep_kind != Some(RepeatKind::ZeroOrOne) { |
281 | item.dot = item.dot.reset(); | 435 | item.dot = item.dot.reset(); |
282 | item.sep_parsed = None; | 436 | item.sep_parsed = None; |
283 | item.bindings.push(Bindings::default()); | 437 | bindings_builder.push_default(&mut item.bindings); |
284 | cur_items.push(item); | 438 | cur_items.push(item); |
285 | } | 439 | } |
286 | } else { | 440 | } else { |
@@ -298,12 +452,12 @@ fn match_loop_inner<'t>( | |||
298 | OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { | 452 | OpDelimited::Op(Op::Repeat { tokens, kind, separator }) => { |
299 | if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { | 453 | if matches!(kind, RepeatKind::ZeroOrMore | RepeatKind::ZeroOrOne) { |
300 | let mut new_item = item.clone(); | 454 | let mut new_item = item.clone(); |
455 | new_item.bindings = bindings_builder.copy(&new_item.bindings); | ||
301 | new_item.dot.next(); | 456 | new_item.dot.next(); |
302 | let mut vars = Vec::new(); | 457 | let mut vars = Vec::new(); |
303 | let bindings = new_item.bindings.last_mut().unwrap(); | ||
304 | collect_vars(&mut vars, tokens); | 458 | collect_vars(&mut vars, tokens); |
305 | for var in vars { | 459 | for var in vars { |
306 | bindings.push_empty(&var); | 460 | bindings_builder.push_empty(&mut new_item.bindings, &var); |
307 | } | 461 | } |
308 | cur_items.push(new_item); | 462 | cur_items.push(new_item); |
309 | } | 463 | } |
@@ -314,7 +468,7 @@ fn match_loop_inner<'t>( | |||
314 | sep: separator.clone(), | 468 | sep: separator.clone(), |
315 | sep_kind: Some(*kind), | 469 | sep_kind: Some(*kind), |
316 | sep_parsed: None, | 470 | sep_parsed: None, |
317 | bindings: smallvec![Bindings::default()], | 471 | bindings: bindings_builder.alloc(), |
318 | meta_result: None, | 472 | meta_result: None, |
319 | is_error: false, | 473 | is_error: false, |
320 | }) | 474 | }) |
@@ -339,7 +493,7 @@ fn match_loop_inner<'t>( | |||
339 | item.meta_result = Some((fork, match_res)); | 493 | item.meta_result = Some((fork, match_res)); |
340 | try_push!(bb_items, item); | 494 | try_push!(bb_items, item); |
341 | } else { | 495 | } else { |
342 | item.bindings.last_mut().unwrap().push_optional(name); | 496 | bindings_builder.push_optional(&mut item.bindings, &name); |
343 | item.dot.next(); | 497 | item.dot.next(); |
344 | cur_items.push(item); | 498 | cur_items.push(item); |
345 | } | 499 | } |
@@ -348,11 +502,11 @@ fn match_loop_inner<'t>( | |||
348 | res.add_err(err); | 502 | res.add_err(err); |
349 | match match_res.value { | 503 | match match_res.value { |
350 | Some(fragment) => { | 504 | Some(fragment) => { |
351 | item.bindings | 505 | bindings_builder.push_fragment( |
352 | .last_mut() | 506 | &mut item.bindings, |
353 | .unwrap() | 507 | &name, |
354 | .inner | 508 | fragment, |
355 | .push((name.clone(), Binding::Fragment(fragment))); | 509 | ); |
356 | } | 510 | } |
357 | _ => {} | 511 | _ => {} |
358 | } | 512 | } |
@@ -394,6 +548,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
394 | let mut res = Match::default(); | 548 | let mut res = Match::default(); |
395 | let mut error_reover_item = None; | 549 | let mut error_reover_item = None; |
396 | 550 | ||
551 | let mut bindings_builder = BindingsBuilder::default(); | ||
552 | |||
397 | let mut cur_items = smallvec![MatchState { | 553 | let mut cur_items = smallvec![MatchState { |
398 | dot: pattern.iter_delimited(None), | 554 | dot: pattern.iter_delimited(None), |
399 | stack: Default::default(), | 555 | stack: Default::default(), |
@@ -401,7 +557,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
401 | sep: None, | 557 | sep: None, |
402 | sep_kind: None, | 558 | sep_kind: None, |
403 | sep_parsed: None, | 559 | sep_parsed: None, |
404 | bindings: smallvec![Bindings::default()], | 560 | bindings: bindings_builder.alloc(), |
405 | is_error: false, | 561 | is_error: false, |
406 | meta_result: None, | 562 | meta_result: None, |
407 | }]; | 563 | }]; |
@@ -419,6 +575,7 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
419 | src.clone(), | 575 | src.clone(), |
420 | &stack, | 576 | &stack, |
421 | &mut res, | 577 | &mut res, |
578 | &mut bindings_builder, | ||
422 | &mut cur_items, | 579 | &mut cur_items, |
423 | &mut bb_items, | 580 | &mut bb_items, |
424 | &mut next_items, | 581 | &mut next_items, |
@@ -428,9 +585,9 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
428 | stdx::always!(cur_items.is_empty()); | 585 | stdx::always!(cur_items.is_empty()); |
429 | 586 | ||
430 | if error_items.len() > 0 { | 587 | if error_items.len() > 0 { |
431 | error_reover_item = error_items.pop(); | 588 | error_reover_item = error_items.pop().map(|it| it.bindings); |
432 | } else if eof_items.len() > 0 { | 589 | } else if eof_items.len() > 0 { |
433 | error_reover_item = Some(eof_items[0].clone()); | 590 | error_reover_item = Some(eof_items[0].bindings.clone()); |
434 | } | 591 | } |
435 | 592 | ||
436 | // We need to do some post processing after the `match_loop_inner`. | 593 | // We need to do some post processing after the `match_loop_inner`. |
@@ -440,11 +597,11 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
440 | if eof_items.len() == 1 { | 597 | if eof_items.len() == 1 { |
441 | // remove all errors, because it is the correct answer ! | 598 | // remove all errors, because it is the correct answer ! |
442 | res = Match::default(); | 599 | res = Match::default(); |
443 | res.bindings = eof_items[0].bindings[0].clone(); | 600 | res.bindings = bindings_builder.build(&eof_items[0].bindings); |
444 | } else { | 601 | } else { |
445 | // Error recovery | 602 | // Error recovery |
446 | if error_reover_item.is_some() { | 603 | if error_reover_item.is_some() { |
447 | res.bindings = error_reover_item.unwrap().bindings[0].clone(); | 604 | res.bindings = bindings_builder.build(&error_reover_item.unwrap()); |
448 | } | 605 | } |
449 | res.add_err(ExpandError::UnexpectedToken); | 606 | res.add_err(ExpandError::UnexpectedToken); |
450 | } | 607 | } |
@@ -467,8 +624,8 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
467 | } | 624 | } |
468 | res.add_err(err!("leftover tokens")); | 625 | res.add_err(err!("leftover tokens")); |
469 | 626 | ||
470 | if let Some(mut error_reover_item) = error_reover_item { | 627 | if let Some(error_reover_item) = error_reover_item { |
471 | res.bindings = error_reover_item.bindings.remove(0); | 628 | res.bindings = bindings_builder.build(&error_reover_item); |
472 | } | 629 | } |
473 | return res; | 630 | return res; |
474 | } | 631 | } |
@@ -494,12 +651,13 @@ fn match_loop(pattern: &MetaTemplate, src: &tt::Subtree) -> Match { | |||
494 | 651 | ||
495 | if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { | 652 | if let Some(OpDelimited::Op(Op::Var { name, .. })) = item.dot.peek() { |
496 | let (iter, match_res) = item.meta_result.take().unwrap(); | 653 | let (iter, match_res) = item.meta_result.take().unwrap(); |
497 | let bindings = item.bindings.last_mut().unwrap(); | ||
498 | match match_res.value { | 654 | match match_res.value { |
499 | Some(fragment) => { | 655 | Some(fragment) => { |
500 | bindings.inner.push((name.clone(), Binding::Fragment(fragment))); | 656 | bindings_builder.push_fragment(&mut item.bindings, &name, fragment); |
657 | } | ||
658 | None if match_res.err.is_none() => { | ||
659 | bindings_builder.push_optional(&mut item.bindings, &name); | ||
501 | } | 660 | } |
502 | None if match_res.err.is_none() => bindings.push_optional(name), | ||
503 | _ => {} | 661 | _ => {} |
504 | } | 662 | } |
505 | if let Some(err) = match_res.err { | 663 | if let Some(err) = match_res.err { |
diff --git a/crates/mbe/src/expander/transcriber.rs b/crates/mbe/src/expander/transcriber.rs index ad9953a7d..c679e5e5d 100644 --- a/crates/mbe/src/expander/transcriber.rs +++ b/crates/mbe/src/expander/transcriber.rs | |||
@@ -13,17 +13,13 @@ use crate::{ | |||
13 | 13 | ||
14 | impl Bindings { | 14 | impl Bindings { |
15 | fn contains(&self, name: &str) -> bool { | 15 | fn contains(&self, name: &str) -> bool { |
16 | self.inner.iter().any(|(n, _)| n == name) | 16 | self.inner.contains_key(name) |
17 | } | 17 | } |
18 | 18 | ||
19 | fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { | 19 | fn get(&self, name: &str, nesting: &mut [NestingState]) -> Result<&Fragment, ExpandError> { |
20 | let mut b: &Binding = self | 20 | let mut b: &Binding = self.inner.get(name).ok_or_else(|| { |
21 | .inner | 21 | ExpandError::BindingError(format!("could not find binding `{}`", name)) |
22 | .iter() | 22 | })?; |
23 | .find_map(|(n, b)| if n == name { Some(b) } else { None }) | ||
24 | .ok_or_else(|| { | ||
25 | ExpandError::BindingError(format!("could not find binding `{}`", name)) | ||
26 | })?; | ||
27 | for nesting_state in nesting.iter_mut() { | 23 | for nesting_state in nesting.iter_mut() { |
28 | nesting_state.hit = true; | 24 | nesting_state.hit = true; |
29 | b = match b { | 25 | b = match b { |
diff --git a/crates/rust-analyzer/build.rs b/crates/rust-analyzer/build.rs index 5ae76ba30..999dc5928 100644 --- a/crates/rust-analyzer/build.rs +++ b/crates/rust-analyzer/build.rs | |||
@@ -39,8 +39,7 @@ fn set_rerun() { | |||
39 | } | 39 | } |
40 | 40 | ||
41 | fn rev() -> Option<String> { | 41 | fn rev() -> Option<String> { |
42 | let output = Command::new("git").args(&["rev-parse", "HEAD"]).output().ok()?; | 42 | let output = Command::new("git").args(&["describe", "--tags"]).output().ok()?; |
43 | let stdout = String::from_utf8(output.stdout).ok()?; | 43 | let stdout = String::from_utf8(output.stdout).ok()?; |
44 | let short_hash = stdout.get(0..7)?; | 44 | Some(stdout) |
45 | Some(short_hash.to_owned()) | ||
46 | } | 45 | } |
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index 8301dc28a..9d9a01e30 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs | |||
@@ -227,6 +227,53 @@ impl Subtree { | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | 229 | ||
230 | impl Subtree { | ||
231 | /// A simple line string used for debugging | ||
232 | pub fn as_debug_string(&self) -> String { | ||
233 | let delim = match self.delimiter_kind() { | ||
234 | Some(DelimiterKind::Brace) => ("{", "}"), | ||
235 | Some(DelimiterKind::Bracket) => ("[", "]"), | ||
236 | Some(DelimiterKind::Parenthesis) => ("(", ")"), | ||
237 | None => (" ", " "), | ||
238 | }; | ||
239 | |||
240 | let mut res = String::new(); | ||
241 | res.push_str(delim.0); | ||
242 | let mut iter = self.token_trees.iter(); | ||
243 | let mut last = None; | ||
244 | while let Some(child) = iter.next() { | ||
245 | let s = match child { | ||
246 | TokenTree::Leaf(it) => { | ||
247 | let s = match it { | ||
248 | Leaf::Literal(it) => it.text.to_string(), | ||
249 | Leaf::Punct(it) => it.char.to_string(), | ||
250 | Leaf::Ident(it) => it.text.to_string(), | ||
251 | }; | ||
252 | match (it, last) { | ||
253 | (Leaf::Ident(_), Some(&TokenTree::Leaf(Leaf::Ident(_)))) => { | ||
254 | " ".to_string() + &s | ||
255 | } | ||
256 | (Leaf::Punct(_), Some(&TokenTree::Leaf(Leaf::Punct(punct)))) => { | ||
257 | if punct.spacing == Spacing::Alone { | ||
258 | " ".to_string() + &s | ||
259 | } else { | ||
260 | s | ||
261 | } | ||
262 | } | ||
263 | _ => s, | ||
264 | } | ||
265 | } | ||
266 | TokenTree::Subtree(it) => it.as_debug_string(), | ||
267 | }; | ||
268 | res.push_str(&s); | ||
269 | last = Some(child); | ||
270 | } | ||
271 | |||
272 | res.push_str(delim.1); | ||
273 | res | ||
274 | } | ||
275 | } | ||
276 | |||
230 | pub mod buffer; | 277 | pub mod buffer; |
231 | 278 | ||
232 | #[derive(Debug, PartialEq, Eq, Clone)] | 279 | #[derive(Debug, PartialEq, Eq, Clone)] |
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index 283b9a160..3e96fbad8 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -253,11 +253,10 @@ export function ssr(ctx: Ctx): Cmd { | |||
253 | export function serverVersion(ctx: Ctx): Cmd { | 253 | export function serverVersion(ctx: Ctx): Cmd { |
254 | return async () => { | 254 | return async () => { |
255 | const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); | 255 | const { stdout } = spawnSync(ctx.serverPath, ["--version"], { encoding: "utf8" }); |
256 | const commitHash = stdout.slice(`rust-analyzer `.length).trim(); | 256 | const versionString = stdout.slice(`rust-analyzer `.length).trim(); |
257 | const { releaseTag } = ctx.config.package; | ||
258 | 257 | ||
259 | void vscode.window.showInformationMessage( | 258 | void vscode.window.showInformationMessage( |
260 | `rust-analyzer version: ${releaseTag ?? "unreleased"} (${commitHash})` | 259 | `rust-analyzer version: ${versionString}` |
261 | ); | 260 | ); |
262 | }; | 261 | }; |
263 | } | 262 | } |