aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/item_tree.rs12
-rw-r--r--crates/hir_def/src/test_db.rs9
-rw-r--r--crates/hir_expand/src/db.rs2
-rw-r--r--crates/hir_ty/src/lower.rs31
-rw-r--r--crates/hir_ty/src/method_resolution.rs3
-rw-r--r--crates/hir_ty/src/tests.rs10
-rw-r--r--crates/hir_ty/src/traits.rs23
-rw-r--r--crates/hir_ty/src/traits/chalk.rs19
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs38
-rw-r--r--crates/mbe/src/expander.rs4
-rw-r--r--crates/mbe/src/expander/matcher.rs272
-rw-r--r--crates/mbe/src/expander/transcriber.rs12
-rw-r--r--crates/tt/src/lib.rs47
13 files changed, 325 insertions, 157 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;
15use syntax::{algo, ast, AstNode, TextRange, TextSize}; 15use syntax::{algo, ast, AstNode, TextRange, TextSize};
16use test_utils::extract_annotations; 16use test_utils::extract_annotations;
17 17
18use crate::{db::DefDatabase, nameres::DefMap, Lookup, ModuleDefId, ModuleId}; 18use 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 @@
8use std::{iter, sync::Arc}; 8use std::{iter, sync::Arc};
9 9
10use base_db::CrateId; 10use base_db::CrateId;
11use chalk_ir::Mutability; 11use chalk_ir::{cast::Cast, Mutability};
12use hir_def::{ 12use 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
28use crate::{ 28use 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};
24use hir_expand::{db::AstDatabase, InFile}; 25use 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)]
42pub struct TraitEnvironment { 42pub 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
46impl TraitEnvironment { 49impl 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;
33mod interner; 33mod interner;
34mod mapping; 34mod mapping;
35 35
36pub(super) trait ToChalk { 36pub(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
42pub(super) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 42pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
43where 43where
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
23use super::interner::*; 23use super::interner::*;
@@ -536,31 +536,6 @@ where
536 } 536 }
537} 537}
538 538
539impl 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
564impl<T: ToChalk> ToChalk for InEnvironment<T> 539impl<T: ToChalk> ToChalk for InEnvironment<T>
565where 540where
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 @@
5mod matcher; 5mod matcher;
6mod transcriber; 6mod transcriber;
7 7
8use smallvec::SmallVec; 8use rustc_hash::FxHashMap;
9use syntax::SmolStr; 9use syntax::SmolStr;
10 10
11use crate::{ExpandError, ExpandResult}; 11use 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)]
98struct Bindings { 98struct 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
62use std::rc::Rc;
63
62use crate::{ 64use 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)]
140enum BindingKind {
141 Empty(SmolStr),
142 Optional(SmolStr),
143 Fragment(SmolStr, Fragment),
144 Nested(usize, usize),
145}
146
147#[derive(Debug, Clone)]
148struct BindingsIdx(usize, usize);
149
150#[derive(Debug, Clone)]
151enum LinkNode<T> {
152 Node(T),
153 Parent { idx: usize, len: usize },
154}
155
156#[derive(Default)]
157struct BindingsBuilder {
158 nodes: Vec<Vec<LinkNode<Rc<BindingKind>>>>,
159 nested: Vec<Vec<LinkNode<usize>>>,
160}
161
162impl 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)]
166struct MatchState<'t> { 321struct 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
14impl Bindings { 14impl 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/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
230impl 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
230pub mod buffer; 277pub mod buffer;
231 278
232#[derive(Debug, PartialEq, Eq, Clone)] 279#[derive(Debug, PartialEq, Eq, Clone)]