Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/name.rs')
-rw-r--r--crates/hir-expand/src/name.rs80
1 files changed, 58 insertions, 22 deletions
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index c3462beac7..f8dbb84277 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -24,27 +24,6 @@ enum Repr {
TupleField(usize),
}
-impl fmt::Display for Name {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match &self.0 {
- Repr::Text(text) => fmt::Display::fmt(&text, f),
- Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
- }
- }
-}
-
-impl<'a> fmt::Display for UnescapedName<'a> {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match &self.0 .0 {
- Repr::Text(text) => {
- let text = text.strip_prefix("r#").unwrap_or(text);
- fmt::Display::fmt(&text, f)
- }
- Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
- }
- }
-}
-
impl<'a> UnescapedName<'a> {
/// Returns the textual representation of this name as a [`SmolStr`]. Prefer using this over
/// [`ToString::to_string`] if possible as this conversion is cheaper in the general case.
@@ -60,6 +39,11 @@ impl<'a> UnescapedName<'a> {
Repr::TupleField(it) => SmolStr::new(it.to_string()),
}
}
+
+ pub fn display(&'a self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
+ _ = db;
+ UnescapedDisplay { name: self }
+ }
}
impl Name {
@@ -78,7 +62,7 @@ impl Name {
Self::new_text(lt.text().into())
}
- /// Shortcut to create inline plain text name
+ /// Shortcut to create inline plain text name. Panics if `text.len() > 22`
const fn new_inline(text: &str) -> Name {
Name::new_text(SmolStr::new_inline(text))
}
@@ -112,6 +96,17 @@ impl Name {
Name::new_inline("[missing name]")
}
+ /// Generates a new name which is only equal to itself, by incrementing a counter. Due
+ /// its implementation, it should not be used in things that salsa considers, like
+ /// type names or field names, and it should be only used in names of local variables
+ /// and labels and similar things.
+ pub fn generate_new_name() -> Name {
+ use std::sync::atomic::{AtomicUsize, Ordering};
+ static CNT: AtomicUsize = AtomicUsize::new(0);
+ let c = CNT.fetch_add(1, Ordering::Relaxed);
+ Name::new_text(format!("<ra@gennew>{c}").into())
+ }
+
/// Returns the tuple index this name represents if it is a tuple field.
pub fn as_tuple_index(&self) -> Option<usize> {
match self.0 {
@@ -156,6 +151,40 @@ impl Name {
Repr::TupleField(_) => false,
}
}
+
+ pub fn display<'a>(&'a self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
+ _ = db;
+ Display { name: self }
+ }
+}
+
+struct Display<'a> {
+ name: &'a Name,
+}
+
+impl<'a> fmt::Display for Display<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match &self.name.0 {
+ Repr::Text(text) => fmt::Display::fmt(&text, f),
+ Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
+ }
+ }
+}
+
+struct UnescapedDisplay<'a> {
+ name: &'a UnescapedName<'a>,
+}
+
+impl<'a> fmt::Display for UnescapedDisplay<'a> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match &self.name.0 .0 {
+ Repr::Text(text) => {
+ let text = text.strip_prefix("r#").unwrap_or(text);
+ fmt::Display::fmt(&text, f)
+ }
+ Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
+ }
+ }
}
pub trait AsName {
@@ -337,18 +366,24 @@ pub mod known {
crate_type,
derive,
global_allocator,
+ no_core,
+ no_std,
test,
test_case,
recursion_limit,
feature,
// known methods of lang items
call_once,
+ call_mut,
+ call,
eq,
ne,
ge,
gt,
le,
lt,
+ // known fields of lang items
+ pieces,
// lang items
add_assign,
add,
@@ -363,6 +398,7 @@ pub mod known {
deref,
div_assign,
div,
+ drop,
fn_mut,
fn_once,
future_trait,