diff options
author | uHOOCCOOHu <[email protected]> | 2019-09-26 19:04:47 +0100 |
---|---|---|
committer | uHOOCCOOHu <[email protected]> | 2019-09-26 19:04:47 +0100 |
commit | 128dc5355b81b0217fede903ae79f75ba0124716 (patch) | |
tree | 7ded1337bc7a77c66098d4307a2d381cb9a1f3b2 | |
parent | 53a30d9e69ee5149e4fdb1c6fe4081281e879d0e (diff) |
Refactor `Name` ready for hygienic macro
-rw-r--r-- | crates/ra_hir/src/adt.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/name.rs | 157 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 9 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 10 |
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)] |
9 | pub struct Name { | 9 | pub struct Name(Repr); |
10 | text: SmolStr, | ||
11 | } | ||
12 | 10 | ||
13 | impl fmt::Display for Name { | 11 | #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] |
14 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | 12 | enum Repr { |
15 | fmt::Display::fmt(&self.text, f) | 13 | Text(SmolStr), |
16 | } | 14 | TupleField(usize), |
17 | } | 15 | } |
18 | 16 | ||
19 | impl fmt::Debug for Name { | 17 | impl 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 | ||
59 | impl AsName for ast::NameRef { | 69 | impl 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 | ||
66 | impl AsName for ast::Name { | 78 | impl 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 | ||
82 | impl AsName for ra_db::Dependency { | 93 | impl 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 |
89 | pub(crate) const ISIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"isize")); | 100 | pub(crate) const ISIZE: Name = Name::new_inline_ascii(5, b"isize"); |
90 | pub(crate) const I8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"i8")); | 101 | pub(crate) const I8: Name = Name::new_inline_ascii(2, b"i8"); |
91 | pub(crate) const I16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i16")); | 102 | pub(crate) const I16: Name = Name::new_inline_ascii(3, b"i16"); |
92 | pub(crate) const I32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i32")); | 103 | pub(crate) const I32: Name = Name::new_inline_ascii(3, b"i32"); |
93 | pub(crate) const I64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"i64")); | 104 | pub(crate) const I64: Name = Name::new_inline_ascii(3, b"i64"); |
94 | pub(crate) const I128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"i128")); | 105 | pub(crate) const I128: Name = Name::new_inline_ascii(4, b"i128"); |
95 | pub(crate) const USIZE: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"usize")); | 106 | pub(crate) const USIZE: Name = Name::new_inline_ascii(5, b"usize"); |
96 | pub(crate) const U8: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"u8")); | 107 | pub(crate) const U8: Name = Name::new_inline_ascii(2, b"u8"); |
97 | pub(crate) const U16: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u16")); | 108 | pub(crate) const U16: Name = Name::new_inline_ascii(3, b"u16"); |
98 | pub(crate) const U32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u32")); | 109 | pub(crate) const U32: Name = Name::new_inline_ascii(3, b"u32"); |
99 | pub(crate) const U64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"u64")); | 110 | pub(crate) const U64: Name = Name::new_inline_ascii(3, b"u64"); |
100 | pub(crate) const U128: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"u128")); | 111 | pub(crate) const U128: Name = Name::new_inline_ascii(4, b"u128"); |
101 | pub(crate) const F32: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f32")); | 112 | pub(crate) const F32: Name = Name::new_inline_ascii(3, b"f32"); |
102 | pub(crate) const F64: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"f64")); | 113 | pub(crate) const F64: Name = Name::new_inline_ascii(3, b"f64"); |
103 | pub(crate) const BOOL: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"bool")); | 114 | pub(crate) const BOOL: Name = Name::new_inline_ascii(4, b"bool"); |
104 | pub(crate) const CHAR: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"char")); | 115 | pub(crate) const CHAR: Name = Name::new_inline_ascii(4, b"char"); |
105 | pub(crate) const STR: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"str")); | 116 | pub(crate) const STR: Name = Name::new_inline_ascii(3, b"str"); |
106 | 117 | ||
107 | // Special names | 118 | // Special names |
108 | pub(crate) const SELF_PARAM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"self")); | 119 | pub(crate) const SELF_PARAM: Name = Name::new_inline_ascii(4, b"self"); |
109 | pub(crate) const SELF_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Self")); | 120 | pub(crate) const SELF_TYPE: Name = Name::new_inline_ascii(4, b"Self"); |
110 | pub(crate) const MACRO_RULES: Name = Name::new(SmolStr::new_inline_from_ascii(11, b"macro_rules")); | 121 | pub(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) |
113 | pub(crate) const STD: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"std")); | 124 | pub(crate) const STD: Name = Name::new_inline_ascii(3, b"std"); |
114 | pub(crate) const ITER: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"iter")); | 125 | pub(crate) const ITER: Name = Name::new_inline_ascii(4, b"iter"); |
115 | pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); | 126 | pub(crate) const OPS: Name = Name::new_inline_ascii(3, b"ops"); |
116 | pub(crate) const FUTURE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); | 127 | pub(crate) const FUTURE: Name = Name::new_inline_ascii(6, b"future"); |
117 | pub(crate) const RESULT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); | 128 | pub(crate) const RESULT: Name = Name::new_inline_ascii(6, b"result"); |
118 | pub(crate) const BOXED: Name = Name::new(SmolStr::new_inline_from_ascii(5, b"boxed")); | 129 | pub(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) |
121 | pub(crate) const INTO_ITERATOR_TYPE: Name = | 132 | pub(crate) const INTO_ITERATOR_TYPE: Name = Name::new_inline_ascii(12, b"IntoIterator"); |
122 | Name::new(SmolStr::new_inline_from_ascii(12, b"IntoIterator")); | 133 | pub(crate) const ITEM_TYPE: Name = Name::new_inline_ascii(4, b"Item"); |
123 | pub(crate) const ITEM_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item")); | 134 | pub(crate) const TRY_TYPE: Name = Name::new_inline_ascii(3, b"Try"); |
124 | pub(crate) const TRY_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); | 135 | pub(crate) const OK_TYPE: Name = Name::new_inline_ascii(2, b"Ok"); |
125 | pub(crate) const OK_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); | 136 | pub(crate) const FUTURE_TYPE: Name = Name::new_inline_ascii(6, b"Future"); |
126 | pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); | 137 | pub(crate) const RESULT_TYPE: Name = Name::new_inline_ascii(6, b"Result"); |
127 | pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); | 138 | pub(crate) const OUTPUT_TYPE: Name = Name::new_inline_ascii(6, b"Output"); |
128 | pub(crate) const OUTPUT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); | 139 | pub(crate) const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target"); |
129 | pub(crate) const TARGET_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); | 140 | pub(crate) const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); |
130 | pub(crate) const BOX_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Box")); | ||
131 | |||
132 | fn 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 | ||
26 | fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { | 36 | fn text_of_first_token(node: &SyntaxNode) -> &SmolStr { |