Repository: rust-lang/rust-analyzer
Pull request #17604 (2024-07-16 10:10:07)

More symbol usage


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index c9542ead79..2a1e7c4d59 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -70,6 +70,7 @@ name = "base-db"
 version = "0.0.0"
 dependencies = [
  "cfg",
+ "intern",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lz4_flex",
  "rustc-hash",
@@ -970,6 +971,7 @@ dependencies = [
  "crossbeam-channel",
  "hir-expand",
  "ide-db",
+ "intern",
  "itertools",
  "paths",
  "proc-macro-api",
diff --git a/crates/base-db/Cargo.toml b/crates/base-db/Cargo.toml
index 4ab99fc33c..1b1ee034ca 100644
--- a/crates/base-db/Cargo.toml
+++ b/crates/base-db/Cargo.toml
@@ -27,6 +27,7 @@ stdx.workspace = true
 syntax.workspace = true
 vfs.workspace = true
 span.workspace = true
+intern.workspace = true
 
 [lints]
 workspace = true
diff --git a/crates/base-db/src/input.rs b/crates/base-db/src/input.rs
index 1d172ab9e4..41b7e271b0 100644
--- a/crates/base-db/src/input.rs
+++ b/crates/base-db/src/input.rs
@@ -9,10 +9,10 @@
 use std::{fmt, mem, ops};
 
 use cfg::CfgOptions;
+use intern::Symbol;
 use la_arena::{Arena, Idx, RawIdx};
 use rustc_hash::{FxHashMap, FxHashSet};
 use span::Edition;
-use syntax::SmolStr;
 use triomphe::Arc;
 use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
 
@@ -99,8 +99,8 @@ impl fmt::Debug for CrateGraph {
 
 pub type CrateId = Idx<CrateData>;
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
-pub struct CrateName(SmolStr);
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CrateName(Symbol);
 
 impl CrateName {
     /// Creates a crate name, checking for dashes in the string provided.
@@ -110,16 +110,16 @@ impl CrateName {
         if name.contains('-') {
             Err(name)
         } else {
-            Ok(Self(SmolStr::new(name)))
+            Ok(Self(Symbol::intern(name)))
         }
     }
 
     /// Creates a crate name, unconditionally replacing the dashes with underscores.
     pub fn normalize_dashes(name: &str) -> CrateName {
-        Self(SmolStr::new(name.replace('-', "_")))
+        Self(Symbol::intern(&name.replace('-', "_")))
     }
 
-    pub fn as_smol_str(&self) -> &SmolStr {
+    pub fn symbol(&self) -> &Symbol {
         &self.0
     }
 }
@@ -133,7 +133,7 @@ impl fmt::Display for CrateName {
 impl ops::Deref for CrateName {
     type Target = str;
     fn deref(&self) -> &str {
-        &self.0
+        self.0.as_str()
     }
 }
 
@@ -141,11 +141,11 @@ impl ops::Deref for CrateName {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum CrateOrigin {
     /// Crates that are from the rustc workspace.
-    Rustc { name: String },
+    Rustc { name: Symbol },
     /// Crates that are workspace members.
-    Local { repo: Option<String>, name: Option<String> },
+    Local { repo: Option<String>, name: Option<Symbol> },
     /// Crates that are non member libraries.
-    Library { repo: Option<String>, name: String },
+    Library { repo: Option<String>, name: Symbol },
     /// Crates that are provided by the language, like std, core, proc-macro, ...
     Lang(LangCrateOrigin),
 }
@@ -201,16 +201,16 @@ impl fmt::Display for LangCrateOrigin {
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateDisplayName {
     // The name we use to display various paths (with `_`).
     crate_name: CrateName,
     // The name as specified in Cargo.toml (with `-`).
-    canonical_name: String,
+    canonical_name: Symbol,
 }
 
 impl CrateDisplayName {
-    pub fn canonical_name(&self) -> &str {
+    pub fn canonical_name(&self) -> &Symbol {
         &self.canonical_name
     }
     pub fn crate_name(&self) -> &CrateName {
@@ -220,7 +220,7 @@ impl CrateDisplayName {
 
 impl From<CrateName> for CrateDisplayName {
     fn from(crate_name: CrateName) -> CrateDisplayName {
-        let canonical_name = crate_name.to_string();
+        let canonical_name = crate_name.0.clone();
         CrateDisplayName { crate_name, canonical_name }
     }
 }
@@ -239,9 +239,9 @@ impl ops::Deref for CrateDisplayName {
 }
 
 impl CrateDisplayName {
-    pub fn from_canonical_name(canonical_name: String) -> CrateDisplayName {
-        let crate_name = CrateName::normalize_dashes(&canonical_name);
-        CrateDisplayName { crate_name, canonical_name }
+    pub fn from_canonical_name(canonical_name: &str) -> CrateDisplayName {
+        let crate_name = CrateName::normalize_dashes(canonical_name);
+        CrateDisplayName { crate_name, canonical_name: Symbol::intern(canonical_name) }
     }
 }
 
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index 1a5ac96aa2..723d675347 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -1,6 +1,6 @@
 //! A higher level attributes based on TokenTree, with also some shortcuts.
 
-use std::{borrow::Cow, hash::Hash, ops, slice::Iter as SliceIter};
+use std::{borrow::Cow, hash::Hash, ops, slice};
 
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
@@ -14,7 +14,7 @@ use la_arena::{ArenaMap, Idx, RawIdx};
 use mbe::DelimiterKind;
 use syntax::{
     ast::{self, HasAttrs},
-    AstPtr, SmolStr,
+    AstPtr,
 };
 use triomphe::Arc;
 
@@ -121,12 +121,12 @@ impl Attrs {
 }
 
 impl Attrs {
-    pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
+    pub fn by_key<'attrs>(&'attrs self, key: &'attrs Symbol) -> AttrQuery<'_> {
         AttrQuery { attrs: self, key }
     }
 
     pub fn cfg(&self) -> Option<CfgExpr> {
-        let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
+        let mut cfgs = self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse);
         let first = cfgs.next()?;
         match cfgs.next() {
             Some(second) => {
@@ -138,7 +138,7 @@ impl Attrs {
     }
 
     pub fn cfgs(&self) -> impl Iterator<Item = CfgExpr> + '_ {
-        self.by_key("cfg").tt_values().map(CfgExpr::parse)
+        self.by_key(&sym::cfg).tt_values().map(CfgExpr::parse)
     }
 
     pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
@@ -148,50 +148,50 @@ impl Attrs {
         }
     }
 
-    pub fn lang(&self) -> Option<&str> {
-        self.by_key("lang").string_value()
+    pub fn lang(&self) -> Option<&Symbol> {
+        self.by_key(&sym::lang).string_value()
     }
 
     pub fn lang_item(&self) -> Option<LangItem> {
-        self.by_key("lang").string_value().and_then(|it| LangItem::from_symbol(&Symbol::intern(it)))
+        self.by_key(&sym::lang).string_value().and_then(LangItem::from_symbol)
     }
 
     pub fn has_doc_hidden(&self) -> bool {
-        self.by_key("doc").tt_values().any(|tt| {
+        self.by_key(&sym::doc).tt_values().any(|tt| {
             tt.delimiter.kind == DelimiterKind::Parenthesis &&
                 matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden)
         })
     }
 
     pub fn has_doc_notable_trait(&self) -> bool {
-        self.by_key("doc").tt_values().any(|tt| {
+        self.by_key(&sym::doc).tt_values().any(|tt| {
             tt.delimiter.kind == DelimiterKind::Parenthesis &&
                 matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait)
         })
     }
 
     pub fn doc_exprs(&self) -> impl Iterator<Item = DocExpr> + '_ {
-        self.by_key("doc").tt_values().map(DocExpr::parse)
+        self.by_key(&sym::doc).tt_values().map(DocExpr::parse)
     }
 
-    pub fn doc_aliases(&self) -> impl Iterator<Item = SmolStr> + '_ {
+    pub fn doc_aliases(&self) -> impl Iterator<Item = Symbol> + '_ {
         self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec())
     }
 
-    pub fn export_name(&self) -> Option<&str> {
-        self.by_key("export_name").string_value()
+    pub fn export_name(&self) -> Option<&Symbol> {
+        self.by_key(&sym::export_name).string_value()
     }
 
     pub fn is_proc_macro(&self) -> bool {
-        self.by_key("proc_macro").exists()
+        self.by_key(&sym::proc_macro).exists()
     }
 
     pub fn is_proc_macro_attribute(&self) -> bool {
-        self.by_key("proc_macro_attribute").exists()
+        self.by_key(&sym::proc_macro_attribute).exists()
     }
 
     pub fn is_proc_macro_derive(&self) -> bool {
-        self.by_key("proc_macro_derive").exists()
+        self.by_key(&sym::proc_macro_derive).exists()
     }
 
     pub fn is_test(&self) -> bool {
@@ -210,27 +210,27 @@ impl Attrs {
     }
 
     pub fn is_ignore(&self) -> bool {
-        self.by_key("ignore").exists()
+        self.by_key(&sym::ignore).exists()
     }
 
     pub fn is_bench(&self) -> bool {
-        self.by_key("bench").exists()
+        self.by_key(&sym::bench).exists()
     }
 
     pub fn is_unstable(&self) -> bool {
-        self.by_key("unstable").exists()
+        self.by_key(&sym::unstable).exists()
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum DocAtom {
     /// eg. `#[doc(hidden)]`
-    Flag(SmolStr),
+    Flag(Symbol),
     /// eg. `#[doc(alias = "it")]`
     ///
     /// Note that a key can have multiple values that are all considered "active" at the same time.
     /// For example, `#[doc(alias = "x")]` and `#[doc(alias = "y")]`.
-    KeyValue { key: SmolStr, value: SmolStr },
+    KeyValue { key: Symbol, value: Symbol },
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -239,7 +239,7 @@ pub enum DocExpr {
     /// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]`
     Atom(DocAtom),
     /// eg. `#[doc(alias("x", "y"))]`
-    Alias(Vec<SmolStr>),
+    Alias(Vec<Symbol>),
 }
 
 impl From<DocAtom> for DocExpr {
@@ -253,9 +253,9 @@ impl DocExpr {
         next_doc_expr(&mut tt.token_trees.iter()).unwrap_or(DocExpr::Invalid)
     }
 
-    pub fn aliases(&self) -> &[SmolStr] {
+    pub fn aliases(&self) -> &[Symbol] {
         match self {
-            DocExpr::Atom(DocAtom::KeyValue { key, value }) if key == "alias" => {
+            DocExpr::Atom(DocAtom::KeyValue { key, value }) if *key == sym::alias => {
                 std::slice::from_ref(value)
             }
             DocExpr::Alias(aliases) => aliases,
@@ -264,7 +264,7 @@ impl DocExpr {
     }
 }
 
-fn next_doc_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<DocExpr> {
+fn next_doc_expr<S>(it: &mut slice::Iter<'_, tt::TokenTree<S>>) -> Option<DocExpr> {
     let name = match it.next() {
         None => return None,
         Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(),
@@ -282,9 +282,7 @@ fn next_doc_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<DocExpr>
                 }))) => {
                     it.next();
                     it.next();
-                    // FIXME: escape? raw string?
-                    let value = SmolStr::new(text.as_str());
-                    DocAtom::KeyValue { key: name.as_str().into(), value }.into()
+                    DocAtom::KeyValue { key: name, value: text.clone() }.into()
                 }
                 _ => return Some(DocExpr::Invalid),
             }
@@ -292,12 +290,12 @@ fn next_doc_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<DocExpr>
         Some(tt::TokenTree::Subtree(subtree)) => {
             it.next();
             let subs = parse_comma_sep(subtree);
-            match name.as_str() {
-                "alias" => DocExpr::Alias(subs),
+            match &name {
+                s if *s == sym::alias => DocExpr::Alias(subs),
                 _ => DocExpr::Invalid,
             }
         }
-        _ => DocAtom::Flag(name.as_str().into()).into(),
+        _ => DocAtom::Flag(name).into(),
     };
 
     // Eat comma separator
@@ -309,16 +307,16 @@ fn next_doc_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<DocExpr>
     Some(ret)
 }
 
-fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<SmolStr> {
+fn parse_comma_sep<S>(subtree: &tt::Subtree<S>) -> Vec<Symbol> {
     subtree
         .token_trees
         .iter()
         .filter_map(|tt| match tt {
             tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
                 kind: tt::LitKind::Str,
-                symbol: text,
+                symbol,
                 ..
-            })) => Some(SmolStr::new(text.as_str())),
+            })) => Some(symbol.clone()),
             _ => None,
         })
         .collect()
@@ -565,7 +563,7 @@ impl AttrSourceMap {
 #[derive(Debug, Clone, Copy)]
 pub struct AttrQuery<'attr> {
     attrs: &'attr Attrs,
-    key: &'static str,
+    key: &'attr Symbol,
 }
 
 impl<'attr> AttrQuery<'attr> {
@@ -573,11 +571,11 @@ impl<'attr> AttrQuery<'attr> {
         self.attrs().filter_map(|attr| attr.token_tree_value())
     }
 
-    pub fn string_value(self) -> Option<&'attr str> {
+    pub fn string_value(self) -> Option<&'attr Symbol> {
         self.attrs().find_map(|attr| attr.string_value())
     }
 
-    pub fn string_value_with_span(self) -> Option<(&'attr str, span::Span)> {
+    pub fn string_value_with_span(self) -> Option<(&'attr Symbol, span::Span)> {
         self.attrs().find_map(|attr| attr.string_value_with_span())
     }
 
@@ -591,9 +589,7 @@ impl<'attr> AttrQuery<'attr> {
 
     pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
         let key = self.key;
-        self.attrs
-            .iter()
-            .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_smol_str() == key))
+        self.attrs.iter().filter(move |attr| attr.path.as_ident().map_or(false, |s| *s == *key))
     }
 
     /// Find string value for a specific key inside token tree
@@ -602,10 +598,10 @@ impl<'attr> AttrQuery<'attr> {
     /// #[doc(html_root_url = "url")]
     ///       ^^^^^^^^^^^^^ key
     /// ```
-    pub fn find_string_value_in_tt(self, key: &'attr str) -> Option<&str> {
+    pub fn find_string_value_in_tt(self, key: &'attr Symbol) -> Option<&str> {
         self.tt_values().find_map(|tt| {
             let name = tt.token_trees.iter()
-                .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if sym.as_str() == key))
+                .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { sym, ..} )) if *sym == *key))
                 .nth(2);
 
             match name {
@@ -660,6 +656,7 @@ mod tests {
     //! This module contains tests for doc-expression parsing.
     //! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`.
 
+    use intern::Symbol;
     use triomphe::Arc;
 
     use base_db::FileId;
@@ -685,24 +682,29 @@ mod tests {
 
     #[test]
     fn test_doc_expr_parser() {
-        assert_parse_result("#![doc(hidden)]", DocAtom::Flag("hidden".into()).into());
+        assert_parse_result("#![doc(hidden)]", DocAtom::Flag(Symbol::intern("hidden")).into());
 
         assert_parse_result(
             r#"#![doc(alias = "foo")]"#,
-            DocAtom::KeyValue { key: "alias".into(), value: "foo".into() }.into(),
+            DocAtom::KeyValue { key: Symbol::intern("alias"), value: Symbol::intern("foo") }.into(),
         );
 
-        assert_parse_result(r#"#![doc(alias("foo"))]"#, DocExpr::Alias(["foo".into()].into()));
+        assert_parse_result(
+            r#"#![doc(alias("foo"))]"#,
+            DocExpr::Alias([Symbol::intern("foo")].into()),
+        );
         assert_parse_result(
             r#"#![doc(alias("foo", "bar", "baz"))]"#,
-            DocExpr::Alias(["foo".into(), "bar".into(), "baz".into()].into()),
+            DocExpr::Alias(
+                [Symbol::intern("foo"), Symbol::intern("bar"), Symbol::intern("baz")].into(),
+            ),
         );
 
         assert_parse_result(
             r#"
         #[doc(alias("Bar", "Qux"))]
         struct Foo;"#,
-            DocExpr::Alias(["Bar".into(), "Qux".into()].into()),
+            DocExpr::Alias([Symbol::intern("Bar"), Symbol::intern("Qux")].into()),
         );
     }
 }
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index b96745022a..b6d43af2eb 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -8,7 +8,7 @@ use hir_expand::{
     name::{AsName, Name},
     ExpandError, InFile,
 };
-use intern::{sym, Interned};
+use intern::{sym, Interned, Symbol};
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::AstIdMap;
@@ -1623,30 +1623,29 @@ impl ExprCollector<'_> {
             }
         }
 
-        let lit_pieces =
-            fmt.template
-                .iter()
-                .enumerate()
-                .filter_map(|(i, piece)| {
-                    match piece {
-                        FormatArgsPiece::Literal(s) => Some(
-                            self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))),
-                        ),
-                        &FormatArgsPiece::Placeholder(_) => {
-                            // Inject empty string before placeholders when not already preceded by a literal piece.
-                            if i == 0
-                                || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_))
-                            {
-                                Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(
-                                    "".into(),
-                                ))))
-                            } else {
-                                None
-                            }
+        let lit_pieces = fmt
+            .template
+            .iter()
+            .enumerate()
+            .filter_map(|(i, piece)| {
+                match piece {
+                    FormatArgsPiece::Literal(s) => {
+                        Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))))
+                    }
+                    &FormatArgsPiece::Placeholder(_) => {
+                        // Inject empty string before placeholders when not already preceded by a literal piece.
+                        if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_))
+                        {
+                            Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(
+                                Symbol::empty(),
+                            ))))
+                        } else {
+                            None
                         }
                     }
-                })
-                .collect();
+                }
+            })
+            .collect();
         let lit_pieces = self.alloc_expr_desugared(Expr::Array(Array::ElementList {
             elements: lit_pieces,
             is_assignee_expr: false,
diff --git a/crates/hir-def/src/body/scope.rs b/crates/hir-def/src/body/scope.rs
index fd685235e1..3fc244a1e8 100644
--- a/crates/hir-def/src/body/scope.rs
+++ b/crates/hir-def/src/body/scope.rs
@@ -338,7 +338,7 @@ mod tests {
         let actual = scopes
             .scope_chain(scope)
             .flat_map(|scope| scopes.entries(scope))
-            .map(|it| it.name().to_smol_str())
+            .map(|it| it.name().as_str())
             .collect::<Vec<_>>()
             .join("\n");
         let expected = expected.join("\n");
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index e2bb02c0c1..a887612707 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -6,7 +6,7 @@ use base_db::CrateId;
 use hir_expand::{
     name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
 };
-use intern::{sym, Interned};
+use intern::{sym, Interned, Symbol};
 use smallvec::SmallVec;
 use syntax::{ast, Parse};
 use triomphe::Arc;
@@ -38,7 +38,7 @@ pub struct FunctionData {
     pub ret_type: Interned<TypeRef>,
     pub attrs: Attrs,
     pub visibility: RawVisibility,
-    pub abi: Option<Interned<str>>,
+    pub abi: Option<Symbol>,
     pub legacy_const_generics_indices: Box<[u32]>,
     pub rustc_allow_incoherent_impl: bool,
     flags: FnFlags,
@@ -92,12 +92,12 @@ impl FunctionData {
 
         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
         let legacy_const_generics_indices = attrs
-            .by_key("rustc_legacy_const_generics")
+            .by_key(&sym::rustc_legacy_const_generics)
             .tt_values()
             .next()
             .map(parse_rustc_legacy_const_generics)
             .unwrap_or_default();
-        let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
+        let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
 
         Arc::new(FunctionData {
             name: func.name.clone(),
@@ -200,8 +200,8 @@ impl TypeAliasData {
             ModItem::from(loc.id.value).into(),
         );
         let rustc_has_incoherent_inherent_impls =
-            attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
-        let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
+            attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
+        let rustc_allow_incoherent_impl = attrs.by_key(&sym::rustc_allow_incoherent_impl).exists();
 
         Arc::new(TypeAliasData {
             name: typ.name.clone(),
@@ -251,10 +251,10 @@ impl TraitData {
         let visibility = item_tree[tr_def.visibility].clone();
         let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
         let skip_array_during_method_dispatch =
-            attrs.by_key("rustc_skip_array_during_method_dispatch").exists();
+            attrs.by_key(&sym::rustc_skip_array_during_method_dispatch).exists();
         let rustc_has_incoherent_inherent_impls =
-            attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
-        let fundamental = attrs.by_key("fundamental").exists();
+            attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
+        let fundamental = attrs.by_key(&sym::fundamental).exists();
         let mut collector =
             AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
         collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
@@ -393,7 +393,7 @@ impl Macro2Data {
 
         let helpers = item_tree
             .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
-            .by_key("rustc_builtin_macro")
+            .by_key(&sym::rustc_builtin_macro)
             .tt_values()
             .next()
             .and_then(|attr| parse_macro_name_and_helper_attrs(&attr.token_trees))
@@ -423,7 +423,7 @@ impl MacroRulesData {
 
         let macro_export = item_tree
             .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
-            .by_key("macro_export")
+            .by_key(&sym::macro_export)
             .exists();
 
         Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
@@ -526,7 +526,7 @@ impl ConstData {
 
         let rustc_allow_incoherent_impl = item_tree
             .attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
-            .by_key("rustc_allow_incoherent_impl")
+            .by_key(&sym::rustc_allow_incoherent_impl)
             .exists();
 
         Arc::new(ConstData {
diff --git a/crates/hir-def/src/data/adt.rs b/crates/hir-def/src/data/adt.rs
index 3942c2a98a..cc6e408b65 100644
--- a/crates/hir-def/src/data/adt.rs
+++ b/crates/hir-def/src/data/adt.rs
@@ -95,7 +95,7 @@ fn repr_from_value(
     item_tree: &ItemTree,
     of: AttrOwner,
 ) -> Option<ReprOptions> {
-    item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
+    item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt)
 }
 
 fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
@@ -194,10 +194,10 @@ impl StructData {
         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
 
         let mut flags = StructFlags::NO_FLAGS;
-        if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
+        if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
             flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
         }
-        if attrs.by_key("fundamental").exists() {
+        if attrs.by_key(&sym::fundamental).exists() {
             flags |= StructFlags::IS_FUNDAMENTAL;
         }
         if let Some(lang) = attrs.lang_item() {
@@ -248,10 +248,10 @@ impl StructData {
         let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
         let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
         let mut flags = StructFlags::NO_FLAGS;
-        if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
+        if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
             flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
         }
-        if attrs.by_key("fundamental").exists() {
+        if attrs.by_key(&sym::fundamental).exists() {
             flags |= StructFlags::IS_FUNDAMENTAL;
         }
 
@@ -287,7 +287,7 @@ impl EnumData {
         let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
         let rustc_has_incoherent_inherent_impls = item_tree
             .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
-            .by_key("rustc_has_incoherent_inherent_impls")
+            .by_key(&sym::rustc_has_incoherent_inherent_impls)
             .exists();
 
         let enum_ = &item_tree[loc.id.value];
diff --git a/crates/hir-def/src/hir.rs b/crates/hir-def/src/hir.rs
index d306f9be65..d7eb80a88b 100644
--- a/crates/hir-def/src/hir.rs
+++ b/crates/hir-def/src/hir.rs
@@ -18,7 +18,7 @@ pub mod type_ref;
 use std::fmt;
 
 use hir_expand::name::Name;
-use intern::Interned;
+use intern::{Interned, Symbol};
 use la_arena::{Idx, RawIdx};
 use rustc_apfloat::ieee::{Half as f16, Quad as f128};
 use smallvec::SmallVec;
@@ -60,41 +60,41 @@ pub type LabelId = Idx<Label>;
 // We leave float values as a string to avoid double rounding.
 // For PartialEq, string comparison should work, as ordering is not important
 // https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
-#[derive(Default, Debug, Clone, Eq, PartialEq)]
-pub struct FloatTypeWrapper(Box<str>);
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct FloatTypeWrapper(Symbol);
 
 // FIXME(#17451): Use builtin types once stabilised.
 impl FloatTypeWrapper {
-    pub fn new(value: String) -> Self {
-        Self(value.into())
+    pub fn new(sym: Symbol) -> Self {
+        Self(sym)
     }
 
     pub fn to_f128(&self) -> f128 {
-        self.0.parse().unwrap_or_default()
+        self.0.as_str().parse().unwrap_or_default()
     }
 
     pub fn to_f64(&self) -> f64 {
-        self.0.parse().unwrap_or_default()
+        self.0.as_str().parse().unwrap_or_default()
     }
 
     pub fn to_f32(&self) -> f32 {
-        self.0.parse().unwrap_or_default()
+        self.0.as_str().parse().unwrap_or_default()
     }
 
     pub fn to_f16(&self) -> f16 {
-        self.0.parse().unwrap_or_default()
+        self.0.as_str().parse().unwrap_or_default()
     }
 }
 
 impl fmt::Display for FloatTypeWrapper {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_str(&self.0)
+        f.write_str(self.0.as_str())
     }
 }
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Literal {
-    String(Box<str>),
+    String(Symbol),
     ByteString(Box<[u8]>),
     CString(Box<[u8]>),
     Char(char),
@@ -130,7 +130,10 @@ impl From<ast::LiteralKind> for Literal {
         match ast_lit_kind {
             LiteralKind::IntNumber(lit) => {
                 if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) {
-                    Literal::Float(FloatTypeWrapper::new(lit.value_string()), builtin)
+                    Literal::Float(
+                        FloatTypeWrapper::new(Symbol::intern(&lit.value_string())),
+                        builtin,
+                    )
                 } else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinUint::from_suffix) {
                     Literal::Uint(lit.value().unwrap_or(0), builtin)
                 } else {
@@ -140,14 +143,14 @@ impl From<ast::LiteralKind> for Literal {
             }
             LiteralKind::FloatNumber(lit) => {
                 let ty = lit.suffix().and_then(BuiltinFloat::from_suffix);
-                Literal::Float(FloatTypeWrapper::new(lit.value_string()), ty)
+                Literal::Float(FloatTypeWrapper::new(Symbol::intern(&lit.value_string())), ty)
             }
             LiteralKind::ByteString(bs) => {
                 let text = bs.value().map_or_else(|_| Default::default(), Box::from);
                 Literal::ByteString(text)
             }
             LiteralKind::String(s) => {
-                let text = s.value().map_or_else(|_| Default::default(), Box::from);
+                let text = s.value().map_or_else(|_| Symbol::empty(), |it| Symbol::intern(&it));
                 Literal::String(text)
             }
             LiteralKind::CString(s) => {
diff --git a/crates/hir-def/src/hir/format_args.rs b/crates/hir-def/src/hir/format_args.rs
index cf176e86db..390e7da677 100644
--- a/crates/hir-def/src/hir/format_args.rs
+++ b/crates/hir-def/src/hir/format_args.rs
@@ -1,7 +1,7 @@
 //! Parses `format_args` input.
-use std::mem;
 
 use hir_expand::name::Name;
+use intern::Symbol;
 use rustc_parse_format as parse;
 use span::SyntaxContextId;
 use stdx::TupleExt;
@@ -29,7 +29,7 @@ pub struct FormatArguments {
 
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub enum FormatArgsPiece {
-    Literal(Box<str>),
+    Literal(Symbol),
     Placeholder(FormatPlaceholder),
 }
 
@@ -291,9 +291,8 @@ pub(crate) fn parse(
             parse::Piece::NextArgument(arg) => {
                 let parse::Argument { position, position_span, format } = *arg;
                 if !unfinished_literal.is_empty() {
-                    template.push(FormatArgsPiece::Literal(
-                        mem::take(&mut unfinished_literal).into_boxed_str(),
-                    ));
+                    template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
+                    unfinished_literal.clear();
                 }
 
                 let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s));
@@ -413,7 +412,7 @@ pub(crate) fn parse(
     }
 
     if !unfinished_literal.is_empty() {
-        template.push(FormatArgsPiece::Literal(unfinished_literal.into_boxed_str()));
+        template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
     }
 
     if !invalid_refs.is_empty() {
diff --git a/crates/hir-def/src/hir/type_ref.rs b/crates/hir-def/src/hir/type_ref.rs
index 7272ed98ce..9b05432258 100644
--- a/crates/hir-def/src/hir/type_ref.rs
+++ b/crates/hir-def/src/hir/type_ref.rs
@@ -9,7 +9,7 @@ use hir_expand::{
     name::{AsName, Name},
     AstId,
 };
-use intern::Interned;
+use intern::{sym, Interned, Symbol};
 use syntax::ast::{self, HasGenericArgs, HasName, IsString};
 
 use crate::{
@@ -122,9 +122,9 @@ pub enum TypeRef {
     /// A fn pointer. Last element of the vector is the return type.
     Fn(
         Vec<(Option<Name>, TypeRef)>,
-        bool,                  /*varargs*/
-        bool,                  /*is_unsafe*/
-        Option<Interned<str>>, /* abi */
+        bool,           /*varargs*/
+        bool,           /*is_unsafe*/
+        Option<Symbol>, /* abi */
     ),
     ImplTrait(Vec<Interned<TypeBound>>),
     DynTrait(Vec<Interned<TypeBound>>),
@@ -230,11 +230,11 @@ impl TypeRef {
                 } else {
                     Vec::new()
                 };
-                fn lower_abi(abi: ast::Abi) -> Interned<str> {
+                fn lower_abi(abi: ast::Abi) -> Symbol {
                     match abi.abi_string() {
-                        Some(tok) => Interned::new_str(tok.text_without_quotes()),
+                        Some(tok) => Symbol::intern(tok.text_without_quotes()),
                         // `extern` default to be `extern "C"`.
-                        _ => Interned::new_str("C"),
+                        _ => sym::C.clone(),
                     }
                 }
 
diff --git a/crates/hir-def/src/import_map.rs b/crates/hir-def/src/import_map.rs
index 2b2db21a9f..8cc022e4c6 100644
--- a/crates/hir-def/src/import_map.rs
+++ b/crates/hir-def/src/import_map.rs
@@ -9,6 +9,7 @@ use itertools::Itertools;
 use rustc_hash::FxHashSet;
 use smallvec::SmallVec;
 use stdx::{format_to, TupleExt};
+use syntax::ToSmolStr;
 use triomphe::Arc;
 
 use crate::{
@@ -81,9 +82,9 @@ impl ImportMap {
             .iter()
             // We've only collected items, whose name cannot be tuple field so unwrapping is fine.
             .flat_map(|(&item, (info, _))| {
-                info.iter()
-                    .enumerate()
-                    .map(move |(idx, info)| (item, info.name.to_smol_str(), idx as u32))
+                info.iter().enumerate().map(move |(idx, info)| {
+                    (item, info.name.display(db.upcast()).to_smolstr(), idx as u32)
+                })
             })
             .collect();
         importables.sort_by(|(_, l_info, _), (_, r_info, _)| {
@@ -412,7 +413,7 @@ pub fn search_dependencies(
             for map in &import_maps {
                 op = op.add(map.fst.search(&automaton));
             }
-            search_maps(&import_maps, op.union(), query)
+            search_maps(db, &import_maps, op.union(), query)
         }
         SearchMode::Fuzzy => {
             let automaton = fst::automaton::Subsequence::new(&query.lowercased);
@@ -420,7 +421,7 @@ pub fn search_dependencies(
             for map in &import_maps {
                 op = op.add(map.fst.search(&automaton));
             }
-            search_maps(&import_maps, op.union(), query)
+            search_maps(db, &import_maps, op.union(), query)
         }
         SearchMode::Prefix => {
             let automaton = fst::automaton::Str::new(&query.lowercased).starts_with();
@@ -428,12 +429,13 @@ pub fn search_dependencies(
             for map in &import_maps {
                 op = op.add(map.fst.search(&automaton));
             }
-            search_maps(&import_maps, op.union(), query)
+            search_maps(db, &import_maps, op.union(), query)
         }
     }
 }
 
 fn search_maps(
+    db: &dyn DefDatabase,
     import_maps: &[Arc<ImportMap>],
     mut stream: fst::map::Union<'_>,
     query: &Query,
@@ -459,7 +461,7 @@ fn search_maps(
                     query.search_mode.check(
                         &query.query,
                         query.case_sensitive,
-                        &info.name.to_smol_str(),
+                        &info.name.display(db.upcast()).to_smolstr(),
                     )
                 });
             res.extend(iter.map(TupleExt::head));
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 7650dfe9f3..479beea4a9 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -46,7 +46,7 @@ use ast::{AstNode, StructKind};
 use base_db::CrateId;
 use either::Either;
 use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
-use intern::Interned;
+use intern::{Interned, Symbol};
 use la_arena::{Arena, Idx, IdxRange, RawIdx};
 use once_cell::sync::OnceCell;
 use rustc_hash::FxHashMap;
@@ -712,7 +712,7 @@ pub struct ExternCrate {
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct ExternBlock {
-    pub abi: Option<Interned<str>>,
+    pub abi: Option<Symbol>,
     pub ast_id: FileAstId<ast::ExternBlock>,
     pub children: Box<[ModItem]>,
 }
@@ -722,7 +722,7 @@ pub struct Function {
     pub name: Name,
     pub visibility: RawVisibilityId,
     pub explicit_generic_params: Interned<GenericParams>,
-    pub abi: Option<Interned<str>>,
+    pub abi: Option<Symbol>,
     pub params: IdxRange<Param>,
     pub ret_type: Interned<TypeRef>,
     pub ast_id: FileAstId<ast::Fn>,
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index 5c80da9304..67092ae0c0 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -3,7 +3,7 @@
 use std::collections::hash_map::Entry;
 
 use hir_expand::{mod_path::path, name::AsName, span_map::SpanMapRef, HirFileId};
-use intern::sym;
+use intern::{sym, Symbol};
 use la_arena::Arena;
 use rustc_hash::FxHashMap;
 use span::{AstIdMap, SyntaxContextId};
@@ -766,11 +766,11 @@ enum HasImplicitSelf {
     No,
 }
 
-fn lower_abi(abi: ast::Abi) -> Interned<str> {
+fn lower_abi(abi: ast::Abi) -> Symbol {
     match abi.abi_string() {
-        Some(tok) => Interned::new_str(tok.text_without_quotes()),
+        Some(tok) => Symbol::intern(tok.text_without_quotes()),
         // `extern` default to be `extern "C"`.
-        _ => Interned::new_str("C"),
+        _ => sym::C.clone(),
     }
 }
 
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 07b27659ab..a09fd658ae 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -5,7 +5,6 @@
 use hir_expand::name::Name;
 use intern::{sym, Symbol};
 use rustc_hash::FxHashMap;
-use syntax::SmolStr;
 use triomphe::Arc;
 
 use crate::{
@@ -253,9 +252,9 @@ macro_rules! language_item_table {
         }
 
         impl LangItem {
-            pub fn name(self) -> SmolStr {
+            pub fn name(self) -> &'static str {
                 match self {
-                    $( LangItem::$variant => SmolStr::new(stringify!($name)), )*
+                    $( LangItem::$variant => stringify!($name), )*
                 }
             }
 
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index a614d99de6..07c408fd9e 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -82,7 +82,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
                     .iter()
                     .enumerate()
                     .map(|(idx, it)| {
-                        let name = Name::new(&it.name, tt::IdentIsRaw::No, ctx);
+                        let name = Name::new_symbol(it.name.clone(), ctx);
                         (
                             name,
                             if !db.expand_proc_attr_macros() {
@@ -296,13 +296,13 @@ impl DefCollector<'_> {
             match () {
                 () if *attr_name == sym::recursion_limit.clone() => {
                     if let Some(limit) = attr.string_value() {
-                        if let Ok(limit) = limit.parse() {
+                        if let Ok(limit) = limit.as_str().parse() {
                             crate_data.recursion_limit = Some(limit);
                         }
                     }
                 }
                 () if *attr_name == sym::crate_type.clone() => {
-                    if let Some("proc-macro") = attr.string_value() {
+                    if attr.string_value() == Some(&sym::proc_dash_macro) {
                         self.is_proc_macro = true;
                     }
                 }
@@ -1599,7 +1599,7 @@ impl ModCollector<'_, '_> {
                         id: ItemTreeId::new(self.tree_id, item_tree_id),
                     }
                     .intern(db);
-                    let is_prelude = attrs.by_key("prelude_import").exists();
+                    let is_prelude = attrs.by_key(&sym::prelude_import).exists();
                     Import::from_use(
                         self.item_tree,
                         ItemTreeId::new(self.tree_id, item_tree_id),
@@ -1624,7 +1624,7 @@ impl ModCollector<'_, '_> {
                         self.process_macro_use_extern_crate(
                             item_tree_id,
                             id,
-                            attrs.by_key("macro_use").attrs(),
+                            attrs.by_key(&sym::macro_use).attrs(),
                         );
                     }
 
@@ -1897,8 +1897,8 @@ impl ModCollector<'_, '_> {
     }
 
     fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
-        let path_attr = attrs.by_key("path").string_value_unescape();
-        let is_macro_use = attrs.by_key("macro_use").exists();
+        let path_attr = attrs.by_key(&sym::path).string_value_unescape();
+        let is_macro_use = attrs.by_key(&sym::macro_use).exists();
         let module = &self.item_tree[module_id];
         match &module.kind {
             // inline module, just recurse
@@ -1974,7 +1974,7 @@ impl ModCollector<'_, '_> {
                                 let is_macro_use = is_macro_use
                                     || item_tree
                                         .top_level_attrs(db, krate)
-                                        .by_key("macro_use")
+                                        .by_key(&sym::macro_use)
                                         .exists();
                                 if is_macro_use {
                                     self.import_all_legacy_macros(module_id);
@@ -2124,7 +2124,7 @@ impl ModCollector<'_, '_> {
         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
         let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
 
-        let export_attr = attrs.by_key("macro_export");
+        let export_attr = attrs.by_key(&sym::macro_export);
 
         let is_export = export_attr.exists();
         let local_inner = if is_export {
@@ -2137,17 +2137,17 @@ impl ModCollector<'_, '_> {
         };
 
         // Case 1: builtin macros
-        let expander = if attrs.by_key("rustc_builtin_macro").exists() {
+        let expander = if attrs.by_key(&sym::rustc_builtin_macro).exists() {
             // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
             let name;
-            let name = match attrs.by_key("rustc_builtin_macro").string_value_with_span() {
+            let name = match attrs.by_key(&sym::rustc_builtin_macro).string_value_with_span() {
                 Some((it, span)) => {
-                    name = Name::new(it, tt::IdentIsRaw::No, span.ctx);
+                    name = Name::new_symbol(it.clone(), span.ctx);
                     &name
                 }
                 None => {
                     let explicit_name =
-                        attrs.by_key("rustc_builtin_macro").tt_values().next().and_then(|tt| {
+                        attrs.by_key(&sym::rustc_builtin_macro).tt_values().next().and_then(|tt| {
                             match tt.token_trees.first() {
                                 Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
                                 _ => None,
@@ -2177,7 +2177,7 @@ impl ModCollector<'_, '_> {
             // Case 2: normal `macro_rules!` macro
             MacroExpander::Declarative
         };
-        let allow_internal_unsafe = attrs.by_key("allow_internal_unsafe").exists();
+        let allow_internal_unsafe = attrs.by_key(&sym::allow_internal_unsafe).exists();
 
         let mut flags = MacroRulesLocFlags::empty();
         flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
@@ -2207,14 +2207,14 @@ impl ModCollector<'_, '_> {
         // Case 1: builtin macros
         let mut helpers_opt = None;
         let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
-        let expander = if attrs.by_key("rustc_builtin_macro").exists() {
+        let expander = if attrs.by_key(&sym::rustc_builtin_macro).exists() {
             if let Some(expander) = find_builtin_macro(&mac.name) {
                 match expander {
                     Either::Left(it) => MacroExpander::BuiltIn(it),
                     Either::Right(it) => MacroExpander::BuiltInEager(it),
                 }
             } else if let Some(expander) = find_builtin_derive(&mac.name) {
-                if let Some(attr) = attrs.by_key("rustc_builtin_macro").tt_values().next() {
+                if let Some(attr) = attrs.by_key(&sym::rustc_builtin_macro).tt_values().next() {
                     // NOTE: The item *may* have both `#[rustc_builtin_macro]` and `#[proc_macro_derive]`,
                     // in which case rustc ignores the helper attributes from the latter, but it
                     // "doesn't make sense in practice" (see rust-lang/rust#87027).
@@ -2247,7 +2247,7 @@ impl ModCollector<'_, '_> {
             // Case 2: normal `macro`
             MacroExpander::Declarative
         };
-        let allow_internal_unsafe = attrs.by_key("allow_internal_unsafe").exists();
+        let allow_internal_unsafe = attrs.by_key(&sym::allow_internal_unsafe).exists();
 
         let macro_id = Macro2Loc {
             container: module,
diff --git a/crates/hir-def/src/nameres/mod_resolution.rs b/crates/hir-def/src/nameres/mod_resolution.rs
index 696fb6a961..6b34fe50ca 100644
--- a/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/crates/hir-def/src/nameres/mod_resolution.rs
@@ -3,6 +3,7 @@ use arrayvec::ArrayVec;
 use base_db::{AnchoredPath, FileId};
 use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
 use limit::Limit;
+use syntax::ToSmolStr as _;
 
 use crate::{db::DefDatabase, HirFileId};
 
@@ -33,7 +34,7 @@ impl ModDir {
         let path = match attr_path {
             None => {
                 let mut path = self.dir_path.clone();
-                path.push(&name.unescaped().to_smol_str());
+                path.push(&name.unescaped().display_no_db().to_smolstr());
                 path
             }
             Some(attr_path) => {
diff --git a/crates/hir-def/src/nameres/proc_macro.rs b/crates/hir-def/src/nameres/proc_macro.rs
index 4789b1f014..fd0b52bc7d 100644
--- a/crates/hir-def/src/nameres/proc_macro.rs
+++ b/crates/hir-def/src/nameres/proc_macro.rs
@@ -36,8 +36,8 @@ impl Attrs {
             Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Bang })
         } else if self.is_proc_macro_attribute() {
             Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
-        } else if self.by_key("proc_macro_derive").exists() {
-            let derive = self.by_key("proc_macro_derive").tt_values().next()?;
+        } else if self.by_key(&sym::proc_macro_derive).exists() {
+            let derive = self.by_key(&sym::proc_macro_derive).tt_values().next()?;
             let def = parse_macro_name_and_helper_attrs(&derive.token_trees)
                 .map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::Derive { helpers } });
 
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index ff5d39cf53..f90bc954a9 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -13,7 +13,7 @@ use crate::{
 };
 use hir_expand::name::Name;
 use intern::Interned;
-use syntax::ast;
+use syntax::{ast, ToSmolStr};
 
 pub use hir_expand::mod_path::{path, ModPath, PathKind};
 
@@ -29,7 +29,7 @@ impl Display for ImportAlias {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
             ImportAlias::Underscore => f.write_str("_"),
-            ImportAlias::Alias(name) => f.write_str(&name.to_smol_str()),
+            ImportAlias::Alias(name) => f.write_str(&name.display_no_db().to_smolstr()),
         }
     }
 }
diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs
index d08e063976..3ee88b536f 100644
--- a/crates/hir-def/src/pretty.rs
+++ b/crates/hir-def/src/pretty.rs
@@ -200,7 +200,7 @@ pub(crate) fn print_type_ref(
             }
             if let Some(abi) = abi {
                 buf.write_str("extern ")?;
-                buf.write_str(abi)?;
+                buf.write_str(abi.as_str())?;
                 buf.write_char(' ')?;
             }
             write!(buf, "fn(")?;
diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs
index 8ef7b7049a..777e415418 100644
--- a/crates/hir-expand/src/attrs.rs
+++ b/crates/hir-expand/src/attrs.rs
@@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt, ops};
 use base_db::CrateId;
 use cfg::CfgExpr;
 use either::Either;
-use intern::{sym, Interned};
+use intern::{sym, Interned, Symbol};
 
 use mbe::{
     desugar_doc_comment_text, syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode,
@@ -310,26 +310,26 @@ impl Attr {
 
 impl Attr {
     /// #[path = "string"]
-    pub fn string_value(&self) -> Option<&str> {
+    pub fn string_value(&self) -> Option<&Symbol> {
         match self.input.as_deref()? {
             AttrInput::Literal(tt::Literal {
                 symbol: text,
                 kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
                 ..
-            }) => Some(text.as_str()),
+            }) => Some(text),
             _ => None,
         }
     }
 
     /// #[path = "string"]
-    pub fn string_value_with_span(&self) -> Option<(&str, span::Span)> {
+    pub fn string_value_with_span(&self) -> Option<(&Symbol, span::Span)> {
         match self.input.as_deref()? {
             AttrInput::Literal(tt::Literal {
                 symbol: text,
                 kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
                 span,
                 suffix: _,
-            }) => Some((text.as_str(), *span)),
+            }) => Some((text, *span)),
             _ => None,
         }
     }
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 64c094bd28..d012d272d7 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -4,7 +4,7 @@ use std::fmt;
 
 use intern::{sym, Symbol};
 use span::SyntaxContextId;
-use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr};
+use syntax::{ast, utils::is_raw_identifier};
 
 /// `Name` is a wrapper around string, which is used in hir for both references
 /// and declarations. In theory, names should also carry hygiene info, but we are
@@ -59,21 +59,14 @@ impl PartialEq<Name> for Symbol {
 pub struct UnescapedName<'a>(&'a Name);
 
 impl UnescapedName<'_> {
-    /// 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.
-    pub fn to_smol_str(&self) -> SmolStr {
-        let it = self.0.symbol.as_str();
-        if let Some(stripped) = it.strip_prefix("r#") {
-            SmolStr::new(stripped)
-        } else {
-            it.into()
-        }
-    }
-
     pub fn display(&self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + '_ {
         _ = db;
         UnescapedDisplay { name: self }
     }
+    #[doc(hidden)]
+    pub fn display_no_db(&self) -> impl fmt::Display + '_ {
+        UnescapedDisplay { name: self }
+    }
 }
 
 impl Name {
@@ -88,7 +81,7 @@ impl Name {
         _ = ctx;
         Name {
             symbol: if raw.yes() {
-                Symbol::intern(&format_smolstr!("{}{text}", raw.as_str()))
+                Symbol::intern(&format!("{}{text}", raw.as_str()))
             } else {
                 Symbol::intern(text)
             },
@@ -118,9 +111,7 @@ impl Name {
             // Keywords (in the current edition) *can* be used as a name in earlier editions of
             // Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their
             // escaped form.
-            None if is_raw_identifier(raw_text) => {
-                Name::new_text(&format_smolstr!("r#{}", raw_text))
-            }
+            None if is_raw_identifier(raw_text) => Name::new_text(&format!("r#{}", raw_text)),
             _ => Name::new_text(raw_text),
         }
     }
@@ -151,7 +142,7 @@ impl Name {
     /// creating desugared locals and labels. The caller is responsible for picking an index
     /// that is stable across re-executions
     pub fn generate_new_name(idx: usize) -> Name {
-        Name::new_text(&format_smolstr!("<ra@gennew>{idx}"))
+        Name::new_text(&format!("<ra@gennew>{idx}"))
     }
 
     /// Returns the tuple index this name represents if it is a tuple field.
@@ -164,14 +155,6 @@ impl Name {
         self.symbol.as_str()
     }
 
-    // FIXME: Remove this
-    /// 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.
-    pub fn to_smol_str(&self) -> SmolStr {
-        self.symbol.as_str().into()
-    }
-
     pub fn unescaped(&self) -> UnescapedName<'_> {
         UnescapedName(self)
     }
@@ -185,6 +168,12 @@ impl Name {
         Display { name: self }
     }
 
+    // FIXME: Remove this
+    #[doc(hidden)]
+    pub fn display_no_db(&self) -> impl fmt::Display + '_ {
+        Display { name: self }
+    }
+
     pub fn symbol(&self) -> &Symbol {
         &self.symbol
     }
diff --git a/crates/hir-expand/src/proc_macro.rs b/crates/hir-expand/src/proc_macro.rs
index def2578b0e..39599bfe02 100644
--- a/crates/hir-expand/src/proc_macro.rs
+++ b/crates/hir-expand/src/proc_macro.rs
@@ -4,10 +4,10 @@ use core::fmt;
 use std::{panic::RefUnwindSafe, sync};
 
 use base_db::{CrateId, Env};
+use intern::Symbol;
 use rustc_hash::FxHashMap;
 use span::Span;
 use stdx::never;
-use syntax::SmolStr;
 use triomphe::Arc;
 
 use crate::{db::ExpandDatabase, tt, ExpandError, ExpandResult};
@@ -53,7 +53,7 @@ pub type ProcMacros = FxHashMap<CrateId, ProcMacroLoadResult>;
 
 #[derive(Debug, Clone)]
 pub struct ProcMacro {
-    pub name: SmolStr,
+    pub name: Symbol,
     pub kind: ProcMacroKind,
     pub expander: sync::Arc<dyn ProcMacroExpander>,
     pub disabled: bool,
diff --git a/crates/hir-ty/src/diagnostics/decl_check.rs b/crates/hir-ty/src/diagnostics/decl_check.rs
index 5175e098fe..b093440060 100644
--- a/crates/hir-ty/src/diagnostics/decl_check.rs
+++ b/crates/hir-ty/src/diagnostics/decl_check.rs
@@ -24,10 +24,11 @@ use hir_expand::{
     name::{AsName, Name},
     HirFileId, MacroFileIdExt,
 };
+use intern::sym;
 use stdx::{always, never};
 use syntax::{
     ast::{self, HasName},
-    AstNode, AstPtr,
+    AstNode, AstPtr, ToSmolStr,
 };
 
 use crate::db::HirDatabase;
@@ -163,8 +164,8 @@ impl<'a> DeclValidator<'a> {
         let is_allowed = |def_id| {
             let attrs = self.db.attrs(def_id);
             // don't bug the user about directly no_mangle annotated stuff, they can't do anything about it
-            (!recursing && attrs.by_key("no_mangle").exists())
-                || attrs.by_key("allow").tt_values().any(|tt| {
+            (!recursing && attrs.by_key(&sym::no_mangle).exists())
+                || attrs.by_key(&sym::allow).tt_values().any(|tt| {
                     let allows = tt.to_string();
                     allows.contains(allow_name)
                         || allows.contains(allow::BAD_STYLE)
@@ -325,7 +326,9 @@ impl<'a> DeclValidator<'a> {
                     let bind_name = &body.bindings[*id].name;
                     let replacement = Replacement {
                         current_name: bind_name.clone(),
-                        suggested_text: to_lower_snake_case(&bind_name.to_smol_str())?,
+                        suggested_text: to_lower_snake_case(
+                            &bind_name.display_no_db().to_smolstr(),
+                        )?,
                         expected_case: CaseType::LowerSnakeCase,
                     };
                     Some((pat_id, replacement))
@@ -405,10 +408,12 @@ impl<'a> DeclValidator<'a> {
         let mut struct_fields_replacements = fields
             .iter()
             .filter_map(|(_, field)| {
-                to_lower_snake_case(&field.name.to_smol_str()).map(|new_name| Replacement {
-                    current_name: field.name.clone(),
-                    suggested_text: new_name,
-                    expected_case: CaseType::LowerSnakeCase,
+                to_lower_snake_case(&field.name.display_no_db().to_smolstr()).map(|new_name| {
+                    Replacement {
+                        current_name: field.name.clone(),
+                        suggested_text: new_name,
+                        expected_case: CaseType::LowerSnakeCase,
+                    }
                 })
             })
             .peekable();
@@ -497,7 +502,7 @@ impl<'a> DeclValidator<'a> {
             .variants
             .iter()
             .filter_map(|(_, name)| {
-                to_camel_case(&name.to_smol_str()).map(|new_name| Replacement {
+                to_camel_case(&name.display_no_db().to_smolstr()).map(|new_name| Replacement {
                     current_name: name.clone(),
                     suggested_text: new_name,
                     expected_case: CaseType::UpperCamelCase,
@@ -564,10 +569,12 @@ impl<'a> DeclValidator<'a> {
         let mut variant_field_replacements = fields
             .iter()
             .filter_map(|(_, field)| {
-                to_lower_snake_case(&field.name.to_smol_str()).map(|new_name| Replacement {
-                    current_name: field.name.clone(),
-                    suggested_text: new_name,
-                    expected_case: CaseType::LowerSnakeCase,
+                to_lower_snake_case(&field.name.display_no_db().to_smolstr()).map(|new_name| {
+                    Replacement {
+                        current_name: field.name.clone(),
+                        suggested_text: new_name,
+                        expected_case: CaseType::LowerSnakeCase,
+                    }
                 })
             })
             .peekable();
@@ -704,9 +711,11 @@ impl<'a> DeclValidator<'a> {
             CaseType::UpperSnakeCase => to_upper_snake_case,
             CaseType::UpperCamelCase => to_camel_case,
         };
-        let Some(replacement) = to_expected_case_type(&name.to_smol_str()).map(|new_name| {
-            Replacement { current_name: name.clone(), suggested_text: new_name, expected_case }
-        }) else {
+        let Some(replacement) =
+            to_expected_case_type(&name.display(self.db.upcast()).to_smolstr()).map(|new_name| {
+                Replacement { current_name: name.clone(), suggested_text: new_name, expected_case }
+            })
+        else {
             return;
         };
 
diff --git a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index 1374d0c38b..ff62344012 100644
--- a/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -101,7 +101,7 @@ impl<'db> MatchCheckCtx<'db> {
     /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
     fn is_foreign_non_exhaustive(&self, adt: hir_def::AdtId) -> bool {
         let is_local = adt.krate(self.db.upcast()) == self.module.krate();
-        !is_local && self.db.attrs(adt.into()).by_key("non_exhaustive").exists()
+        !is_local && self.db.attrs(adt.into()).by_key(&sym::non_exhaustive).exists()
     }
 
     fn variant_id_for_adt(
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index f15f6575b7..a433ecfd77 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -1935,7 +1935,7 @@ impl HirDisplay for TypeRef {
                 }
                 if let Some(abi) = abi {
                     f.write_str("extern \"")?;
-                    f.write_str(abi)?;
+                    f.write_str(abi.as_str())?;
                     f.write_str("\" ")?;
                 }
                 write!(f, "fn(")?;
@@ -2044,7 +2044,7 @@ impl HirDisplay for Path {
                     .display_name
                     .as_ref()
                     .map(|name| name.canonical_name())
-                    .unwrap_or("$crate");
+                    .unwrap_or(&sym::dollar_crate);
                 write!(f, "{name}")?
             }
         }
diff --git a/crates/hir-ty/src/inhabitedness.rs b/crates/hir-ty/src/inhabitedness.rs
index f5fb2ffd78..c0a781b17e 100644
--- a/crates/hir-ty/src/inhabitedness.rs
+++ b/crates/hir-ty/src/inhabitedness.rs
@@ -6,6 +6,7 @@ use chalk_ir::{
     DebruijnIndex,
 };
 use hir_def::{visibility::Visibility, AdtId, EnumVariantId, HasModule, ModuleId, VariantId};
+use intern::sym;
 use rustc_hash::FxHashSet;
 
 use crate::{
@@ -118,7 +119,7 @@ impl UninhabitedFrom<'_> {
         subst: &Substitution,
     ) -> ControlFlow<VisiblyUninhabited> {
         let is_local = variant.krate(self.db.upcast()) == self.target_mod.krate();
-        if !is_local && self.db.attrs(variant.into()).by_key("non_exhaustive").exists() {
+        if !is_local && self.db.attrs(variant.into()).by_key(&sym::non_exhaustive).exists() {
             return CONTINUE_OPAQUELY_INHABITED;
         }
 
diff --git a/crates/hir-ty/src/layout/adt.rs b/crates/hir-ty/src/layout/adt.rs
index 4cc7dffc24..3463e69097 100644
--- a/crates/hir-ty/src/layout/adt.rs
+++ b/crates/hir-ty/src/layout/adt.rs
@@ -8,6 +8,7 @@ use hir_def::{
     layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
     AdtId, VariantId,
 };
+use intern::sym;
 use rustc_index::IndexVec;
 use smallvec::SmallVec;
 use triomphe::Arc;
@@ -129,7 +130,10 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound<u128>,
         }
         Bound::Unbounded
     };
-    (get("rustc_layout_scalar_valid_range_start"), get("rustc_layout_scalar_valid_range_end"))
+    (
+        get(&sym::rustc_layout_scalar_valid_range_start),
+        get(&sym::rustc_layout_scalar_valid_range_end),
+    )
 }
 
 pub fn layout_of_adt_recover(
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index aabf11f268..2f93ce3181 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -62,7 +62,7 @@ use chalk_ir::{
 use either::Either;
 use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
 use hir_expand::name::Name;
-use intern::sym;
+use intern::{sym, Symbol};
 use la_arena::{Arena, Idx};
 use mir::{MirEvalError, VTableMap};
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -423,45 +423,45 @@ impl Hash for FnAbi {
 }
 
 impl FnAbi {
-    #[allow(clippy::should_implement_trait)]
-    pub fn from_str(s: &str) -> FnAbi {
+    #[rustfmt::skip]
+    pub fn from_symbol(s: &Symbol) -> FnAbi {
         match s {
-            "aapcs-unwind" => FnAbi::AapcsUnwind,
-            "aapcs" => FnAbi::Aapcs,
-            "avr-interrupt" => FnAbi::AvrInterrupt,
-            "avr-non-blocking-interrupt" => FnAbi::AvrNonBlockingInterrupt,
-            "C-cmse-nonsecure-call" => FnAbi::CCmseNonsecureCall,
-            "C-unwind" => FnAbi::CUnwind,
-            "C" => FnAbi::C,
-            "cdecl-unwind" => FnAbi::CDeclUnwind,
-            "cdecl" => FnAbi::CDecl,
-            "efiapi" => FnAbi::Efiapi,
-            "fastcall-unwind" => FnAbi::FastcallUnwind,
-            "fastcall" => FnAbi::Fastcall,
-            "msp430-interrupt" => FnAbi::Msp430Interrupt,
-            "platform-intrinsic" => FnAbi::PlatformIntrinsic,
-            "ptx-kernel" => FnAbi::PtxKernel,
-            "riscv-interrupt-m" => FnAbi::RiscvInterruptM,
-            "riscv-interrupt-s" => FnAbi::RiscvInterruptS,
-            "rust-call" => FnAbi::RustCall,
-            "rust-cold" => FnAbi::RustCold,
-            "rust-intrinsic" => FnAbi::RustIntrinsic,
-            "Rust" => FnAbi::Rust,
-            "stdcall-unwind" => FnAbi::StdcallUnwind,
-            "stdcall" => FnAbi::Stdcall,
-            "system-unwind" => FnAbi::SystemUnwind,
-            "system" => FnAbi::System,
-            "sysv64-unwind" => FnAbi::Sysv64Unwind,
-            "sysv64" => FnAbi::Sysv64,
-            "thiscall-unwind" => FnAbi::ThiscallUnwind,
-            "thiscall" => FnAbi::Thiscall,
-            "unadjusted" => FnAbi::Unadjusted,
-            "vectorcall-unwind" => FnAbi::VectorcallUnwind,
-            "vectorcall" => FnAbi::Vectorcall,
-            "wasm" => FnAbi::Wasm,
-            "win64-unwind" => FnAbi::Win64Unwind,
-            "win64" => FnAbi::Win64,
-            "x86-interrupt" => FnAbi::X86Interrupt,
+            s if *s == sym::aapcs_dash_unwind => FnAbi::AapcsUnwind,
+            s if *s == sym::aapcs => FnAbi::Aapcs,
+            s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
+            s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
+            s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
+            s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
+            s if *s == sym::C => FnAbi::C,
+            s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
+            s if *s == sym::cdecl => FnAbi::CDecl,
+            s if *s == sym::efiapi => FnAbi::Efiapi,
+            s if *s == sym::fastcall_dash_unwind => FnAbi::FastcallUnwind,
+            s if *s == sym::fastcall => FnAbi::Fastcall,
+            s if *s == sym::msp430_dash_interrupt => FnAbi::Msp430Interrupt,
+            s if *s == sym::platform_dash_intrinsic => FnAbi::PlatformIntrinsic,
+            s if *s == sym::ptx_dash_kernel => FnAbi::PtxKernel,
+            s if *s == sym::riscv_dash_interrupt_dash_m => FnAbi::RiscvInterruptM,
+            s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS,
+            s if *s == sym::rust_dash_call => FnAbi::RustCall,
+            s if *s == sym::rust_dash_cold => FnAbi::RustCold,
+            s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic,
+            s if *s == sym::Rust => FnAbi::Rust,
+            s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind,
+            s if *s == sym::stdcall => FnAbi::Stdcall,
+            s if *s == sym::system_dash_unwind => FnAbi::SystemUnwind,
+            s if *s == sym::system => FnAbi::System,
+            s if *s == sym::sysv64_dash_unwind => FnAbi::Sysv64Unwind,
+            s if *s == sym::sysv64 => FnAbi::Sysv64,
+            s if *s == sym::thiscall_dash_unwind => FnAbi::ThiscallUnwind,
+            s if *s == sym::thiscall => FnAbi::Thiscall,
+            s if *s == sym::unadjusted => FnAbi::Unadjusted,
+            s if *s == sym::vectorcall_dash_unwind => FnAbi::VectorcallUnwind,
+            s if *s == sym::vectorcall => FnAbi::Vectorcall,
+            s if *s == sym::wasm => FnAbi::Wasm,
+            s if *s == sym::win64_dash_unwind => FnAbi::Win64Unwind,
+            s if *s == sym::win64 => FnAbi::Win64,
+            s if *s == sym::x86_dash_interrupt => FnAbi::X86Interrupt,
             _ => FnAbi::Unknown,
         }
     }
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index d421e72d36..444628ff52 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -298,7 +298,7 @@ impl<'a> TyLoweringContext<'a> {
                 TyKind::Function(FnPointer {
                     num_binders: 0, // FIXME lower `for<'a> fn()` correctly
                     sig: FnSig {
-                        abi: abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
+                        abi: abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
                         safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
                         variadic,
                     },
@@ -1858,7 +1858,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
         ret,
         data.is_varargs(),
         if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe },
-        data.abi.as_deref().map_or(FnAbi::Rust, FnAbi::from_str),
+        data.abi.as_ref().map_or(FnAbi::Rust, FnAbi::from_symbol),
     );
     make_binders(db, &generics, sig)
 }
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index fad74c2448..d3ddc883a8 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -13,6 +13,7 @@ use hir_def::{
     ModuleId, TraitId,
 };
 use hir_expand::name::Name;
+use intern::sym;
 use rustc_hash::{FxHashMap, FxHashSet};
 use smallvec::{smallvec, SmallVec};
 use span::Edition;
@@ -200,7 +201,7 @@ impl TraitImpls {
                 // FIXME: Reservation impls should be considered during coherence checks. If we are
                 // (ever) to implement coherence checks, this filtering should be done by the trait
                 // solver.
-                if db.attrs(impl_id.into()).by_key("rustc_reservation_impl").exists() {
+                if db.attrs(impl_id.into()).by_key(&sym::rustc_reservation_impl).exists() {
                     continue;
                 }
                 let target_trait = match db.impl_trait(impl_id) {
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 32b7d6dc11..8c146aae97 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -15,7 +15,7 @@ use hir_def::{
     StaticId, VariantId,
 };
 use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile};
-use intern::{sym, Interned};
+use intern::sym;
 use la_arena::ArenaMap;
 use rustc_abi::TargetDataLayout;
 use rustc_apfloat::{
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 6818759310..bd43a62341 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -15,9 +15,9 @@ use crate::{
     error_lifetime,
     mir::eval::{
         pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
-        Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned,
-        ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability,
-        Result, Substitution, Ty, TyBuilder, TyExt,
+        InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId,
+        LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution,
+        Ty, TyBuilder, TyExt,
     },
 };
 
@@ -54,12 +54,12 @@ impl Evaluator<'_> {
 
         let function_data = self.db.function_data(def);
         let is_intrinsic = match &function_data.abi {
-            Some(abi) => *abi == Interned::new_str("rust-intrinsic"),
+            Some(abi) => *abi == sym::rust_dash_intrinsic,
             None => match def.lookup(self.db.upcast()).container {
                 hir_def::ItemContainerId::ExternBlockId(block) => {
                     let id = block.lookup(self.db.upcast()).id;
-                    id.item_tree(self.db.upcast())[id.value].abi.as_deref()
-                        == Some("rust-intrinsic")
+                    id.item_tree(self.db.upcast())[id.value].abi.as_ref()
+                        == Some(&sym::rust_dash_intrinsic)
                 }
                 _ => false,
             },
@@ -76,12 +76,12 @@ impl Evaluator<'_> {
             return Ok(true);
         }
         let is_platform_intrinsic = match &function_data.abi {
-            Some(abi) => *abi == Interned::new_str("platform-intrinsic"),
+            Some(abi) => *abi == sym::platform_dash_intrinsic,
             None => match def.lookup(self.db.upcast()).container {
                 hir_def::ItemContainerId::ExternBlockId(block) => {
                     let id = block.lookup(self.db.upcast()).id;
-                    id.item_tree(self.db.upcast())[id.value].abi.as_deref()
-                        == Some("platform-intrinsic")
+                    id.item_tree(self.db.upcast())[id.value].abi.as_ref()
+                        == Some(&sym::platform_dash_intrinsic)
                 }
                 _ => false,
             },
@@ -100,7 +100,7 @@ impl Evaluator<'_> {
         let is_extern_c = match def.lookup(self.db.upcast()).container {
             hir_def::ItemContainerId::ExternBlockId(block) => {
                 let id = block.lookup(self.db.upcast()).id;
-                id.item_tree(self.db.upcast())[id.value].abi.as_deref() == Some("C")
+                id.item_tree(self.db.upcast())[id.value].abi.as_ref() == Some(&sym::C)
             }
             _ => false,
         };
@@ -314,7 +314,7 @@ impl Evaluator<'_> {
         use LangItem::*;
         let attrs = self.db.attrs(def.into());
 
-        if attrs.by_key("rustc_const_panic_str").exists() {
+        if attrs.by_key(&sym::rustc_const_panic_str).exists() {
             // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
             return Some(LangItem::BeginPanic);
         }
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 1b8c772d80..1f3c85f0fd 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -1406,6 +1406,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         const USIZE_SIZE: usize = mem::size_of::<usize>();
         let bytes: Box<[_]> = match l {
             hir_def::hir::Literal::String(b) => {
+                let b = b.as_str();
                 let mut data = [0; { 2 * USIZE_SIZE }];
                 data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes());
                 data[USIZE_SIZE..].copy_from_slice(&b.len().to_le_bytes());
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 738e842146..fbec332885 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -18,6 +18,7 @@ use hir_def::{
     TypeOrConstParamId,
 };
 use hir_expand::name::Name;
+use intern::sym;
 use rustc_abi::TargetDataLayout;
 use rustc_hash::FxHashSet;
 use smallvec::{smallvec, SmallVec};
@@ -254,7 +255,7 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
     let data = db.function_data(func);
     if data.has_unsafe_kw() {
         // Functions that are `#[rustc_deprecated_safe_2024]` are safe to call before 2024.
-        if db.attrs(func.into()).by_key("rustc_deprecated_safe_2024").exists() {
+        if db.attrs(func.into()).by_key(&sym::rustc_deprecated_safe_2024).exists() {
             // FIXME: Properly check the caller span and mark it as unsafe after 2024.
             return false;
         }
@@ -268,11 +269,11 @@ pub fn is_fn_unsafe_to_call(db: &dyn HirDatabase, func: FunctionId) -> bool {
             let id = block.lookup(db.upcast()).id;
 
             let is_intrinsic =
-                id.item_tree(db.upcast())[id.value].abi.as_deref() == Some("rust-intrinsic");
+                id.item_tree(db.upcast())[id.value].abi.as_ref() == Some(&sym::rust_dash_intrinsic);
 
             if is_intrinsic {
                 // Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute
-                !data.attrs.by_key("rustc_safe_intrinsic").exists()
+                !data.attrs.by_key(&sym::rustc_safe_intrinsic).exists()
             } else {
                 // Extern items are always unsafe
                 true
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 72e79af75d..a0dbead221 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -82,8 +82,7 @@ impl HirDisplay for Function {
             f.write_str("unsafe ")?;
         }
         if let Some(abi) = &data.abi {
-            // FIXME: String escape?
-            write!(f, "extern \"{}\" ", &**abi)?;
+            write!(f, "extern \"{}\" ", abi.as_str())?;
         }
         write!(f, "fn {}", data.name.display(f.db.upcast()))?;
 
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9f33c50670..dece4edb88 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -82,7 +82,7 @@ use span::{Edition, MacroCallId};
 use stdx::{impl_from, never};
 use syntax::{
     ast::{self, HasAttrs as _, HasName},
-    format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, T,
+    format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
 };
 use triomphe::Arc;
 
@@ -259,7 +259,7 @@ impl Crate {
     pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
         // Look for #![doc(html_root_url = "...")]
         let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
-        let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
+        let doc_url = attrs.by_key(&sym::doc).find_string_value_in_tt(&sym::html_root_url);
         doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
     }
 
@@ -677,9 +677,9 @@ impl Module {
                             TypeOrConstParamId { parent, local_id },
                         ))
                     });
-                let res = type_params
-                    .chain(lifetime_params)
-                    .any(|p| db.attrs(AttrDefId::GenericParamId(p)).by_key("may_dangle").exists());
+                let res = type_params.chain(lifetime_params).any(|p| {
+                    db.attrs(AttrDefId::GenericParamId(p)).by_key(&sym::may_dangle).exists()
+                });
                 Some(res)
             })()
             .unwrap_or(false);
@@ -2088,14 +2088,14 @@ impl Function {
     /// is this a `fn main` or a function with an `export_name` of `main`?
     pub fn is_main(self, db: &dyn HirDatabase) -> bool {
         let data = db.function_data(self.id);
-        data.attrs.export_name() == Some("main")
-            || self.module(db).is_crate_root() && data.name.to_smol_str() == "main"
+        data.attrs.export_name() == Some(&sym::main)
+            || self.module(db).is_crate_root() && data.name == sym::main
     }
 
     /// Is this a function with an `export_name` of `main`?
     pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
         let data = db.function_data(self.id);
-        data.attrs.export_name() == Some("main")
+        data.attrs.export_name() == Some(&sym::main)
     }
 
     /// Does this function have the ignore attribute?
@@ -4607,7 +4607,7 @@ impl Type {
     ) -> impl Iterator<Item = SmolStr> + 'a {
         // iterate the lifetime
         self.as_adt()
-            .and_then(|a| a.lifetime(db).map(|lt| lt.name.to_smol_str()))
+            .and_then(|a| a.lifetime(db).map(|lt| lt.name.display_no_db().to_smolstr()))
             .into_iter()
             // add the type and const parameters
             .chain(self.type_and_const_arguments(db))
diff --git a/crates/hir/src/symbols.rs b/crates/hir/src/symbols.rs
index a6e69d7992..cdfeae1b28 100644
--- a/crates/hir/src/symbols.rs
+++ b/crates/hir/src/symbols.rs
@@ -10,7 +10,7 @@ use hir_def::{
 };
 use hir_expand::{HirFileId, InFile};
 use hir_ty::{db::HirDatabase, display::HirDisplay};
-use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr};
+use syntax::{ast::HasName, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, ToSmolStr};
 
 use crate::{Module, ModuleDef, Semantics};
 
@@ -258,10 +258,18 @@ impl<'a> SymbolCollector<'a> {
 
     fn def_with_body_id_name(&self, body_id: DefWithBodyId) -> Option<SmolStr> {
         match body_id {
-            DefWithBodyId::FunctionId(id) => Some(self.db.function_data(id).name.to_smol_str()),
-            DefWithBodyId::StaticId(id) => Some(self.db.static_data(id).name.to_smol_str()),
-            DefWithBodyId::ConstId(id) => Some(self.db.const_data(id).name.as_ref()?.to_smol_str()),
-            DefWithBodyId::VariantId(id) => Some(self.db.enum_variant_data(id).name.to_smol_str()),
+            DefWithBodyId::FunctionId(id) => {
+                Some(self.db.function_data(id).name.display_no_db().to_smolstr())
+            }
+            DefWithBodyId::StaticId(id) => {
+                Some(self.db.static_data(id).name.display_no_db().to_smolstr())
+            }
+            DefWithBodyId::ConstId(id) => {
+                Some(self.db.const_data(id).name.as_ref()?.display_no_db().to_smolstr())
+            }
+            DefWithBodyId::VariantId(id) => {
+                Some(self.db.enum_variant_data(id).name.display_no_db().to_smolstr())
+            }
             DefWithBodyId::InTypeConstId(_) => Some("in type const".into()),
         }
     }
@@ -293,7 +301,7 @@ impl<'a> SymbolCollector<'a> {
         if let Some(attrs) = def.attrs(self.db) {
             for alias in attrs.doc_aliases() {
                 self.symbols.push(FileSymbol {
-                    name: alias,
+                    name: alias.as_str().into(),
                     def,
                     loc: dec_loc.clone(),
                     container_name: self.current_container_name.clone(),
@@ -330,7 +338,7 @@ impl<'a> SymbolCollector<'a> {
         if let Some(attrs) = def.attrs(self.db) {
             for alias in attrs.doc_aliases() {
                 self.symbols.push(FileSymbol {
-                    name: alias,
+                    name: alias.as_str().into(),
                     def,
                     loc: dec_loc.clone(),
                     container_name: self.current_container_name.clone(),
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
index 4eb29a2378..e1bf6b27bc 100644
--- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs
+++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs
@@ -1,7 +1,7 @@
 use std::iter::{self, Peekable};
 
 use either::Either;
-use hir::{Adt, Crate, HasAttrs, HasSource, ImportPathConfig, ModuleDef, Semantics};
+use hir::{sym, Adt, Crate, HasAttrs, HasSource, ImportPathConfig, ModuleDef, Semantics};
 use ide_db::RootDatabase;
 use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
 use itertools::Itertools;
@@ -381,7 +381,7 @@ impl ExtendedEnum {
     fn is_non_exhaustive(self, db: &RootDatabase, krate: Crate) -> bool {
         match self {
             ExtendedEnum::Enum(e) => {
-                e.attrs(db).by_key("non_exhaustive").exists() && e.module(db).krate() != krate
+                e.attrs(db).by_key(&sym::non_exhaustive).exists() && e.module(db).krate() != krate
             }
             _ => false,
         }
diff --git a/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 62bb6dff21..da902f7e10 100644
--- a/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -1,4 +1,4 @@
-use hir::{HasVisibility, ImportPathConfig};
+use hir::{sym, HasVisibility, ImportPathConfig};
 use ide_db::{
     assists::{AssistId, AssistKind},
     defs::Definition,
@@ -7,7 +7,7 @@ use ide_db::{
     FxHashMap, FxHashSet,
 };
 use itertools::Itertools;
-use syntax::{ast, ted, AstNode, SmolStr, SyntaxNode};
+use syntax::{ast, ted, AstNode, SmolStr, SyntaxNode, ToSmolStr};
 use text_edit::TextRange;
 
 use crate::{
@@ -98,7 +98,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
     let kind = struct_type.kind(ctx.db());
     let struct_def_path = module.find_path(ctx.db(), struct_def, cfg)?;
 
-    let is_non_exhaustive = struct_def.attrs(ctx.db())?.by_key("non_exhaustive").exists();
+    let is_non_exhaustive = struct_def.attrs(ctx.db())?.by_key(&sym::non_exhaustive).exists();
     let is_foreign_crate =
         struct_def.module(ctx.db()).map_or(false, |m| m.krate() != module.krate());
 
@@ -251,7 +251,7 @@ fn generate_field_names(ctx: &AssistContext<'_>, data: &StructEditData) -> Vec<(
             .visible_fields
             .iter()
             .map(|field| {
-                let field_name = field.name(ctx.db()).to_smol_str();
+                let field_name = field.name(ctx.db()).display_no_db().to_smolstr();
                 let new_name = new_field_name(field_name.clone(), &data.names_in_scope);
                 (field_name, new_name)
             })
diff --git a/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs b/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
index 2887e0c3e5..758f50d3f4 100644
--- a/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
+++ b/crates/ide-assists/src/handlers/fill_record_pattern_fields.rs
@@ -1,6 +1,6 @@
 use syntax::{
     ast::{self, make},
-    AstNode,
+    AstNode, ToSmolStr,
 };
 
 use crate::{AssistContext, AssistId, Assists};
@@ -45,8 +45,9 @@ pub(crate) fn fill_record_pattern_fields(acc: &mut Assists, ctx: &AssistContext<
     let new_field_list =
         make::record_pat_field_list(old_field_list.fields(), None).clone_for_update();
     for (f, _) in missing_fields.iter() {
-        let field =
-            make::record_pat_field_shorthand(make::name_ref(&f.name(ctx.sema.db).to_smol_str()));
+        let field = make::record_pat_field_shorthand(make::name_ref(
+            &f.name(ctx.sema.db).display_no_db().to_smolstr(),
+        ));
         new_field_list.add_field(field.clone_for_update());
     }
 
diff --git a/crates/ide-assists/src/handlers/fix_visibility.rs b/crates/ide-assists/src/handlers/fix_visibility.rs
index 589591a677..759750a550 100644
--- a/crates/ide-assists/src/handlers/fix_visibility.rs
+++ b/crates/ide-assists/src/handlers/fix_visibility.rs
@@ -4,7 +4,7 @@ use hir::{
 use ide_db::base_db::FileId;
 use syntax::{
     ast::{self, edit_in_place::HasVisibilityEdit, make, HasVisibility as _},
-    AstNode, TextRange,
+    AstNode, TextRange, ToSmolStr,
 };
 
 use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -48,7 +48,7 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
     let (_, def) = module
         .scope(ctx.db(), None)
         .into_iter()
-        .find(|(name, _)| name.to_smol_str() == name_ref.text().as_str())?;
+        .find(|(name, _)| name.display_no_db().to_smolstr() == name_ref.text().as_str())?;
     let ScopeDef::ModuleDef(def) = def else {
         return None;
     };
diff --git a/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
index 78def51a4a..5a3457e5b7 100644
--- a/crates/ide-assists/src/handlers/generate_delegate_trait.rs
+++ b/crates/ide-assists/src/handlers/generate_delegate_trait.rs
@@ -22,7 +22,7 @@ use syntax::{
         WherePred,
     },
     ted::{self, Position},
-    AstNode, NodeOrToken, SmolStr, SyntaxKind,
+    AstNode, NodeOrToken, SmolStr, SyntaxKind, ToSmolStr,
 };
 
 // Assist: generate_delegate_trait
@@ -170,11 +170,11 @@ impl Delegee {
 
         for m in it.module(db).path_to_root(db).iter().rev() {
             if let Some(name) = m.name(db) {
-                s.push_str(&format!("{}::", name.to_smol_str()));
+                s.push_str(&format!("{}::", name.display_no_db().to_smolstr()));
             }
         }
 
-        s.push_str(&it.name(db).to_smol_str());
+        s.push_str(&it.name(db).display_no_db().to_smolstr());
         s
     }
 }
@@ -259,7 +259,7 @@ fn generate_impl(
                 strukt_params.clone(),
                 strukt_params.map(|params| params.to_generic_args()),
                 delegee.is_auto(db),
-                make::ty(&delegee.name(db).to_smol_str()),
+                make::ty(&delegee.name(db).display_no_db().to_smolstr()),
                 strukt_ty,
                 bound_def.where_clause(),
                 ast_strukt.where_clause(),
@@ -349,7 +349,8 @@ fn generate_impl(
 
             let type_gen_args = strukt_params.clone().map(|params| params.to_generic_args());
 
-            let path_type = make::ty(&trait_.name(db).to_smol_str()).clone_for_update();
+            let path_type =
+                make::ty(&trait_.name(db).display_no_db().to_smolstr()).clone_for_update();
             transform_impl(ctx, ast_strukt, &old_impl, &transform_args, path_type.syntax())?;
 
             // 3) Generate delegate trait impl
diff --git a/crates/ide-assists/src/handlers/move_module_to_file.rs b/crates/ide-assists/src/handlers/move_module_to_file.rs
index 9af8411f4c..802dca9fad 100644
--- a/crates/ide-assists/src/handlers/move_module_to_file.rs
+++ b/crates/ide-assists/src/handlers/move_module_to_file.rs
@@ -1,7 +1,7 @@
 use std::iter;
 
 use ast::edit::IndentLevel;
-use hir::HasAttrs;
+use hir::{sym, HasAttrs};
 use ide_db::base_db::AnchoredPathBuf;
 use itertools::Itertools;
 use stdx::format_to;
@@ -57,7 +57,7 @@ pub(crate) fn move_module_to_file(acc: &mut Assists, ctx: &AssistContext<'_>) ->
                         if !parent_module.is_mod_rs(db)
                             && parent_module
                                 .attrs(db)
-                                .by_key("path")
+                                .by_key(&sym::path)
                                 .string_value_unescape()
                                 .is_none() =>
                     {
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index ee27d8611e..414b096ad4 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -26,7 +26,7 @@ use std::iter;
 
 use hir::{sym, HasAttrs, ImportPathConfig, Name, ScopeDef, Variant};
 use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind};
-use syntax::{ast, SmolStr};
+use syntax::{ast, SmolStr, ToSmolStr};
 
 use crate::{
     context::{
@@ -541,13 +541,21 @@ impl Completions {
     }
 
     pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
-        CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), name.to_smol_str())
-            .add_to(self, ctx.db)
+        CompletionItem::new(
+            SymbolKind::LifetimeParam,
+            ctx.source_range(),
+            name.display_no_db().to_smolstr(),
+        )
+        .add_to(self, ctx.db)
     }
 
     pub(crate) fn add_label(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
-        CompletionItem::new(SymbolKind::Label, ctx.source_range(), name.to_smol_str())
-            .add_to(self, ctx.db)
+        CompletionItem::new(
+            SymbolKind::Label,
+            ctx.source_range(),
+            name.display_no_db().to_smolstr(),
+        )
+        .add_to(self, ctx.db)
     }
 
     pub(crate) fn add_variant_pat(
diff --git a/crates/ide-completion/src/completions/attribute/derive.rs b/crates/ide-completion/src/completions/attribute/derive.rs
index 90dac1902a..0127a42824 100644
--- a/crates/ide-completion/src/completions/attribute/derive.rs
+++ b/crates/ide-completion/src/completions/attribute/derive.rs
@@ -2,7 +2,7 @@
 use hir::ScopeDef;
 use ide_db::{documentation::HasDocs, SymbolKind};
 use itertools::Itertools;
-use syntax::SmolStr;
+use syntax::{SmolStr, ToSmolStr};
 
 use crate::{
     context::{CompletionContext, ExistingDerives, PathCompletionCtx, Qualified},
@@ -62,7 +62,7 @@ pub(crate) fn complete_derive_path(
                     _ => return acc.add_macro(ctx, path_ctx, mac, name),
                 };
 
-                let name_ = name.to_smol_str();
+                let name_ = name.display_no_db().to_smolstr();
                 let find = DEFAULT_DERIVE_DEPENDENCIES
                     .iter()
                     .find(|derive_completion| derive_completion.label == name_);
@@ -75,7 +75,7 @@ pub(crate) fn complete_derive_path(
                                 !existing_derives
                                     .iter()
                                     .map(|it| it.name(ctx.db))
-                                    .any(|it| it.to_smol_str() == dependency)
+                                    .any(|it| it.display_no_db().to_smolstr() == dependency)
                             },
                         ));
                         let lookup = components.join(", ");
diff --git a/crates/ide-completion/src/completions/extern_crate.rs b/crates/ide-completion/src/completions/extern_crate.rs
index b67d82c20d..2427f4e49f 100644
--- a/crates/ide-completion/src/completions/extern_crate.rs
+++ b/crates/ide-completion/src/completions/extern_crate.rs
@@ -2,6 +2,7 @@
 
 use hir::Name;
 use ide_db::{documentation::HasDocs, SymbolKind};
+use syntax::ToSmolStr;
 
 use crate::{context::CompletionContext, CompletionItem, CompletionItemKind};
 
@@ -18,7 +19,7 @@ pub(crate) fn complete_extern_crate(acc: &mut Completions, ctx: &CompletionConte
         let mut item = CompletionItem::new(
             CompletionItemKind::SymbolKind(SymbolKind::Module),
             ctx.source_range(),
-            name.to_smol_str(),
+            name.display_no_db().to_smolstr(),
         );
         item.set_documentation(module.docs(ctx.db));
 
diff --git a/crates/ide-completion/src/completions/flyimport.rs b/crates/ide-completion/src/completions/flyimport.rs
index 3a8b9c0cb9..e803072fa8 100644
--- a/crates/ide-completion/src/completions/flyimport.rs
+++ b/crates/ide-completion/src/completions/flyimport.rs
@@ -5,7 +5,7 @@ use ide_db::imports::{
     insert_use::ImportScope,
 };
 use itertools::Itertools;
-use syntax::{ast, AstNode, SyntaxNode, T};
+use syntax::{ast, AstNode, SyntaxNode, ToSmolStr, T};
 
 use crate::{
     context::{
@@ -424,7 +424,7 @@ fn compute_fuzzy_completion_order_key(
     cov_mark::hit!(certain_fuzzy_order_test);
     let import_name = match proposed_mod_path.segments().last() {
         // FIXME: nasty alloc, this is a hot path!
-        Some(name) => name.to_smol_str().to_ascii_lowercase(),
+        Some(name) => name.display_no_db().to_smolstr().to_ascii_lowercase(),
         None => return usize::MAX,
     };
     match import_name.match_indices(user_input_lowercased).next() {
diff --git a/crates/ide-completion/src/completions/format_string.rs b/crates/ide-completion/src/completions/format_string.rs
index 559a9bcba2..23affc3659 100644
--- a/crates/ide-completion/src/completions/format_string.rs
+++ b/crates/ide-completion/src/completions/format_string.rs
@@ -3,7 +3,7 @@
 use hir::{ModuleDef, ScopeDef};
 use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind};
 use itertools::Itertools;
-use syntax::{ast, AstToken, TextRange, TextSize};
+use syntax::{ast, AstToken, TextRange, TextSize, ToSmolStr};
 
 use crate::{context::CompletionContext, CompletionItem, CompletionItemKind, Completions};
 
@@ -32,8 +32,12 @@ pub(crate) fn format_string(
 
     let source_range = TextRange::new(brace_offset, cursor);
     ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()).for_each(|(name, _)| {
-        CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
-            .add_to(acc, ctx.db);
+        CompletionItem::new(
+            CompletionItemKind::Binding,
+            source_range,
+            name.display_no_db().to_smolstr(),
+        )
+        .add_to(acc, ctx.db);
     });
     ctx.scope.process_all_names(&mut |name, scope| {
         if let ScopeDef::ModuleDef(module_def) = scope {
@@ -46,7 +50,7 @@ pub(crate) fn format_string(
             CompletionItem::new(
                 CompletionItemKind::SymbolKind(symbol_kind),
                 source_range,
-                name.to_smol_str(),
+                name.display_no_db().to_smolstr(),
             )
             .add_to(acc, ctx.db);
         }
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index c48672e80a..f9dc62562f 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -38,7 +38,7 @@ use ide_db::{
 };
 use syntax::{
     ast::{self, edit_in_place::AttrsOwnerEdit, HasTypeBounds},
-    format_smolstr, AstNode, SmolStr, SyntaxElement, SyntaxKind, TextRange, T,
+    format_smolstr, AstNode, SmolStr, SyntaxElement, SyntaxKind, TextRange, ToSmolStr, T,
 };
 use text_edit::TextEdit;
 
@@ -252,7 +252,7 @@ fn add_type_alias_impl(
     type_alias: hir::TypeAlias,
     impl_def: hir::Impl,
 ) {
-    let alias_name = type_alias.name(ctx.db).unescaped().to_smol_str();
+    let alias_name = type_alias.name(ctx.db).unescaped().display(ctx.db).to_smolstr();
 
     let label = format_smolstr!("type {alias_name} =");
 
@@ -314,7 +314,7 @@ fn add_const_impl(
     const_: hir::Const,
     impl_def: hir::Impl,
 ) {
-    let const_name = const_.name(ctx.db).map(|n| n.to_smol_str());
+    let const_name = const_.name(ctx.db).map(|n| n.display_no_db().to_smolstr());
 
     if let Some(const_name) = const_name {
         if let Some(source) = ctx.sema.source(const_) {
diff --git a/crates/ide-completion/src/completions/lifetime.rs b/crates/ide-completion/src/completions/lifetime.rs
index f31352f49f..03fe93c563 100644
--- a/crates/ide-completion/src/completions/lifetime.rs
+++ b/crates/ide-completion/src/completions/lifetime.rs
@@ -8,7 +8,7 @@
 //! show up for normal completions, or they won't show completions other than lifetimes depending
 //! on the fixture input.
 use hir::{sym, Name, ScopeDef};
-use syntax::{ast, TokenText};
+use syntax::{ast, ToSmolStr, TokenText};
 
 use crate::{
     completions::Completions,
@@ -41,7 +41,7 @@ pub(crate) fn complete_lifetime(
         if matches!(
             res,
             ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_))
-                 if param_lifetime != Some(&*name.to_smol_str())
+                 if param_lifetime != Some(&*name.display_no_db().to_smolstr())
         ) {
             acc.add_lifetime(ctx, name);
         }
diff --git a/crates/ide-completion/src/completions/mod_.rs b/crates/ide-completion/src/completions/mod_.rs
index f307ba9eb3..c0333b1d0a 100644
--- a/crates/ide-completion/src/completions/mod_.rs
+++ b/crates/ide-completion/src/completions/mod_.rs
@@ -7,7 +7,7 @@ use ide_db::{
     base_db::{SourceDatabaseExt, VfsPath},
     FxHashSet, RootDatabase, SymbolKind,
 };
-use syntax::{ast, AstNode, SyntaxKind};
+use syntax::{ast, AstNode, SyntaxKind, ToSmolStr};
 
 use crate::{context::CompletionContext, CompletionItem, Completions};
 
@@ -139,7 +139,7 @@ fn directory_to_look_for_submodules(
     module_chain_to_containing_module_file(module, db)
         .into_iter()
         .filter_map(|module| module.name(db))
-        .try_fold(base_directory, |path, name| path.join(&name.to_smol_str()))
+        .try_fold(base_directory, |path, name| path.join(&name.display_no_db().to_smolstr()))
 }
 
 fn module_chain_to_containing_module_file(
diff --git a/crates/ide-completion/src/completions/use_.rs b/crates/ide-completion/src/completions/use_.rs
index 5fe6cd0e90..8e5b55360d 100644
--- a/crates/ide-completion/src/completions/use_.rs
+++ b/crates/ide-completion/src/completions/use_.rs
@@ -48,7 +48,7 @@ pub(crate) fn complete_use_path(
                     let unknown_is_current = |name: &hir::Name| {
                         matches!(
                             name_ref,
-                            Some(name_ref) if name_ref.syntax().text() == name.to_smol_str().as_str()
+                            Some(name_ref) if name_ref.syntax().text() == name.as_str()
                         )
                     };
                     for (name, def) in module_scope {
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 5782a4423a..55f39440ee 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -519,7 +519,7 @@ impl CompletionContext<'_> {
         I: hir::HasAttrs + Copy,
     {
         let attrs = item.attrs(self.db);
-        attrs.doc_aliases().collect()
+        attrs.doc_aliases().map(|it| it.as_str().into()).collect()
     }
 
     /// Check if an item is `#[doc(hidden)]`.
@@ -543,7 +543,7 @@ impl CompletionContext<'_> {
     /// Whether the given trait is an operator trait or not.
     pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
         match trait_.attrs(self.db).lang() {
-            Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang),
+            Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
             None => false,
         }
     }
@@ -643,7 +643,7 @@ impl CompletionContext<'_> {
 
     pub(crate) fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
         if let Some(attrs) = scope_def.attrs(self.db) {
-            attrs.doc_aliases().collect()
+            attrs.doc_aliases().map(|it| it.as_str().into()).collect()
         } else {
             vec![]
         }
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index 15c20f1186..abcff62341 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -10,14 +10,14 @@ pub(crate) mod type_alias;
 pub(crate) mod union_literal;
 pub(crate) mod variant;
 
-use hir::{AsAssocItem, HasAttrs, HirDisplay, ImportPathConfig, ModuleDef, ScopeDef, Type};
+use hir::{sym, AsAssocItem, HasAttrs, HirDisplay, ImportPathConfig, ModuleDef, ScopeDef, Type};
 use ide_db::{
     documentation::{Documentation, HasDocs},
     helpers::item_name,
     imports::import_assets::LocatedImport,
     RootDatabase, SnippetCap, SymbolKind,
 };
-use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange};
+use syntax::{ast, format_smolstr, AstNode, SmolStr, SyntaxKind, TextRange, ToSmolStr};
 use text_edit::TextEdit;
 
 use crate::{
@@ -95,7 +95,7 @@ impl<'a> RenderContext<'a> {
 
     fn is_deprecated(&self, def: impl HasAttrs) -> bool {
         let attrs = def.attrs(self.db());
-        attrs.by_key("deprecated").exists()
+        attrs.by_key(&sym::deprecated).exists()
     }
 
     fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
@@ -133,7 +133,8 @@ pub(crate) fn render_field(
     let db = ctx.db();
     let is_deprecated = ctx.is_deprecated(field);
     let name = field.name(db);
-    let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
+    let (name, escaped_name) =
+        (name.unescaped().display(db).to_smolstr(), name.display_no_db().to_smolstr());
     let mut item = CompletionItem::new(
         SymbolKind::Field,
         ctx.source_range(),
@@ -399,10 +400,10 @@ fn render_resolution_path(
     let config = completion.config;
     let requires_import = import_to_add.is_some();
 
-    let name = local_name.to_smol_str();
+    let name = local_name.display_no_db().to_smolstr();
     let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
     if local_name.is_escaped() {
-        item.insert_text(local_name.to_smol_str());
+        item.insert_text(local_name.display_no_db().to_smolstr());
     }
     // Add `<>` for generic types
     let type_path_no_ty_args = matches!(
@@ -484,8 +485,11 @@ fn render_resolution_simple_(
     let ctx = ctx.import_to_add(import_to_add);
     let kind = res_to_kind(resolution);
 
-    let mut item =
-        CompletionItem::new(kind, ctx.source_range(), local_name.unescaped().to_smol_str());
+    let mut item = CompletionItem::new(
+        kind,
+        ctx.source_range(),
+        local_name.unescaped().display(db).to_smolstr(),
+    );
     item.set_relevance(ctx.completion_relevance())
         .set_documentation(scope_def_docs(db, resolution))
         .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
diff --git a/crates/ide-completion/src/render/const_.rs b/crates/ide-completion/src/render/const_.rs
index a6a1c79e66..3bfec0de6b 100644
--- a/crates/ide-completion/src/render/const_.rs
+++ b/crates/ide-completion/src/render/const_.rs
@@ -2,6 +2,7 @@
 
 use hir::{AsAssocItem, HirDisplay};
 use ide_db::SymbolKind;
+use syntax::ToSmolStr;
 
 use crate::{item::CompletionItem, render::RenderContext};
 
@@ -13,7 +14,8 @@ pub(crate) fn render_const(ctx: RenderContext<'_>, const_: hir::Const) -> Option
 fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem> {
     let db = ctx.db();
     let name = const_.name(db)?;
-    let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
+    let (name, escaped_name) =
+        (name.unescaped().display(db).to_smolstr(), name.display(db).to_smolstr());
     let detail = const_.display(db).to_string();
 
     let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), name);
@@ -24,7 +26,7 @@ fn render(ctx: RenderContext<'_>, const_: hir::Const) -> Option<CompletionItem>
 
     if let Some(actm) = const_.as_assoc_item(db) {
         if let Some(trt) = actm.container_or_implemented_trait(db) {
-            item.trait_name(trt.name(db).to_smol_str());
+            item.trait_name(trt.name(db).display_no_db().to_smolstr());
         }
     }
     item.insert_text(escaped_name);
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index cdfe231701..05b2d0ae38 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -4,7 +4,7 @@ use hir::{db::HirDatabase, AsAssocItem, HirDisplay};
 use ide_db::{SnippetCap, SymbolKind};
 use itertools::Itertools;
 use stdx::{format_to, to_lower_snake_case};
-use syntax::{format_smolstr, AstNode, SmolStr};
+use syntax::{format_smolstr, AstNode, SmolStr, ToSmolStr};
 
 use crate::{
     context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
@@ -64,7 +64,7 @@ fn render(
             ),
             format_smolstr!("{}.{}", receiver.display(ctx.db()), name.display(ctx.db())),
         ),
-        _ => (name.unescaped().to_smol_str(), name.to_smol_str()),
+        _ => (name.unescaped().display(db).to_smolstr(), name.display(db).to_smolstr()),
     };
     let has_self_param = func.self_param(db).is_some();
     let mut item = CompletionItem::new(
@@ -148,7 +148,7 @@ fn render(
     item.set_documentation(ctx.docs(func))
         .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
         .detail(detail)
-        .lookup_by(name.unescaped().to_smol_str());
+        .lookup_by(name.unescaped().display(db).to_smolstr());
 
     if let Some((cap, (self_param, params))) = complete_call_parens {
         add_call_parens(&mut item, completion, cap, call, escaped_call, self_param, params);
@@ -161,7 +161,7 @@ fn render(
         None => {
             if let Some(actm) = assoc_item {
                 if let Some(trt) = actm.container_or_implemented_trait(db) {
-                    item.trait_name(trt.name(db).to_smol_str());
+                    item.trait_name(trt.name(db).display_no_db().to_smolstr());
                 }
             }
         }
@@ -219,7 +219,7 @@ pub(super) fn add_call_parens<'b>(
                 params.iter().enumerate().format_with(", ", |(index, param), f| {
                     match param.name(ctx.db) {
                         Some(n) => {
-                            let smol_str = n.to_smol_str();
+                            let smol_str = n.display_no_db().to_smolstr();
                             let text = smol_str.as_str().trim_start_matches('_');
                             let ref_ = ref_of_param(ctx, text, param.ty());
                             f(&format_args!("${{{}:{ref_}{text}}}", index + offset))
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs
index a6c8c0e853..de715bcbfa 100644
--- a/crates/ide-completion/src/render/macro_.rs
+++ b/crates/ide-completion/src/render/macro_.rs
@@ -2,7 +2,7 @@
 
 use hir::HirDisplay;
 use ide_db::{documentation::Documentation, SymbolKind};
-use syntax::{format_smolstr, SmolStr};
+use syntax::{format_smolstr, SmolStr, ToSmolStr};
 
 use crate::{
     context::{PathCompletionCtx, PathKind, PatternContext},
@@ -46,7 +46,8 @@ fn render(
         ctx.source_range()
     };
 
-    let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
+    let (name, escaped_name) =
+        (name.unescaped().display(ctx.db()).to_smolstr(), name.display(ctx.db()).to_smolstr());
     let docs = ctx.docs(macro_);
     let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default();
     let is_fn_like = macro_.is_fn_like(completion.db);
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index 942670be2a..598b8762b6 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -3,7 +3,7 @@
 use hir::{db::HirDatabase, Name, StructKind};
 use ide_db::{documentation::HasDocs, SnippetCap};
 use itertools::Itertools;
-use syntax::SmolStr;
+use syntax::{SmolStr, ToSmolStr};
 
 use crate::{
     context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext},
@@ -31,7 +31,8 @@ pub(crate) fn render_struct_pat(
     }
 
     let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
-    let (name, escaped_name) = (name.unescaped().to_smol_str(), name.to_smol_str());
+    let (name, escaped_name) =
+        (name.unescaped().display(ctx.db()).to_smolstr(), name.display(ctx.db()).to_smolstr());
     let kind = strukt.kind(ctx.db());
     let label = format_literal_label(name.as_str(), kind, ctx.snippet_cap());
     let lookup = format_literal_lookup(name.as_str(), kind);
@@ -63,7 +64,11 @@ pub(crate) fn render_variant_pat(
         ),
         None => {
             let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
-            (name.unescaped().to_smol_str(), name.to_smol_str())
+            let it = (
+                name.unescaped().display(ctx.db()).to_smolstr(),
+                name.display(ctx.db()).to_smolstr(),
+            );
+            it
         }
     };
 
@@ -184,7 +189,7 @@ fn render_record_as_pat(
         None => {
             format!(
                 "{name} {{ {}{} }}",
-                fields.map(|field| field.name(db).to_smol_str()).format(", "),
+                fields.map(|field| field.name(db).display_no_db().to_smolstr()).format(", "),
                 if fields_omitted { ", .." } else { "" },
                 name = name
             )
diff --git a/crates/ide-completion/src/render/type_alias.rs b/crates/ide-completion/src/render/type_alias.rs
index 47254e6a18..b81caf2422 100644
--- a/crates/ide-completion/src/render/type_alias.rs
+++ b/crates/ide-completion/src/render/type_alias.rs
@@ -2,7 +2,7 @@
 
 use hir::{AsAssocItem, HirDisplay};
 use ide_db::SymbolKind;
-use syntax::SmolStr;
+use syntax::{SmolStr, ToSmolStr};
 
 use crate::{item::CompletionItem, render::RenderContext};
 
@@ -32,11 +32,11 @@ fn render(
     let name = type_alias.name(db);
     let (name, escaped_name) = if with_eq {
         (
-            SmolStr::from_iter([&name.unescaped().to_smol_str(), " = "]),
-            SmolStr::from_iter([&name.to_smol_str(), " = "]),
+            SmolStr::from_iter([&name.unescaped().display(db).to_smolstr(), " = "]),
+            SmolStr::from_iter([&name.display_no_db().to_smolstr(), " = "]),
         )
     } else {
-        (name.unescaped().to_smol_str(), name.to_smol_str())
+        (name.unescaped().display(db).to_smolstr(), name.display_no_db().to_smolstr())
     };
     let detail = type_alias.display(db).to_string();
 
@@ -48,7 +48,7 @@ fn render(
 
     if let Some(actm) = type_alias.as_assoc_item(db) {
         if let Some(trt) = actm.container_or_implemented_trait(db) {
-            item.trait_name(trt.name(db).to_smol_str());
+            item.trait_name(trt.name(db).display_no_db().to_smolstr());
         }
     }
     item.insert_text(escaped_name);
diff --git a/crates/ide-completion/src/render/union_literal.rs b/crates/ide-completion/src/render/union_literal.rs
index 93e943dbed..ca7593c122 100644
--- a/crates/ide-completion/src/render/union_literal.rs
+++ b/crates/ide-completion/src/render/union_literal.rs
@@ -3,6 +3,7 @@
 use hir::{HirDisplay, Name, StructKind};
 use ide_db::SymbolKind;
 use itertools::Itertools;
+use syntax::ToSmolStr;
 
 use crate::{
     render::{
@@ -26,8 +27,12 @@ pub(crate) fn render_union_literal(
             (name.unescaped().display(ctx.db()).to_string(), name.display(ctx.db()).to_string())
         }
     };
-    let label = format_literal_label(&name.to_smol_str(), StructKind::Record, ctx.snippet_cap());
-    let lookup = format_literal_lookup(&name.to_smol_str(), StructKind::Record);
+    let label = format_literal_label(
+        &name.display_no_db().to_smolstr(),
+        StructKind::Record,
+        ctx.snippet_cap(),
+    );
+    let lookup = format_literal_lookup(&name.display_no_db().to_smolstr(), StructKind::Record);
     let mut item = CompletionItem::new(
         CompletionItemKind::SymbolKind(SymbolKind::Union),
         ctx.source_range(),
@@ -47,7 +52,10 @@ pub(crate) fn render_union_literal(
         format!(
             "{} {{ ${{1|{}|}}: ${{2:()}} }}$0",
             escaped_qualified_name,
-            fields.iter().map(|field| field.name(ctx.db()).to_smol_str()).format(",")
+            fields
+                .iter()
+                .map(|field| field.name(ctx.db()).display_no_db().to_smolstr())
+                .format(",")
         )
     } else {
         format!(
diff --git a/crates/ide-completion/src/render/variant.rs b/crates/ide-completion/src/render/variant.rs
index 28238de455..bc2df9e39f 100644
--- a/crates/ide-completion/src/render/variant.rs
+++ b/crates/ide-completion/src/render/variant.rs
@@ -1,7 +1,7 @@
 //! Code common to structs, unions, and enum variants.
 
 use crate::context::CompletionContext;
-use hir::{db::HirDatabase, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind};
+use hir::{db::HirDatabase, sym, HasAttrs, HasCrate, HasVisibility, HirDisplay, StructKind};
 use ide_db::SnippetCap;
 use itertools::Itertools;
 use syntax::SmolStr;
@@ -86,7 +86,7 @@ pub(crate) fn visible_fields(
         .copied()
         .collect::<Vec<_>>();
     let has_invisible_field = n_fields - fields.len() > 0;
-    let is_foreign_non_exhaustive = item.attrs(ctx.db).by_key("non_exhaustive").exists()
+    let is_foreign_non_exhaustive = item.attrs(ctx.db).by_key(&sym::non_exhaustive).exists()
         && item.krate(ctx.db) != module.krate();
     let fields_omitted = has_invisible_field || is_foreign_non_exhaustive;
     Some((fields, fields_omitted))
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index a53c156b5d..991bef344a 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -17,7 +17,7 @@ use hir::{
 use stdx::{format_to, impl_from};
 use syntax::{
     ast::{self, AstNode},
-    match_ast, SyntaxKind, SyntaxNode, SyntaxToken,
+    match_ast, SyntaxKind, SyntaxNode, SyntaxToken, ToSmolStr,
 };
 
 use crate::documentation::{Documentation, HasDocs};
@@ -670,7 +670,7 @@ impl NameRefClass {
                                 hir::AssocItem::TypeAlias(it) => Some(it),
                                 _ => None,
                             })
-                            .find(|alias| alias.name(sema.db).to_smol_str() == name_ref.text().as_str())
+                            .find(|alias| alias.name(sema.db).display_no_db().to_smolstr() == name_ref.text().as_str())
                         {
                             return Some(NameRefClass::Definition(Definition::TypeAlias(ty)));
                         }
diff --git a/crates/ide-db/src/documentation.rs b/crates/ide-db/src/documentation.rs
index 1b9b78f691..5e443badf9 100644
--- a/crates/ide-db/src/documentation.rs
+++ b/crates/ide-db/src/documentation.rs
@@ -2,7 +2,7 @@
 use either::Either;
 use hir::{
     db::{DefDatabase, HirDatabase},
-    resolve_doc_path_on, AttrId, AttrSourceMap, AttrsWithOwner, HasAttrs, InFile,
+    resolve_doc_path_on, sym, AttrId, AttrSourceMap, AttrsWithOwner, HasAttrs, InFile,
 };
 use itertools::Itertools;
 use syntax::{
@@ -92,7 +92,7 @@ pub fn docs_with_rangemap(
     attrs: &AttrsWithOwner,
 ) -> Option<(Documentation, DocsRangeMap)> {
     let docs = attrs
-        .by_key("doc")
+        .by_key(&sym::doc)
         .attrs()
         .filter_map(|attr| attr.string_value_unescape().map(|s| (s, attr.id)));
     let indent = doc_indent(attrs);
@@ -134,7 +134,7 @@ pub fn docs_with_rangemap(
 }
 
 pub fn docs_from_attrs(attrs: &hir::Attrs) -> Option<String> {
-    let docs = attrs.by_key("doc").attrs().filter_map(|attr| attr.string_value_unescape());
+    let docs = attrs.by_key(&sym::doc).attrs().filter_map(|attr| attr.string_value_unescape());
     let indent = doc_indent(attrs);
     let mut buf = String::new();
     for doc in docs {
@@ -270,7 +270,7 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
 
 fn doc_indent(attrs: &hir::Attrs) -> usize {
     let mut min = !0;
-    for val in attrs.by_key("doc").attrs().filter_map(|attr| attr.string_value_unescape()) {
+    for val in attrs.by_key(&sym::doc).attrs().filter_map(|attr| attr.string_value_unescape()) {
         if let Some(m) =
             val.lines().filter_map(|line| line.chars().position(|c| !c.is_whitespace())).min()
         {
diff --git a/crates/ide-db/src/famous_defs.rs b/crates/ide-db/src/famous_defs.rs
index 51ac0b7191..1a16a567f3 100644
--- a/crates/ide-db/src/famous_defs.rs
+++ b/crates/ide-db/src/famous_defs.rs
@@ -2,6 +2,7 @@
 
 use base_db::{CrateOrigin, LangCrateOrigin, SourceDatabase};
 use hir::{Crate, Enum, Function, Macro, Module, ScopeDef, Semantics, Trait};
+use syntax::ToSmolStr;
 
 use crate::RootDatabase;
 
@@ -198,15 +199,18 @@ impl FamousDefs<'_, '_> {
         for segment in path {
             module = module.children(db).find_map(|child| {
                 let name = child.name(db)?;
-                if name.to_smol_str() == segment {
+                if name.display_no_db().to_smolstr() == segment {
                     Some(child)
                 } else {
                     None
                 }
             })?;
         }
-        let def =
-            module.scope(db, None).into_iter().find(|(name, _def)| name.to_smol_str() == trait_)?.1;
+        let def = module
+            .scope(db, None)
+            .into_iter()
+            .find(|(name, _def)| name.display_no_db().to_smolstr() == trait_)?
+            .1;
         Some(def)
     }
 }
diff --git a/crates/ide-db/src/helpers.rs b/crates/ide-db/src/helpers.rs
index c069e1c25b..0e7ee13717 100644
--- a/crates/ide-db/src/helpers.rs
+++ b/crates/ide-db/src/helpers.rs
@@ -6,7 +6,7 @@ use base_db::{FileId, SourceDatabaseExt};
 use hir::{Crate, DescendPreference, ItemInNs, ModuleDef, Name, Semantics};
 use syntax::{
     ast::{self, make},
-    AstToken, SyntaxKind, SyntaxToken, TokenAtOffset,
+    AstToken, SyntaxKind, SyntaxToken, ToSmolStr, TokenAtOffset,
 };
 
 use crate::{
@@ -50,9 +50,9 @@ pub fn mod_path_to_ast(path: &hir::ModPath) -> ast::Path {
     }
 
     segments.extend(
-        path.segments()
-            .iter()
-            .map(|segment| make::path_segment(make::name_ref(&segment.to_smol_str()))),
+        path.segments().iter().map(|segment| {
+            make::path_segment(make::name_ref(&segment.display_no_db().to_smolstr()))
+        }),
     );
     make::path_from_segments(segments, is_abs)
 }
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index 38cb4a162c..3bb5ac1b10 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -9,7 +9,7 @@ use itertools::{EitherOrBoth, Itertools};
 use rustc_hash::{FxHashMap, FxHashSet};
 use syntax::{
     ast::{self, make, HasName},
-    AstNode, SmolStr, SyntaxNode,
+    AstNode, SmolStr, SyntaxNode, ToSmolStr,
 };
 
 use crate::{
@@ -459,7 +459,7 @@ fn find_import_for_segment(
     unresolved_first_segment: &str,
 ) -> Option<ItemInNs> {
     let segment_is_name = item_name(db, original_item)
-        .map(|name| name.to_smol_str() == unresolved_first_segment)
+        .map(|name| name.display_no_db().to_smolstr() == unresolved_first_segment)
         .unwrap_or(false);
 
     Some(if segment_is_name {
@@ -483,7 +483,7 @@ fn module_with_segment_name(
     };
     while let Some(module) = current_module {
         if let Some(module_name) = module.name(db) {
-            if module_name.to_smol_str() == segment_name {
+            if module_name.display_no_db().to_smolstr() == segment_name {
                 return Some(module);
             }
         }
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index e1cfe04898..b7b8c5a66f 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -8,14 +8,14 @@ use std::mem;
 
 use base_db::{salsa::Database, FileId, FileRange, SourceDatabase, SourceDatabaseExt};
 use hir::{
-    AsAssocItem, DefWithBody, DescendPreference, HasAttrs, HasSource, HirFileIdExt, InFile,
+    sym, AsAssocItem, DefWithBody, DescendPreference, HasAttrs, HasSource, HirFileIdExt, InFile,
     InRealFile, ModuleSource, PathResolution, Semantics, Visibility,
 };
 use memchr::memmem::Finder;
 use nohash_hasher::IntMap;
 use once_cell::unsync::Lazy;
 use parser::SyntaxKind;
-use syntax::{ast, match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize};
+use syntax::{ast, match_ast, AstNode, AstToken, SyntaxElement, TextRange, TextSize, ToSmolStr};
 use triomphe::Arc;
 
 use crate::{
@@ -333,7 +333,7 @@ impl Definition {
         if let Definition::Macro(macro_def) = self {
             return match macro_def.kind(db) {
                 hir::MacroKind::Declarative => {
-                    if macro_def.attrs(db).by_key("macro_export").exists() {
+                    if macro_def.attrs(db).by_key(&sym::macro_export).exists() {
                         SearchScope::reverse_dependencies(db, module.krate())
                     } else {
                         SearchScope::krate(db, module.krate())
@@ -456,7 +456,7 @@ impl<'a> FindUsages<'a> {
                 module
                     .krate()
                     .display_name(self.sema.db)
-                    .map(|crate_name| crate_name.crate_name().as_smol_str().clone())
+                    .map(|crate_name| crate_name.crate_name().symbol().as_str().into())
             }
             _ => {
                 let self_kw_refs = || {
@@ -468,7 +468,10 @@ impl<'a> FindUsages<'a> {
                 };
                 // We need to unescape the name in case it is written without "r#" in earlier
                 // editions of Rust where it isn't a keyword.
-                self.def.name(sema.db).or_else(self_kw_refs).map(|it| it.unescaped().to_smol_str())
+                self.def
+                    .name(sema.db)
+                    .or_else(self_kw_refs)
+                    .map(|it| it.unescaped().display(sema.db).to_smolstr())
             }
         };
         let name = match &name {
diff --git a/crates/ide-db/src/ty_filter.rs b/crates/ide-db/src/ty_filter.rs
index 46f47f258b..5b566c5067 100644
--- a/crates/ide-db/src/ty_filter.rs
+++ b/crates/ide-db/src/ty_filter.rs
@@ -5,7 +5,10 @@
 use std::iter;
 
 use hir::Semantics;
-use syntax::ast::{self, make, Pat};
+use syntax::{
+    ast::{self, make, Pat},
+    ToSmolStr,
+};
 
 use crate::RootDatabase;
 
@@ -26,7 +29,7 @@ impl TryEnum {
             _ => return None,
         };
         TryEnum::ALL.iter().find_map(|&var| {
-            if enum_.name(sema.db).to_smol_str() == var.type_name() {
+            if enum_.name(sema.db).display_no_db().to_smolstr() == var.type_name() {
                 return Some(var);
             }
             None
diff --git a/crates/ide-db/src/use_trivial_constructor.rs b/crates/ide-db/src/use_trivial_constructor.rs
index a915391ad9..965f432407 100644
--- a/crates/ide-db/src/use_trivial_constructor.rs
+++ b/crates/ide-db/src/use_trivial_constructor.rs
@@ -1,7 +1,10 @@
 //! Functionality for generating trivial constructors
 
 use hir::StructKind;
-use syntax::ast::{make, Expr, Path};
+use syntax::{
+    ast::{make, Expr, Path},
+    ToSmolStr,
+};
 
 /// given a type return the trivial constructor (if one exists)
 pub fn use_trivial_constructor(
@@ -15,7 +18,9 @@ pub fn use_trivial_constructor(
                 if variant.kind(db) == hir::StructKind::Unit {
                     let path = make::path_qualified(
                         path,
-                        make::path_segment(make::name_ref(&variant.name(db).to_smol_str())),
+                        make::path_segment(make::name_ref(
+                            &variant.name(db).display_no_db().to_smolstr(),
+                        )),
                     );
 
                     return Some(make::expr_path(path));
diff --git a/crates/ide-diagnostics/src/handlers/missing_fields.rs b/crates/ide-diagnostics/src/handlers/missing_fields.rs
index a41bf457a9..ea7908525a 100644
--- a/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -11,7 +11,7 @@ use stdx::format_to;
 use syntax::{
     algo,
     ast::{self, make},
-    AstNode, SyntaxNode, SyntaxNodePtr,
+    AstNode, SyntaxNode, SyntaxNodePtr, ToSmolStr,
 };
 use text_edit::TextEdit;
 
@@ -146,7 +146,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
                     }
                 };
                 let field = make::record_expr_field(
-                    make::name_ref(&f.name(ctx.sema.db).to_smol_str()),
+                    make::name_ref(&f.name(ctx.sema.db).display_no_db().to_smolstr()),
                     field_expr,
                 );
                 new_field_list.add_field(field.clone_for_update());
@@ -160,7 +160,7 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Ass
             let new_field_list = old_field_list.clone_for_update();
             for (f, _) in missing_fields.iter() {
                 let field = make::record_pat_field_shorthand(make::name_ref(
-                    &f.name(ctx.sema.db).to_smol_str(),
+                    &f.name(ctx.sema.db).display_no_db().to_smolstr(),
                 ));
                 new_field_list.add_field(field.clone_for_update());
             }
diff --git a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
index 8c50960684..6d756484eb 100644
--- a/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
+++ b/crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs
@@ -4,6 +4,7 @@ use ide_db::{
     label::Label,
     source_change::SourceChangeBuilder,
 };
+use syntax::ToSmolStr;
 use text_edit::TextRange;
 
 use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
@@ -21,7 +22,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
     let assoc_item = d.assoc_item.1;
 
     let default_range = d.impl_.syntax_node_ptr().text_range();
-    let trait_name = d.trait_.name(db).to_smol_str();
+    let trait_name = d.trait_.name(db).display_no_db().to_smolstr();
 
     let (redundant_item_name, diagnostic_range, redundant_item_def) = match assoc_item {
         hir::AssocItem::Function(id) => {
@@ -45,7 +46,10 @@ pub(crate) fn trait_impl_redundant_assoc_item(
             (
                 format!("`type {redundant_assoc_item_name}`"),
                 type_alias.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
-                format!("\n    type {};", type_alias.name(ctx.sema.db).to_smol_str()),
+                format!(
+                    "\n    type {};",
+                    type_alias.name(ctx.sema.db).display_no_db().to_smolstr()
+                ),
             )
         }
     };
diff --git a/crates/ide-diagnostics/src/handlers/unlinked_file.rs b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
index 77ffd0fd96..2c90577120 100644
--- a/crates/ide-diagnostics/src/handlers/unlinked_file.rs
+++ b/crates/ide-diagnostics/src/handlers/unlinked_file.rs
@@ -11,7 +11,7 @@ use ide_db::{
 use paths::Utf8Component;
 use syntax::{
     ast::{self, edit::IndentLevel, HasModuleItem, HasName},
-    AstNode, TextRange,
+    AstNode, TextRange, ToSmolStr,
 };
 use text_edit::TextEdit;
 
@@ -106,7 +106,8 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
                 // shouldn't occur
                 _ => continue 'crates,
             };
-            match current.children.iter().find(|(name, _)| name.to_smol_str() == seg) {
+            match current.children.iter().find(|(name, _)| name.display_no_db().to_smolstr() == seg)
+            {
                 Some((_, &child)) => current = &crate_def_map[child],
                 None => continue 'crates,
             }
@@ -156,7 +157,11 @@ fn fixes(ctx: &DiagnosticsContext<'_>, file_id: FileId) -> Option<Vec<Assist>> {
             // try finding a parent that has an inline tree from here on
             let mut current = module;
             for s in stack.iter().rev() {
-                match module.children.iter().find(|(name, _)| name.to_smol_str() == s) {
+                match module
+                    .children
+                    .iter()
+                    .find(|(name, _)| name.display_no_db().to_smolstr() == s)
+                {
                     Some((_, child)) => {
                         current = &crate_def_map[*child];
                     }
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_method.rs b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
index 46722f43d4..41f4b57508 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_method.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_method.rs
@@ -7,7 +7,7 @@ use ide_db::{
 };
 use syntax::{
     ast::{self, make, HasArgList},
-    AstNode, SmolStr, TextRange,
+    format_smolstr, AstNode, SmolStr, TextRange, ToSmolStr,
 };
 use text_edit::TextEdit;
 
@@ -154,14 +154,16 @@ fn assoc_func_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedMethodCall) -
             _ => false,
         };
 
-        let mut receiver_type_adt_name = receiver_type.as_adt()?.name(db).to_smol_str().to_string();
+        let mut receiver_type_adt_name =
+            receiver_type.as_adt()?.name(db).display_no_db().to_smolstr();
 
         let generic_parameters: Vec<SmolStr> = receiver_type.generic_parameters(db).collect();
         // if receiver should be pass as first arg in the assoc func,
         // we could omit generic parameters cause compiler can deduce it automatically
         if !need_to_take_receiver_as_first_arg && !generic_parameters.is_empty() {
             let generic_parameters = generic_parameters.join(", ");
-            receiver_type_adt_name = format!("{receiver_type_adt_name}::<{generic_parameters}>");
+            receiver_type_adt_name =
+                format_smolstr!("{receiver_type_adt_name}::<{generic_parameters}>");
         }
 
         let method_name = call.name_ref()?;
diff --git a/crates/ide-ssr/src/resolving.rs b/crates/ide-ssr/src/resolving.rs
index d3c1af1f31..9feb096677 100644
--- a/crates/ide-ssr/src/resolving.rs
+++ b/crates/ide-ssr/src/resolving.rs
@@ -238,7 +238,7 @@ impl<'db> ResolutionScope<'db> {
                 None,
                 |assoc_item| {
                     let item_name = assoc_item.name(self.scope.db)?;
-                    if item_name.to_smol_str().as_str() == name.text() {
+                    if item_name.as_str() == name.text() {
                         Some(hir::PathResolution::Def(assoc_item.into()))
                     } else {
                         None
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs
index f42613637b..7214c89a1e 100644
--- a/crates/ide/src/doc_links.rs
+++ b/crates/ide/src/doc_links.rs
@@ -11,7 +11,8 @@ use stdx::format_to;
 use url::Url;
 
 use hir::{
-    db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, DescendPreference, HasAttrs,
+    db::HirDatabase, sym, Adt, AsAssocItem, AssocItem, AssocItemContainer, DescendPreference,
+    HasAttrs,
 };
 use ide_db::{
     base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, SourceDatabase},
@@ -593,12 +594,14 @@ fn filename_and_frag_for_def(
         },
         Definition::Module(m) => match m.name(db) {
             // `#[doc(keyword = "...")]` is internal used only by rust compiler
-            Some(name) => match m.attrs(db).by_key("doc").find_string_value_in_tt("keyword") {
-                Some(kw) => {
-                    format!("keyword.{}.html", kw.trim_matches('"'))
+            Some(name) => {
+                match m.attrs(db).by_key(&sym::doc).find_string_value_in_tt(&sym::keyword) {
+                    Some(kw) => {
+                        format!("keyword.{}.html", kw)
+                    }
+                    None => format!("{}/index.html", name.display(db.upcast())),
                 }
-                None => format!("{}/index.html", name.display(db.upcast())),
-            },
+            }
             None => String::from("index.html"),
         },
         Definition::Trait(t) => format!("trait.{}.html", t.name(db).display(db.upcast())),
diff --git a/crates/ide/src/fetch_crates.rs b/crates/ide/src/fetch_crates.rs
index 14c2655f84..712615c49a 100644
--- a/crates/ide/src/fetch_crates.rs
+++ b/crates/ide/src/fetch_crates.rs
@@ -38,5 +38,5 @@ fn crate_info(data: &ide_db::base_db::CrateData) -> CrateInfo {
 }
 
 fn crate_name(data: &ide_db::base_db::CrateData) -> Option<String> {
-    data.display_name.as_ref().map(|it| it.canonical_name().to_owned())
+    data.display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned())
 }
diff --git a/crates/ide/src/inlay_hints/implicit_drop.rs b/crates/ide/src/inlay_hints/implicit_drop.rs
index 31f0c79037..fcfbbbd626 100644
--- a/crates/ide/src/inlay_hints/implicit_drop.rs
+++ b/crates/ide/src/inlay_hints/implicit_drop.rs
@@ -14,7 +14,7 @@ use ide_db::{base_db::FileRange, RootDatabase};
 
 use syntax::{
     ast::{self, AstNode},
-    match_ast,
+    match_ast, ToSmolStr,
 };
 
 use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
@@ -88,7 +88,7 @@ pub(super) fn hints(
                 .and_then(|d| {
                     Some(FileRange { file_id: d.file_id.file_id()?, range: d.value.text_range() })
                 });
-            let name = binding.name.to_smol_str();
+            let name = binding.name.display_no_db().to_smolstr();
             if name.starts_with("<ra@") {
                 continue; // Ignore desugared variables
             }
diff --git a/crates/ide/src/inlay_hints/param_name.rs b/crates/ide/src/inlay_hints/param_name.rs
index 2e2a64c552..01d8dfbc78 100644
--- a/crates/ide/src/inlay_hints/param_name.rs
+++ b/crates/ide/src/inlay_hints/param_name.rs
@@ -10,7 +10,10 @@ use hir::{Callable, Semantics};
 use ide_db::{base_db::FileRange, RootDatabase};
 
 use stdx::to_lower_snake_case;
-use syntax::ast::{self, AstNode, HasArgList, HasName, UnaryOp};
+use syntax::{
+    ast::{self, AstNode, HasArgList, HasName, UnaryOp},
+    ToSmolStr,
+};
 
 use crate::{InlayHint, InlayHintLabel, InlayHintPosition, InlayHintsConfig, InlayKind};
 
@@ -118,7 +121,7 @@ fn should_hide_param_name_hint(
     }
 
     let fn_name = match callable.kind() {
-        hir::CallableKind::Function(it) => Some(it.name(sema.db).to_smol_str()),
+        hir::CallableKind::Function(it) => Some(it.name(sema.db).display_no_db().to_smolstr()),
         _ => None,
     };
     let fn_name = fn_name.as_deref();
diff --git a/crates/ide/src/moniker.rs b/crates/ide/src/moniker.rs
index 68854c33ce..81d5b52796 100644
--- a/crates/ide/src/moniker.rs
+++ b/crates/ide/src/moniker.rs
@@ -408,7 +408,7 @@ pub(crate) fn def_to_moniker(
                     }),
                 ),
             };
-            PackageInformation { name, repo, version }
+            PackageInformation { name: name.as_str().to_owned(), repo, version }
         },
     })
 }
diff --git a/crates/ide/src/navigation_target.rs b/crates/ide/src/navigation_target.rs
index bfd62e7624..21b32f776d 100644
--- a/crates/ide/src/navigation_target.rs
+++ b/crates/ide/src/navigation_target.rs
@@ -17,7 +17,7 @@ use ide_db::{
 use stdx::never;
 use syntax::{
     ast::{self, HasName},
-    format_smolstr, AstNode, SmolStr, SyntaxNode, TextRange,
+    format_smolstr, AstNode, SmolStr, SyntaxNode, TextRange, ToSmolStr,
 };
 
 /// `NavigationTarget` represents an element in the editor's UI which you can
@@ -98,7 +98,7 @@ impl NavigationTarget {
         db: &RootDatabase,
         module: hir::Module,
     ) -> UpmappingResult<NavigationTarget> {
-        let name = module.name(db).map(|it| it.to_smol_str()).unwrap_or_default();
+        let name = module.name(db).map(|it| it.display_no_db().to_smolstr()).unwrap_or_default();
         match module.declaration_source(db) {
             Some(InFile { value, file_id }) => {
                 orig_range_with_focus(db, file_id, value.syntax(), value.name()).map(
@@ -190,7 +190,7 @@ impl TryToNav for FileSymbol {
                         .is_alias
                         .then(|| self.def.name(db))
                         .flatten()
-                        .map_or_else(|| self.name.clone(), |it| it.to_smol_str()),
+                        .map_or_else(|| self.name.clone(), |it| it.display_no_db().to_smolstr()),
                     alias: self.is_alias.then(|| self.name.clone()),
                     kind: Some(hir::ModuleDefId::from(self.def).into()),
                     full_range,
@@ -274,9 +274,9 @@ pub(crate) trait ToNavFromAst: Sized {
 
 fn container_name(db: &RootDatabase, t: impl HasContainer) -> Option<SmolStr> {
     match t.container(db) {
-        hir::ItemContainer::Trait(it) => Some(it.name(db).to_smol_str()),
+        hir::ItemContainer::Trait(it) => Some(it.name(db).display_no_db().to_smolstr()),
         // FIXME: Handle owners of blocks correctly here
-        hir::ItemContainer::Module(it) => it.name(db).map(|name| name.to_smol_str()),
+        hir::ItemContainer::Module(it) => it.name(db).map(|name| name.display_no_db().to_smolstr()),
         _ => None,
     }
 }
@@ -367,7 +367,7 @@ impl ToNav for hir::Module {
     fn to_nav(&self, db: &RootDatabase) -> UpmappingResult<NavigationTarget> {
         let InFile { file_id, value } = self.definition_source(db);
 
-        let name = self.name(db).map(|it| it.to_smol_str()).unwrap_or_default();
+        let name = self.name(db).map(|it| it.display_no_db().to_smolstr()).unwrap_or_default();
         let (syntax, focus) = match &value {
             ModuleSource::SourceFile(node) => (node.syntax(), None),
             ModuleSource::Module(node) => (node.syntax(), node.name()),
@@ -424,7 +424,10 @@ impl TryToNav for hir::ExternCrateDecl {
             |(FileRange { file_id, range: full_range }, focus_range)| {
                 let mut res = NavigationTarget::from_syntax(
                     file_id,
-                    self.alias_or_name(db).unwrap_or_else(|| self.name(db)).to_smol_str(),
+                    self.alias_or_name(db)
+                        .unwrap_or_else(|| self.name(db))
+                        .display_no_db()
+                        .to_smolstr(),
                     focus_range,
                     full_range,
                     SymbolKind::Module,
@@ -532,7 +535,7 @@ impl ToNav for LocalSource {
 
         orig_range_with_focus(db, file_id, node, name).map(
             |(FileRange { file_id, range: full_range }, focus_range)| {
-                let name = local.name(db).to_smol_str();
+                let name = local.name(db).display_no_db().to_smolstr();
                 let kind = if local.is_self(db) {
                     SymbolKind::SelfParam
                 } else if local.is_param(db) {
@@ -565,7 +568,7 @@ impl ToNav for hir::Local {
 impl TryToNav for hir::Label {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let InFile { file_id, value } = self.source(db)?;
-        let name = self.name(db).to_smol_str();
+        let name = self.name(db).display_no_db().to_smolstr();
 
         Some(orig_range_with_focus(db, file_id, value.syntax(), value.lifetime()).map(
             |(FileRange { file_id, range: full_range }, focus_range)| NavigationTarget {
@@ -586,7 +589,7 @@ impl TryToNav for hir::Label {
 impl TryToNav for hir::TypeParam {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let InFile { file_id, value } = self.merge().source(db)?;
-        let name = self.name(db).to_smol_str();
+        let name = self.name(db).display_no_db().to_smolstr();
 
         let value = match value {
             Either::Left(ast::TypeOrConstParam::Type(x)) => Either::Left(x),
@@ -628,7 +631,7 @@ impl TryToNav for hir::TypeOrConstParam {
 impl TryToNav for hir::LifetimeParam {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let InFile { file_id, value } = self.source(db)?;
-        let name = self.name(db).to_smol_str();
+        let name = self.name(db).display_no_db().to_smolstr();
 
         Some(orig_range(db, file_id, value.syntax()).map(
             |(FileRange { file_id, range: full_range }, focus_range)| NavigationTarget {
@@ -649,7 +652,7 @@ impl TryToNav for hir::LifetimeParam {
 impl TryToNav for hir::ConstParam {
     fn try_to_nav(&self, db: &RootDatabase) -> Option<UpmappingResult<NavigationTarget>> {
         let InFile { file_id, value } = self.merge().source(db)?;
-        let name = self.name(db).to_smol_str();
+        let name = self.name(db).display_no_db().to_smolstr();
 
         let value = match value {
             Either::Left(ast::TypeOrConstParam::Const(x)) => x,
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 3d08e2f371..e5f8632871 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -16,6 +16,7 @@ use itertools::Itertools;
 use stdx::{always, never};
 use syntax::{
     ast, utils::is_raw_identifier, AstNode, SmolStr, SyntaxKind, SyntaxNode, TextRange, TextSize,
+    ToSmolStr,
 };
 
 use text_edit::TextEdit;
@@ -266,7 +267,7 @@ fn find_definitions(
                             // if the name differs from the definitions name it has to be an alias
                             if def
                                 .name(sema.db)
-                                .map_or(false, |it| it.to_smol_str() != name_ref.text().as_str())
+                                .map_or(false, |it| it.display_no_db().to_smolstr() != name_ref.text().as_str())
                             {
                                 Err(format_err!("Renaming aliases is currently unsupported"))
                             } else {
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs
index 362d3238a9..f309b98f58 100644
--- a/crates/ide/src/runnables.rs
+++ b/crates/ide/src/runnables.rs
@@ -19,7 +19,7 @@ use span::TextSize;
 use stdx::{always, format_to};
 use syntax::{
     ast::{self, AstNode},
-    SmolStr, SyntaxNode,
+    SmolStr, SyntaxNode, ToSmolStr,
 };
 
 use crate::{references, FileId, NavigationTarget, ToNav, TryToNav};
@@ -332,7 +332,7 @@ pub(crate) fn runnable_fn(
             };
             canonical_path
                 .map(TestId::Path)
-                .unwrap_or(TestId::Name(def.name(sema.db).to_smol_str()))
+                .unwrap_or(TestId::Name(def.name(sema.db).display_no_db().to_smolstr()))
         };
 
         if def.is_test(sema.db) {
@@ -481,7 +481,8 @@ fn module_def_doctest(db: &RootDatabase, def: Definition) -> Option<Runnable> {
         Some(path)
     })();
 
-    let test_id = path.map_or_else(|| TestId::Name(def_name.to_smol_str()), TestId::Path);
+    let test_id =
+        path.map_or_else(|| TestId::Name(def_name.display_no_db().to_smolstr()), TestId::Path);
 
     let mut nav = match def {
         Definition::Module(def) => NavigationTarget::from_module_to_decl(db, def),
diff --git a/crates/ide/src/signature_help.rs b/crates/ide/src/signature_help.rs
index c5eaacdb10..fe6688c053 100644
--- a/crates/ide/src/signature_help.rs
+++ b/crates/ide/src/signature_help.rs
@@ -19,7 +19,7 @@ use syntax::{
     algo,
     ast::{self, AstChildren, HasArgList},
     match_ast, AstNode, Direction, NodeOrToken, SyntaxElementChildren, SyntaxNode, SyntaxToken,
-    TextRange, TextSize, T,
+    TextRange, TextSize, ToSmolStr, T,
 };
 
 use crate::RootDatabase;
@@ -379,7 +379,7 @@ fn add_assoc_type_bindings(
 
     for item in tr.items_with_supertraits(db) {
         if let AssocItem::TypeAlias(ty) = item {
-            let name = ty.name(db).to_smol_str();
+            let name = ty.name(db).display_no_db().to_smolstr();
             if !present_bindings.contains(&*name) {
                 buf.clear();
                 format_to!(buf, "{} = …", name);
diff --git a/crates/ide/src/syntax_highlighting/inject.rs b/crates/ide/src/syntax_highlighting/inject.rs
index f9b8a22a3c..c80bb7413f 100644
--- a/crates/ide/src/syntax_highlighting/inject.rs
+++ b/crates/ide/src/syntax_highlighting/inject.rs
@@ -3,7 +3,7 @@
 use std::mem;
 
 use either::Either;
-use hir::{InFile, Semantics};
+use hir::{sym, InFile, Semantics};
 use ide_db::{
     active_parameter::ActiveParameter, base_db::FileId, defs::Definition,
     documentation::docs_with_rangemap, rust_doc::is_rust_fence, SymbolKind,
@@ -153,7 +153,7 @@ pub(super) fn doc_comment(
     let mut new_comments = Vec::new();
     let mut string;
 
-    for attr in attributes.by_key("doc").attrs() {
+    for attr in attributes.by_key(&sym::doc).attrs() {
         let InFile { file_id, value: src } = attrs_source_map.source_of(attr);
         if file_id != src_file_id {
             continue;
@@ -271,7 +271,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
         // #[cfg_attr(..., doc = "", ...)]
         None => {
             // We gotta hunt the string token manually here
-            let text = attr.string_value()?;
+            let text = attr.string_value()?.as_str();
             // FIXME: We just pick the first string literal that has the same text as the doc attribute
             // This means technically we might highlight the wrong one
             it.syntax()
diff --git a/crates/intern/src/symbol/symbols.rs b/crates/intern/src/symbol/symbols.rs
index 04c70e4fae..1454d825b7 100644
--- a/crates/intern/src/symbol/symbols.rs
+++ b/crates/intern/src/symbol/symbols.rs
@@ -12,7 +12,7 @@ use crate::{
 };
 
 macro_rules! define_symbols {
-    (@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => {
+    (@WITH_NAME: $($alias:ident = $value:literal,)* @PLAIN: $($name:ident,)*) => {
         // Ideally we would be emitting `const` here, but then we no longer have stable addresses
         // which is what we are relying on for equality! In the future if consts can refer to
         // statics we should swap these for `const`s and have the the string literal being pointed
@@ -56,15 +56,6 @@ macro_rules! define_symbols {
 define_symbols! {
     @WITH_NAME:
 
-    __empty = "",
-    unsafe_ = "unsafe",
-    in_ = "in",
-    super_ = "super",
-    self_ = "self",
-    Self_ = "Self",
-    tick_static = "'static",
-    dollar_crate = "$crate",
-    MISSING_NAME = "[missing name]",
     INTEGER_0 = "0",
     INTEGER_1 = "1",
     INTEGER_2 = "2",
@@ -81,6 +72,15 @@ define_symbols! {
     INTEGER_13 = "13",
     INTEGER_14 = "14",
     INTEGER_15 = "15",
+    __empty = "",
+    unsafe_ = "unsafe",
+    in_ = "in",
+    super_ = "super",
+    self_ = "self",
+    Self_ = "Self",
+    tick_static = "'static",
+    dollar_crate = "$crate",
+    MISSING_NAME = "[missing name]",
     fn_ = "fn",
     crate_ = "crate",
     underscore = "_",
@@ -88,16 +88,43 @@ define_symbols! {
     false_ = "false",
     let_ = "let",
     const_ = "const",
+    proc_dash_macro = "proc-macro",
+    aapcs_dash_unwind = "aapcs-unwind",
+    avr_dash_interrupt = "avr-interrupt",
+    avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt",
+    C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call",
+    C_dash_unwind = "C-unwind",
+    cdecl_dash_unwind = "cdecl-unwind",
+    fastcall_dash_unwind = "fastcall-unwind",
+    msp430_dash_interrupt = "msp430-interrupt",
+    platform_dash_intrinsic = "platform-intrinsic",
+    ptx_dash_kernel = "ptx-kernel",
+    riscv_dash_interrupt_dash_m = "riscv-interrupt-m",
+    riscv_dash_interrupt_dash_s = "riscv-interrupt-s",
+    rust_dash_call = "rust-call",
+    rust_dash_cold = "rust-cold",
+    rust_dash_intrinsic = "rust-intrinsic",
+    stdcall_dash_unwind = "stdcall-unwind",
+    system_dash_unwind = "system-unwind",
+    sysv64_dash_unwind = "sysv64-unwind",
+    thiscall_dash_unwind = "thiscall-unwind",
+    vectorcall_dash_unwind = "vectorcall-unwind",
+    win64_dash_unwind = "win64-unwind",
+    x86_dash_interrupt = "x86-interrupt",
 
     @PLAIN:
     __ra_fixup,
+    aapcs,
     add_assign,
     add,
+    alias,
     align_offset,
     align,
     all,
     alloc_layout,
     alloc,
+    allow_internal_unsafe,
+    allow,
     any,
     as_str,
     asm,
@@ -122,6 +149,7 @@ define_symbols! {
     call_mut,
     call_once,
     call,
+    cdecl,
     Center,
     cfg_accessible,
     cfg_attr,
@@ -154,6 +182,7 @@ define_symbols! {
     Debug,
     default,
     Default,
+    deprecated,
     deref_mut,
     deref_target,
     deref,
@@ -168,6 +197,7 @@ define_symbols! {
     drop_in_place,
     drop,
     dyn_metadata,
+    efiapi,
     eh_catch_typeinfo,
     eh_personality,
     env,
@@ -176,10 +206,12 @@ define_symbols! {
     Err,
     exchange_malloc,
     exhaustive_patterns,
+    export_name,
     f128,
     f16,
     f32,
     f64,
+    fastcall,
     feature,
     file,
     filter_map,
@@ -203,6 +235,7 @@ define_symbols! {
     from_residual,
     from_usize,
     from_yeet,
+    fundamental,
     future_trait,
     future,
     Future,
@@ -213,6 +246,7 @@ define_symbols! {
     gt,
     Hash,
     hidden,
+    html_root_url,
     i128,
     i16,
     i32,
@@ -238,6 +272,8 @@ define_symbols! {
     iter_mut,
     iter,
     Iterator,
+    keyword,
+    lang,
     le,
     Left,
     len,
@@ -246,8 +282,12 @@ define_symbols! {
     local_inner_macros,
     log_syntax,
     lt,
+    macro_export,
     macro_rules,
+    macro_use,
+    main,
     manually_drop,
+    may_dangle,
     maybe_uninit,
     metadata_type,
     min_exhaustive_patterns,
@@ -273,7 +313,9 @@ define_symbols! {
     new,
     next,
     no_core,
+    no_mangle,
     no_std,
+    non_exhaustive,
     none,
     None,
     not,
@@ -305,6 +347,7 @@ define_symbols! {
     partial_ord,
     PartialEq,
     PartialOrd,
+    path,
     Pending,
     phantom_data,
     pieces,
@@ -313,7 +356,11 @@ define_symbols! {
     pointer_like,
     poll,
     Poll,
+    prelude_import,
     prelude,
+    proc_macro_attribute,
+    proc_macro_derive,
+    proc_macro,
     quote,
     range_inclusive_new,
     Range,
@@ -329,6 +376,7 @@ define_symbols! {
     register_tool,
     rem_assign,
     rem,
+    repr,
     result,
     Result,
     ResumeTy,
@@ -338,8 +386,20 @@ define_symbols! {
     rust_2021,
     rust_2024,
     rust_analyzer,
+    Rust,
+    rustc_allow_incoherent_impl,
+    rustc_builtin_macro,
     rustc_coherence_is_core,
+    rustc_const_panic_str,
+    rustc_deprecated_safe_2024,
+    rustc_has_incoherent_inherent_impls,
+    rustc_layout_scalar_valid_range_end,
+    rustc_layout_scalar_valid_range_start,
+    rustc_legacy_const_generics,
     rustc_macro_transparency,
+    rustc_reservation_impl,
+    rustc_safe_intrinsic,
+    rustc_skip_array_during_method_dispatch,
     semitransparent,
     shl_assign,
     shl,
@@ -352,6 +412,7 @@ define_symbols! {
     start,
     std_panic,
     std,
+    stdcall,
     str,
     string,
     String,
@@ -361,10 +422,13 @@ define_symbols! {
     sub_assign,
     sub,
     sync,
+    system,
+    sysv64,
     Target,
     termination,
     test_case,
     test,
+    thiscall,
     trace_macros,
     transmute_opts,
     transmute_trait,
@@ -376,6 +440,7 @@ define_symbols! {
     u32,
     u64,
     u8,
+    unadjusted,
     Unknown,
     unpin,
     unreachable_2015,
@@ -383,7 +448,11 @@ define_symbols! {
     unreachable,
     unsafe_cell,
     unsize,
+    unstable,
     usize,
     v1,
-    va_list
+    va_list,
+    vectorcall,
+    wasm,
+    win64,
 }
diff --git a/crates/load-cargo/Cargo.toml b/crates/load-cargo/Cargo.toml
index b6f90ec53b..64ed93bbb1 100644
--- a/crates/load-cargo/Cargo.toml
+++ b/crates/load-cargo/Cargo.toml
@@ -27,6 +27,7 @@ span.workspace = true
 tt.workspace = true
 vfs-notify.workspace = true
 vfs.workspace = true
+intern.workspace = true
 
 [features]
 in-rust-tree = ["hir-expand/in-rust-tree"]
diff --git a/crates/load-cargo/src/lib.rs b/crates/load-cargo/src/lib.rs
index de68b86714..b7ddbc9665 100644
--- a/crates/load-cargo/src/lib.rs
+++ b/crates/load-cargo/src/lib.rs
@@ -428,14 +428,19 @@ fn expander_to_proc_macro(
     expander: proc_macro_api::ProcMacro,
     ignored_macros: &[Box<str>],
 ) -> ProcMacro {
-    let name = From::from(expander.name());
+    let name = expander.name();
     let kind = match expander.kind() {
         proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive,
         proc_macro_api::ProcMacroKind::Bang => ProcMacroKind::Bang,
         proc_macro_api::ProcMacroKind::Attr => ProcMacroKind::Attr,
     };
-    let disabled = ignored_macros.iter().any(|replace| **replace == name);
-    ProcMacro { name, kind, expander: sync::Arc::new(Expander(expander)), disabled }
+    let disabled = ignored_macros.iter().any(|replace| **replace == *name);
+    ProcMacro {
+        name: intern::Symbol::intern(name),
+        kind,
+        expander: sync::Arc::new(Expander(expander)),
+        disabled,
+    }
 }
 
 #[derive(Debug)]
diff --git a/crates/project-model/src/project_json.rs b/crates/project-model/src/project_json.rs
index 4a916e570b..4b55f9d2b9 100644
--- a/crates/project-model/src/project_json.rs
+++ b/crates/project-model/src/project_json.rs
@@ -224,6 +224,7 @@ impl ProjectJson {
                     Crate {
                         display_name: crate_data
                             .display_name
+                            .as_deref()
                             .map(CrateDisplayName::from_canonical_name),
                         root_module,
                         edition: crate_data.edition.into(),
diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs
index e006b70362..dd7a11ca85 100644
--- a/crates/project-model/src/workspace.rs
+++ b/crates/project-model/src/workspace.rs
@@ -894,7 +894,10 @@ fn project_json_to_crate_graph(
                     .collect();
                 override_cfg.apply(
                     &mut cfg_options,
-                    display_name.as_ref().map(|it| it.canonical_name()).unwrap_or_default(),
+                    display_name
+                        .as_ref()
+                        .map(|it| it.canonical_name().as_str())
+                        .unwrap_or_default(),
                 );
                 let crate_graph_crate_id = crate_graph.add_crate_root(
                     file_id,
@@ -917,7 +920,7 @@ fn project_json_to_crate_graph(
                 if *is_proc_macro {
                     if let Some(path) = proc_macro_dylib_path.clone() {
                         let node = Ok((
-                            display_name.as_ref().map(|it| it.canonical_name().to_owned()),
+                            display_name.as_ref().map(|it| it.canonical_name().as_str().to_owned()),
                             path,
                         ));
                         proc_macros.insert(crate_graph_crate_id, node);
@@ -1014,12 +1017,12 @@ fn cargo_to_crate_graph(
                 if pkg_data.is_local {
                     CrateOrigin::Local {
                         repo: pkg_data.repository.clone(),
-                        name: Some(pkg_data.name.clone()),
+                        name: Some(Symbol::intern(&pkg_data.name)),
                     }
                 } else {
                     CrateOrigin::Library {
                         repo: pkg_data.repository.clone(),
-                        name: pkg_data.name.clone(),
+                        name: Symbol::intern(&pkg_data.name),
                     }
                 },
             );
@@ -1157,9 +1160,7 @@ fn detached_file_to_crate_graph(
             return (crate_graph, FxHashMap::default());
         }
     };
-    let display_name = detached_file
-        .file_stem()
-        .map(|file_stem| CrateDisplayName::from_canonical_name(file_stem.to_owned()));
+    let display_name = detached_file.file_stem().map(CrateDisplayName::from_canonical_name);
     let detached_file_crate = crate_graph.add_crate_root(
         file_id,
         Edition::CURRENT,
@@ -1232,7 +1233,7 @@ fn handle_rustc_crates(
                         file_id,
                         &rustc_workspace[tgt].name,
                         kind,
-                        CrateOrigin::Rustc { name: rustc_workspace[pkg].name.clone() },
+                        CrateOrigin::Rustc { name: Symbol::intern(&rustc_workspace[pkg].name) },
                     );
                     pkg_to_lib_crate.insert(pkg, crate_id);
                     // Add dependencies on core / std / alloc for this crate
@@ -1329,7 +1330,7 @@ fn add_target_crate_root(
     let crate_id = crate_graph.add_crate_root(
         file_id,
         edition,
-        Some(CrateDisplayName::from_canonical_name(cargo_name.to_owned())),
+        Some(CrateDisplayName::from_canonical_name(cargo_name)),
         Some(pkg.version.to_string()),
         Arc::new(cfg_options),
         potential_cfg_options.map(Arc::new),
@@ -1402,7 +1403,7 @@ fn sysroot_to_crate_graph(
                 // patch the origin
                 if c.origin.is_local() {
                     let lang_crate = LangCrateOrigin::from(
-                        c.display_name.as_ref().map_or("", |it| it.canonical_name()),
+                        c.display_name.as_ref().map_or("", |it| it.canonical_name().as_str()),
                     );
                     c.origin = CrateOrigin::Lang(lang_crate);
                     match lang_crate {
@@ -1459,8 +1460,7 @@ fn sysroot_to_crate_graph(
                 .filter_map(|krate| {
                     let file_id = load(&stitched[krate].root)?;
 
-                    let display_name =
-                        CrateDisplayName::from_canonical_name(stitched[krate].name.clone());
+                    let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
                     let crate_id = crate_graph.add_crate_root(
                         file_id,
                         Edition::CURRENT,
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 90316f3b89..a0f1c941dd 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -621,7 +621,7 @@ impl flags::AnalysisStats {
                 module
                     .krate()
                     .display_name(db)
-                    .map(|it| it.canonical_name().to_owned())
+                    .map(|it| it.canonical_name().as_str().to_owned())
                     .into_iter()
                     .chain(
                         module
@@ -912,7 +912,7 @@ impl flags::AnalysisStats {
                 module
                     .krate()
                     .display_name(db)
-                    .map(|it| it.canonical_name().to_owned())
+                    .map(|it| it.canonical_name().as_str().to_owned())
                     .into_iter()
                     .chain(
                         module
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 177f48b986..abff16b6f5 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -65,7 +65,7 @@ pub use rowan::{
     TokenAtOffset, WalkEvent,
 };
 pub use rustc_lexer::unescape;
-pub use smol_str::{format_smolstr, SmolStr};
+pub use smol_str::{format_smolstr, SmolStr, ToSmolStr};
 
 /// `Parse` is the result of the parsing: a syntax tree and a collection of
 /// errors.


Test patch:
diff --git a/crates/hir-def/src/macro_expansion_tests/mod.rs b/crates/hir-def/src/macro_expansion_tests/mod.rs
index dc964b3c9a..b6c6e4b397 100644
--- a/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -24,6 +24,7 @@ use hir_expand::{
     span_map::SpanMapRef,
     InFile, MacroFileId, MacroFileIdExt,
 };
+use intern::Symbol;
 use span::Span;
 use stdx::{format_to, format_to_acc};
 use syntax::{
@@ -55,7 +56,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
 "#
         .into(),
         ProcMacro {
-            name: "identity_when_valid".into(),
+            name: Symbol::intern("identity_when_valid"),
             kind: ProcMacroKind::Attr,
             expander: sync::Arc::new(IdentityWhenValidProcMacroExpander),
             disabled: false,
diff --git a/crates/hir-ty/src/layout/tests.rs b/crates/hir-ty/src/layout/tests.rs
index 35ea13eb11..e2ddb1bb22 100644
--- a/crates/hir-ty/src/layout/tests.rs
+++ b/crates/hir-ty/src/layout/tests.rs
@@ -3,6 +3,7 @@ use either::Either;
 use hir_def::db::DefDatabase;
 use project_model::{target_data_layout::RustcDataLayoutConfig, Sysroot};
 use rustc_hash::FxHashMap;
+use syntax::ToSmolStr;
 use test_fixture::WithFixture;
 use triomphe::Arc;
 
@@ -40,14 +41,20 @@ fn eval_goal(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
             let adt_or_type_alias_id = scope.declarations().find_map(|x| match x {
                 hir_def::ModuleDefId::AdtId(x) => {
                     let name = match x {
-                        hir_def::AdtId::StructId(x) => db.struct_data(x).name.to_smol_str(),
-                        hir_def::AdtId::UnionId(x) => db.union_data(x).name.to_smol_str(),
-                        hir_def::AdtId::EnumId(x) => db.enum_data(x).name.to_smol_str(),
+                        hir_def::AdtId::StructId(x) => {
+                            db.struct_data(x).name.display_no_db().to_smolstr()
+                        }
+                        hir_def::AdtId::UnionId(x) => {
+                            db.union_data(x).name.display_no_db().to_smolstr()
+                        }
+                        hir_def::AdtId::EnumId(x) => {
+                            db.enum_data(x).name.display_no_db().to_smolstr()
+                        }
                     };
                     (name == "Goal").then_some(Either::Left(x))
                 }
                 hir_def::ModuleDefId::TypeAliasId(x) => {
-                    let name = db.type_alias_data(x).name.to_smol_str();
+                    let name = db.type_alias_data(x).name.display_no_db().to_smolstr();
                     (name == "Goal").then_some(Either::Right(x))
                 }
                 _ => None,
@@ -87,14 +94,19 @@ fn eval_expr(ra_fixture: &str, minicore: &str) -> Result<Arc<Layout>, LayoutErro
         .declarations()
         .find_map(|x| match x {
             hir_def::ModuleDefId::FunctionId(x) => {
-                let name = db.function_data(x).name.to_smol_str();
+                let name = db.function_data(x).name.display_no_db().to_smolstr();
                 (name == "main").then_some(x)
             }
             _ => None,
         })
         .unwrap();
     let hir_body = db.body(function_id.into());
-    let b = hir_body.bindings.iter().find(|x| x.1.name.to_smol_str() == "goal").unwrap().0;
+    let b = hir_body
+        .bindings
+        .iter()
+        .find(|x| x.1.name.display_no_db().to_smolstr() == "goal")
+        .unwrap()
+        .0;
     let infer = db.infer(function_id.into());
     let goal_ty = infer.type_of_binding[b].clone();
     db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
diff --git a/crates/test-fixture/src/lib.rs b/crates/test-fixture/src/lib.rs
index e910094c77..d9f9fb82be 100644
--- a/crates/test-fixture/src/lib.rs
+++ b/crates/test-fixture/src/lib.rs
@@ -267,7 +267,7 @@ impl ChangeFixture {
             let core_crate = crate_graph.add_crate_root(
                 core_file,
                 Edition::CURRENT,
-                Some(CrateDisplayName::from_canonical_name("core".to_owned())),
+                Some(CrateDisplayName::from_canonical_name("core")),
                 None,
                 Default::default(),
                 Default::default(),
@@ -314,7 +314,7 @@ impl ChangeFixture {
             let proc_macros_crate = crate_graph.add_crate_root(
                 proc_lib_file,
                 Edition::CURRENT,
-                Some(CrateDisplayName::from_canonical_name("proc_macros".to_owned())),
+                Some(CrateDisplayName::from_canonical_name("proc_macros")),
                 None,
                 Default::default(),
                 Default::default(),
@@ -370,7 +370,7 @@ pub fn identity(_attr: TokenStream, item: TokenStream) -> TokenStream {
 "#
             .into(),
             ProcMacro {
-                name: "identity".into(),
+                name: Symbol::intern("identity"),
                 kind: ProcMacroKind::Attr,
                 expander: sync::Arc::new(IdentityProcMacroExpander),
                 disabled: false,
@@ -385,7 +385,7 @@ pub fn derive_identity(item: TokenStream) -> TokenStream {
 "#
             .into(),
             ProcMacro {
-                name: "DeriveIdentity".into(),
+                name: Symbol::intern("DeriveIdentity"),
                 kind: ProcMacroKind::CustomDerive,
                 expander: sync::Arc::new(IdentityProcMacroExpander),
                 disabled: false,
@@ -400,7 +400,7 @@ pub fn input_replace(attr: TokenStream, _item: TokenStream) -> TokenStream {
 "#
             .into(),
             ProcMacro {
-                name: "input_replace".into(),
+                name: Symbol::intern("input_replace"),
                 kind: ProcMacroKind::Attr,
                 expander: sync::Arc::new(AttributeInputReplaceProcMacroExpander),
                 disabled: false,
@@ -415,7 +415,7 @@ pub fn mirror(input: TokenStream) -> TokenStream {
 "#
             .into(),
             ProcMacro {
-                name: "mirror".into(),
+                name: Symbol::intern("mirror"),
                 kind: ProcMacroKind::Bang,
                 expander: sync::Arc::new(MirrorProcMacroExpander),
                 disabled: false,
@@ -430,7 +430,7 @@ pub fn shorten(input: TokenStream) -> TokenStream {
 "#
             .into(),
             ProcMacro {
-                name: "shorten".into(),
+                name: Symbol::intern("shorten"),
                 kind: ProcMacroKind::Bang,
                 expander: sync::Arc::new(ShortenProcMacroExpander),
                 disabled: false,
@@ -448,7 +448,8 @@ fn filter_test_proc_macros(
     let mut proc_macros = Vec::new();
 
     for (c, p) in proc_macro_defs {
-        if !proc_macro_names.iter().any(|name| name == &stdx::to_lower_snake_case(&p.name)) {
+        if !proc_macro_names.iter().any(|name| name == &stdx::to_lower_snake_case(p.name.as_str()))
+        {
             continue;
         }
         proc_macros.push(p);
@@ -530,7 +531,7 @@ fn parse_crate(
 
     let origin = match LangCrateOrigin::from(&*name) {
         LangCrateOrigin::Other => {
-            let name = name.clone();
+            let name = Symbol::intern(&name);
             if non_workspace_member {
                 CrateOrigin::Library { repo, name }
             } else {