aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruHOOCCOOHu <[email protected]>2019-09-26 19:04:47 +0100
committeruHOOCCOOHu <[email protected]>2019-09-26 19:04:47 +0100
commit128dc5355b81b0217fede903ae79f75ba0124716 (patch)
tree7ded1337bc7a77c66098d4307a2d381cb9a1f3b2
parent53a30d9e69ee5149e4fdb1c6fe4081281e879d0e (diff)
Refactor `Name` ready for hygienic macro
-rw-r--r--crates/ra_hir/src/adt.rs2
-rw-r--r--crates/ra_hir/src/name.rs157
-rw-r--r--crates/ra_hir/src/ty/infer.rs9
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs10
4 files changed, 94 insertions, 84 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index fbb4ff4d8..99d286215 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -133,7 +133,7 @@ impl VariantData {
133 .fields() 133 .fields()
134 .enumerate() 134 .enumerate()
135 .map(|(i, fd)| StructFieldData { 135 .map(|(i, fd)| StructFieldData {
136 name: Name::tuple_field_name(i), 136 name: Name::new_tuple_field(i),
137 type_ref: TypeRef::from_ast_opt(fd.type_ref()), 137 type_ref: TypeRef::from_ast_opt(fd.type_ref()),
138 }) 138 })
139 .collect(); 139 .collect();
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs
index 1bf993ffb..d50867f5d 100644
--- a/crates/ra_hir/src/name.rs
+++ b/crates/ra_hir/src/name.rs
@@ -5,20 +5,21 @@ use ra_syntax::{ast, SmolStr};
5/// `Name` is a wrapper around string, which is used in hir for both references 5/// `Name` is a wrapper around string, which is used in hir for both references
6/// and declarations. In theory, names should also carry hygiene info, but we are 6/// and declarations. In theory, names should also carry hygiene info, but we are
7/// not there yet! 7/// not there yet!
8#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] 8#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
9pub struct Name { 9pub struct Name(Repr);
10 text: SmolStr,
11}
12 10
13impl fmt::Display for Name { 11#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 12enum Repr {
15 fmt::Display::fmt(&self.text, f) 13 Text(SmolStr),
16 } 14 TupleField(usize),
17} 15}
18 16
19impl fmt::Debug for Name { 17impl fmt::Display for Name {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
21 fmt::Debug::fmt(&self.text, f) 19 match &self.0 {
20 Repr::Text(text) => fmt::Display::fmt(&text, f),
21 Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
22 }
22 } 23 }
23} 24}
24 25
@@ -26,29 +27,38 @@ impl Name {
26 /// Note: this is private to make creating name from random string hard. 27 /// Note: this is private to make creating name from random string hard.
27 /// Hopefully, this should allow us to integrate hygiene cleaner in the 28 /// Hopefully, this should allow us to integrate hygiene cleaner in the
28 /// future, and to switch to interned representation of names. 29 /// future, and to switch to interned representation of names.
29 const fn new(text: SmolStr) -> Name { 30 const fn new_text(text: SmolStr) -> Name {
30 Name { text } 31 Name(Repr::Text(text))
31 } 32 }
32 33
33 pub(crate) fn missing() -> Name { 34 pub(crate) fn new_tuple_field(idx: usize) -> Name {
34 Name::new("[missing name]".into()) 35 Name(Repr::TupleField(idx))
35 } 36 }
36 37
37 pub(crate) fn tuple_field_name(idx: usize) -> Name { 38 /// Shortcut to create inline plain text name
38 Name::new(idx.to_string().into()) 39 const fn new_inline_ascii(len: usize, text: &[u8]) -> Name {
40 Name::new_text(SmolStr::new_inline_from_ascii(len, text))
39 } 41 }
40 42
41 // There's should be no way to extract a string out of `Name`: `Name` in the 43 /// Resolve a name from the text of token.
42 // future, `Name` will include hygiene information, and you can't encode 44 fn resolve(raw_text: &SmolStr) -> Name {
43 // hygiene into a String. 45 let raw_start = "r#";
44 // 46 if raw_text.as_str().starts_with(raw_start) {
45 // If you need to compare something with `Name`, compare `Name`s directly. 47 Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
46 // 48 } else {
47 // If you need to render `Name` for the user, use the `Display` impl, but be 49 Name::new_text(raw_text.clone())
48 // aware that it strips hygiene info. 50 }
49 #[deprecated(note = "use to_string instead")] 51 }
50 pub fn as_smolstr(&self) -> &SmolStr { 52
51 &self.text 53 pub(crate) fn missing() -> Name {
54 Name::new_text("[missing name]".into())
55 }
56
57 pub(crate) fn as_tuple_index(&self) -> Option<usize> {
58 match self.0 {
59 Repr::TupleField(idx) => Some(idx),
60 _ => None,
61 }
52 } 62 }
53} 63}
54 64
@@ -58,15 +68,16 @@ pub(crate) trait AsName {
58 68
59impl AsName for ast::NameRef { 69impl AsName for ast::NameRef {
60 fn as_name(&self) -> Name { 70 fn as_name(&self) -> Name {
61 let name = resolve_name(self.text()); 71 match self.as_tuple_field() {
62 Name::new(name) 72 Some(idx) => Name::new_tuple_field(idx),
73 None => Name::resolve(self.text()),
74 }
63 } 75 }
64} 76}
65 77
66impl AsName for ast::Name { 78impl AsName for ast::Name {
67 fn as_name(&self) -> Name { 79 fn as_name(&self) -> Name {
68 let name = resolve_name(self.text()); 80 Name::resolve(self.text())
69 Name::new(name)
70 } 81 }
71} 82}
72 83
@@ -74,66 +85,56 @@ impl AsName for ast::FieldKind {
74 fn as_name(&self) -> Name { 85 fn as_name(&self) -> Name {
75 match self { 86 match self {
76 ast::FieldKind::Name(nr) => nr.as_name(), 87 ast::FieldKind::Name(nr) => nr.as_name(),
77 ast::FieldKind::Index(idx) => Name::new(idx.text().clone()), 88 ast::FieldKind::Index(idx) => Name::new_tuple_field(idx.text().parse().unwrap()),
78 } 89 }
79 } 90 }
80} 91}
81 92
82impl AsName for ra_db::Dependency { 93impl AsName for ra_db::Dependency {
83 fn as_name(&self) -> Name { 94 fn as_name(&self) -> Name {
84 Name::new(self.name.clone()) 95 Name::new_text(self.name.clone())
85 } 96 }
86} 97}
87 98
88// Primitives 99// Primitives
89pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize")); 100pub(crate) const ISIZE: Name = Name::new_inline_ascii(5, b"isize");
90pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8")); 101pub(crate) const I8: Name = Name::new_inline_ascii(2, b"i8");
91pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16")); 102pub(crate) const I16: Name = Name::new_inline_ascii(3, b"i16");
92pub(crate) const I32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i32")); 103pub(crate) const I32: Name = Name::new_inline_ascii(3, b"i32");
93pub(crate) const I64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i64")); 104pub(crate) const I64: Name = Name::new_inline_ascii(3, b"i64");
94pub(crate) const I128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"i128")); 105pub(crate) const I128: Name = Name::new_inline_ascii(4, b"i128");
95pub(crate) const USIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"usize")); 106pub(crate) const USIZE: Name = Name::new_inline_ascii(5, b"usize");
96pub(crate) const U8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"u8")); 107pub(crate) const U8: Name = Name::new_inline_ascii(2, b"u8");
97pub(crate) const U16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u16")); 108pub(crate) const U16: Name = Name::new_inline_ascii(3, b"u16");
98pub(crate) const U32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u32")); 109pub(crate) const U32: Name = Name::new_inline_ascii(3, b"u32");
99pub(crate) const U64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u64")); 110pub(crate) const U64: Name = Name::new_inline_ascii(3, b"u64");
100pub(crate) const U128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"u128")); 111pub(crate) const U128: Name = Name::new_inline_ascii(4, b"u128");
101pub(crate) const F32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f32")); 112pub(crate) const F32: Name = Name::new_inline_ascii(3, b"f32");
102pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")); 113pub(crate) const F64: Name = Name::new_inline_ascii(3, b"f64");
103pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool")); 114pub(crate) const BOOL: Name = Name::new_inline_ascii(4, b"bool");
104pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char")); 115pub(crate) const CHAR: Name = Name::new_inline_ascii(4, b"char");
105pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str")); 116pub(crate) const STR: Name = Name::new_inline_ascii(3, b"str");
106 117
107// Special names 118// Special names
108pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self")); 119pub(crate) const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self");
109pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self")); 120pub(crate) const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self");
110pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules")); 121pub(crate) const MACRO_RULES: Name = Name::new_inline_ascii(11, b"macro_rules");
111 122
112// Components of known path (value or mod name) 123// Components of known path (value or mod name)
113pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std")); 124pub(crate) const STD: Name = Name::new_inline_ascii(3, b"std");
114pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter")); 125pub(crate) const ITER: Name = Name::new_inline_ascii(4, b"iter");
115pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); 126pub(crate) const OPS: Name = Name::new_inline_ascii(3, b"ops");
116pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); 127pub(crate) const FUTURE: Name = Name::new_inline_ascii(6, b"future");
117pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); 128pub(crate) const RESULT: Name = Name::new_inline_ascii(6, b"result");
118pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed")); 129pub(crate) const BOXED: Name = Name::new_inline_ascii(5, b"boxed");
119 130
120// Components of known path (type name) 131// Components of known path (type name)
121pub(crate) const INTO_ITERATOR_TYPE: Name = 132pub(crate) const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator");
122 Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator")); 133pub(crate) const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item");
123pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item")); 134pub(crate) const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try");
124pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); 135pub(crate) const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok");
125pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); 136pub(crate) const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future");
126pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); 137pub(crate) const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result");
127pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); 138pub(crate) const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output");
128pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); 139pub(crate) const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target");
129pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); 140pub(crate) const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
130pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box"));
131
132fn resolve_name(text: &SmolStr) -> SmolStr {
133 let raw_start = "r#";
134 if text.as_str().starts_with(raw_start) {
135 SmolStr::new(&text[raw_start.len()..])
136 } else {
137 text.clone()
138 }
139}
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index db3377357..8f92468e6 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -609,7 +609,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
609 609
610 for (i, &subpat) in subpats.iter().enumerate() { 610 for (i, &subpat) in subpats.iter().enumerate() {
611 let expected_ty = def 611 let expected_ty = def
612 .and_then(|d| d.field(self.db, &Name::tuple_field_name(i))) 612 .and_then(|d| d.field(self.db, &Name::new_tuple_field(i)))
613 .map_or(Ty::Unknown, |field| field.ty(self.db)) 613 .map_or(Ty::Unknown, |field| field.ty(self.db))
614 .subst(&substs); 614 .subst(&substs);
615 let expected_ty = self.normalize_associated_types_in(expected_ty); 615 let expected_ty = self.normalize_associated_types_in(expected_ty);
@@ -1375,10 +1375,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1375 ) 1375 )
1376 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { 1376 .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) {
1377 Ty::Apply(a_ty) => match a_ty.ctor { 1377 Ty::Apply(a_ty) => match a_ty.ctor {
1378 TypeCtor::Tuple { .. } => { 1378 TypeCtor::Tuple { .. } => name
1379 let i = name.to_string().parse::<usize>().ok(); 1379 .as_tuple_index()
1380 i.and_then(|i| a_ty.parameters.0.get(i).cloned()) 1380 .and_then(|idx| a_ty.parameters.0.get(idx).cloned()),
1381 }
1382 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| { 1381 TypeCtor::Adt(Adt::Struct(s)) => s.field(self.db, name).map(|field| {
1383 self.write_field_resolution(tgt_expr, field); 1382 self.write_field_resolution(tgt_expr, field);
1384 field.ty(self.db).subst(&a_ty.parameters) 1383 field.ty(self.db).subst(&a_ty.parameters)
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index 5f7e9f5b1..0433edb84 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -21,6 +21,16 @@ impl ast::NameRef {
21 pub fn text(&self) -> &SmolStr { 21 pub fn text(&self) -> &SmolStr {
22 text_of_first_token(self.syntax()) 22 text_of_first_token(self.syntax())
23 } 23 }
24
25 pub fn as_tuple_field(&self) -> Option<usize> {
26 self.syntax().children_with_tokens().find_map(|c| {
27 if c.kind() == SyntaxKind::INT_NUMBER {
28 c.as_token().and_then(|tok| tok.text().as_str().parse().ok())
29 } else {
30 None
31 }
32 })
33 }
24} 34}
25 35
26fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { 36fn text_of_first_token(node: &SyntaxNode) -> &SmolStr {