More symbol usage

This commit is contained in:
Lukas Wirth 2024-07-16 12:05:16 +02:00
parent c30bdfcc84
commit df5f1777b8
50 changed files with 388 additions and 303 deletions

1
Cargo.lock generated
View file

@ -70,6 +70,7 @@ name = "base-db"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"cfg", "cfg",
"intern",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lz4_flex", "lz4_flex",
"rustc-hash", "rustc-hash",

View file

@ -27,6 +27,7 @@ stdx.workspace = true
syntax.workspace = true syntax.workspace = true
vfs.workspace = true vfs.workspace = true
span.workspace = true span.workspace = true
intern.workspace = true
[lints] [lints]
workspace = true workspace = true

View file

@ -9,10 +9,10 @@
use std::{fmt, mem, ops}; use std::{fmt, mem, ops};
use cfg::CfgOptions; use cfg::CfgOptions;
use intern::Symbol;
use la_arena::{Arena, Idx, RawIdx}; use la_arena::{Arena, Idx, RawIdx};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::Edition; use span::Edition;
use syntax::SmolStr;
use triomphe::Arc; use triomphe::Arc;
use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath}; use vfs::{file_set::FileSet, AbsPathBuf, AnchoredPath, FileId, VfsPath};
@ -99,8 +99,8 @@ impl fmt::Debug for CrateGraph {
pub type CrateId = Idx<CrateData>; pub type CrateId = Idx<CrateData>;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CrateName(SmolStr); pub struct CrateName(Symbol);
impl CrateName { impl CrateName {
/// Creates a crate name, checking for dashes in the string provided. /// Creates a crate name, checking for dashes in the string provided.
@ -110,16 +110,16 @@ impl CrateName {
if name.contains('-') { if name.contains('-') {
Err(name) Err(name)
} else { } else {
Ok(Self(SmolStr::new(name))) Ok(Self(Symbol::intern(name)))
} }
} }
/// Creates a crate name, unconditionally replacing the dashes with underscores. /// Creates a crate name, unconditionally replacing the dashes with underscores.
pub fn normalize_dashes(name: &str) -> CrateName { 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 &self.0
} }
} }
@ -133,7 +133,7 @@ impl fmt::Display for CrateName {
impl ops::Deref for CrateName { impl ops::Deref for CrateName {
type Target = str; type Target = str;
fn deref(&self) -> &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)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum CrateOrigin { pub enum CrateOrigin {
/// Crates that are from the rustc workspace. /// Crates that are from the rustc workspace.
Rustc { name: String }, Rustc { name: Symbol },
/// Crates that are workspace members. /// 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. /// 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, ... /// Crates that are provided by the language, like std, core, proc-macro, ...
Lang(LangCrateOrigin), 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 { pub struct CrateDisplayName {
// The name we use to display various paths (with `_`). // The name we use to display various paths (with `_`).
crate_name: CrateName, crate_name: CrateName,
// The name as specified in Cargo.toml (with `-`). // The name as specified in Cargo.toml (with `-`).
canonical_name: String, canonical_name: Symbol,
} }
impl CrateDisplayName { impl CrateDisplayName {
pub fn canonical_name(&self) -> &str { pub fn canonical_name(&self) -> &Symbol {
&self.canonical_name &self.canonical_name
} }
pub fn crate_name(&self) -> &CrateName { pub fn crate_name(&self) -> &CrateName {
@ -220,7 +220,7 @@ impl CrateDisplayName {
impl From<CrateName> for CrateDisplayName { impl From<CrateName> for CrateDisplayName {
fn from(crate_name: CrateName) -> 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 } CrateDisplayName { crate_name, canonical_name }
} }
} }
@ -239,9 +239,9 @@ impl ops::Deref for CrateDisplayName {
} }
impl CrateDisplayName { impl CrateDisplayName {
pub fn from_canonical_name(canonical_name: String) -> CrateDisplayName { pub fn from_canonical_name(canonical_name: &str) -> CrateDisplayName {
let crate_name = CrateName::normalize_dashes(&canonical_name); let crate_name = CrateName::normalize_dashes(canonical_name);
CrateDisplayName { crate_name, canonical_name } CrateDisplayName { crate_name, canonical_name: Symbol::intern(canonical_name) }
} }
} }

View file

@ -1,6 +1,6 @@
//! A higher level attributes based on TokenTree, with also some shortcuts. //! 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 base_db::CrateId;
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
@ -14,7 +14,7 @@ use la_arena::{ArenaMap, Idx, RawIdx};
use mbe::DelimiterKind; use mbe::DelimiterKind;
use syntax::{ use syntax::{
ast::{self, HasAttrs}, ast::{self, HasAttrs},
AstPtr, SmolStr, AstPtr,
}; };
use triomphe::Arc; use triomphe::Arc;
@ -121,12 +121,12 @@ impl Attrs {
} }
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 } AttrQuery { attrs: self, key }
} }
pub fn cfg(&self) -> Option<CfgExpr> { 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()?; let first = cfgs.next()?;
match cfgs.next() { match cfgs.next() {
Some(second) => { Some(second) => {
@ -138,7 +138,7 @@ impl Attrs {
} }
pub fn cfgs(&self) -> impl Iterator<Item = CfgExpr> + '_ { 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 { pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
@ -148,50 +148,50 @@ impl Attrs {
} }
} }
pub fn lang(&self) -> Option<&str> { pub fn lang(&self) -> Option<&Symbol> {
self.by_key("lang").string_value() self.by_key(&sym::lang).string_value()
} }
pub fn lang_item(&self) -> Option<LangItem> { 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 { 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 && tt.delimiter.kind == DelimiterKind::Parenthesis &&
matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden) matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::hidden)
}) })
} }
pub fn has_doc_notable_trait(&self) -> bool { 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 && tt.delimiter.kind == DelimiterKind::Parenthesis &&
matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.sym == sym::notable_trait) 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> + '_ { 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()) self.doc_exprs().flat_map(|doc_expr| doc_expr.aliases().to_vec())
} }
pub fn export_name(&self) -> Option<&str> { pub fn export_name(&self) -> Option<&Symbol> {
self.by_key("export_name").string_value() self.by_key(&sym::export_name).string_value()
} }
pub fn is_proc_macro(&self) -> bool { 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 { 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 { 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 { pub fn is_test(&self) -> bool {
@ -210,27 +210,27 @@ impl Attrs {
} }
pub fn is_ignore(&self) -> bool { pub fn is_ignore(&self) -> bool {
self.by_key("ignore").exists() self.by_key(&sym::ignore).exists()
} }
pub fn is_bench(&self) -> bool { pub fn is_bench(&self) -> bool {
self.by_key("bench").exists() self.by_key(&sym::bench).exists()
} }
pub fn is_unstable(&self) -> bool { 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 { pub enum DocAtom {
/// eg. `#[doc(hidden)]` /// eg. `#[doc(hidden)]`
Flag(SmolStr), Flag(Symbol),
/// eg. `#[doc(alias = "it")]` /// eg. `#[doc(alias = "it")]`
/// ///
/// Note that a key can have multiple values that are all considered "active" at the same time. /// 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")]`. /// 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)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
@ -239,7 +239,7 @@ pub enum DocExpr {
/// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]` /// eg. `#[doc(hidden)]`, `#[doc(alias = "x")]`
Atom(DocAtom), Atom(DocAtom),
/// eg. `#[doc(alias("x", "y"))]` /// eg. `#[doc(alias("x", "y"))]`
Alias(Vec<SmolStr>), Alias(Vec<Symbol>),
} }
impl From<DocAtom> for DocExpr { impl From<DocAtom> for DocExpr {
@ -253,9 +253,9 @@ impl DocExpr {
next_doc_expr(&mut tt.token_trees.iter()).unwrap_or(DocExpr::Invalid) next_doc_expr(&mut tt.token_trees.iter()).unwrap_or(DocExpr::Invalid)
} }
pub fn aliases(&self) -> &[SmolStr] { pub fn aliases(&self) -> &[Symbol] {
match self { 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) std::slice::from_ref(value)
} }
DocExpr::Alias(aliases) => aliases, 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() { let name = match it.next() {
None => return None, None => return None,
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) => ident.sym.clone(), 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();
it.next(); it.next();
// FIXME: escape? raw string? DocAtom::KeyValue { key: name, value: text.clone() }.into()
let value = SmolStr::new(text.as_str());
DocAtom::KeyValue { key: name.as_str().into(), value }.into()
} }
_ => return Some(DocExpr::Invalid), _ => 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)) => { Some(tt::TokenTree::Subtree(subtree)) => {
it.next(); it.next();
let subs = parse_comma_sep(subtree); let subs = parse_comma_sep(subtree);
match name.as_str() { match &name {
"alias" => DocExpr::Alias(subs), s if *s == sym::alias => DocExpr::Alias(subs),
_ => DocExpr::Invalid, _ => DocExpr::Invalid,
} }
} }
_ => DocAtom::Flag(name.as_str().into()).into(), _ => DocAtom::Flag(name).into(),
}; };
// Eat comma separator // Eat comma separator
@ -309,16 +307,16 @@ fn next_doc_expr<S>(it: &mut SliceIter<'_, tt::TokenTree<S>>) -> Option<DocExpr>
Some(ret) 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 subtree
.token_trees .token_trees
.iter() .iter()
.filter_map(|tt| match tt { .filter_map(|tt| match tt {
tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal {
kind: tt::LitKind::Str, kind: tt::LitKind::Str,
symbol: text, symbol,
.. ..
})) => Some(SmolStr::new(text.as_str())), })) => Some(symbol.clone()),
_ => None, _ => None,
}) })
.collect() .collect()
@ -565,7 +563,7 @@ impl AttrSourceMap {
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct AttrQuery<'attr> { pub struct AttrQuery<'attr> {
attrs: &'attr Attrs, attrs: &'attr Attrs,
key: &'static str, key: &'attr Symbol,
} }
impl<'attr> AttrQuery<'attr> { impl<'attr> AttrQuery<'attr> {
@ -573,11 +571,11 @@ impl<'attr> AttrQuery<'attr> {
self.attrs().filter_map(|attr| attr.token_tree_value()) 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()) 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()) 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 { pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
let key = self.key; let key = self.key;
self.attrs self.attrs.iter().filter(move |attr| attr.path.as_ident().map_or(false, |s| *s == *key))
.iter()
.filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_smol_str() == key))
} }
/// Find string value for a specific key inside token tree /// Find string value for a specific key inside token tree
@ -602,10 +598,10 @@ impl<'attr> AttrQuery<'attr> {
/// #[doc(html_root_url = "url")] /// #[doc(html_root_url = "url")]
/// ^^^^^^^^^^^^^ key /// ^^^^^^^^^^^^^ 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| { self.tt_values().find_map(|tt| {
let name = tt.token_trees.iter() 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); .nth(2);
match name { match name {
@ -660,6 +656,7 @@ mod tests {
//! This module contains tests for doc-expression parsing. //! This module contains tests for doc-expression parsing.
//! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`. //! Currently, it tests `#[doc(hidden)]` and `#[doc(alias)]`.
use intern::Symbol;
use triomphe::Arc; use triomphe::Arc;
use base_db::FileId; use base_db::FileId;
@ -685,24 +682,29 @@ mod tests {
#[test] #[test]
fn test_doc_expr_parser() { 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( assert_parse_result(
r#"#![doc(alias = "foo")]"#, 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( assert_parse_result(
r#"#![doc(alias("foo", "bar", "baz"))]"#, 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( assert_parse_result(
r#" r#"
#[doc(alias("Bar", "Qux"))] #[doc(alias("Bar", "Qux"))]
struct Foo;"#, struct Foo;"#,
DocExpr::Alias(["Bar".into(), "Qux".into()].into()), DocExpr::Alias([Symbol::intern("Bar"), Symbol::intern("Qux")].into()),
); );
} }
} }

View file

@ -8,7 +8,7 @@ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
ExpandError, InFile, ExpandError, InFile,
}; };
use intern::{sym, Interned}; use intern::{sym, Interned, Symbol};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::AstIdMap; use span::AstIdMap;
@ -1623,30 +1623,29 @@ impl ExprCollector<'_> {
} }
} }
let lit_pieces = let lit_pieces = fmt
fmt.template .template
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(i, piece)| { .filter_map(|(i, piece)| {
match piece { match piece {
FormatArgsPiece::Literal(s) => Some( FormatArgsPiece::Literal(s) => {
self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))), Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(s.clone()))))
), }
&FormatArgsPiece::Placeholder(_) => { &FormatArgsPiece::Placeholder(_) => {
// Inject empty string before placeholders when not already preceded by a literal piece. // Inject empty string before placeholders when not already preceded by a literal piece.
if i == 0 if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_))
|| matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
{ Some(self.alloc_expr_desugared(Expr::Literal(Literal::String(
Some(self.alloc_expr_desugared(Expr::Literal(Literal::String( Symbol::empty(),
"".into(), ))))
)))) } else {
} else { None
None
}
} }
} }
}) }
.collect(); })
.collect();
let lit_pieces = self.alloc_expr_desugared(Expr::Array(Array::ElementList { let lit_pieces = self.alloc_expr_desugared(Expr::Array(Array::ElementList {
elements: lit_pieces, elements: lit_pieces,
is_assignee_expr: false, is_assignee_expr: false,

View file

@ -338,7 +338,7 @@ mod tests {
let actual = scopes let actual = scopes
.scope_chain(scope) .scope_chain(scope)
.flat_map(|scope| scopes.entries(scope)) .flat_map(|scope| scopes.entries(scope))
.map(|it| it.name().to_smol_str()) .map(|it| it.name().as_str())
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("\n"); .join("\n");
let expected = expected.join("\n"); let expected = expected.join("\n");

View file

@ -6,7 +6,7 @@ use base_db::CrateId;
use hir_expand::{ use hir_expand::{
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind, name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
}; };
use intern::{sym, Interned}; use intern::{sym, Interned, Symbol};
use smallvec::SmallVec; use smallvec::SmallVec;
use syntax::{ast, Parse}; use syntax::{ast, Parse};
use triomphe::Arc; use triomphe::Arc;
@ -38,7 +38,7 @@ pub struct FunctionData {
pub ret_type: Interned<TypeRef>, pub ret_type: Interned<TypeRef>,
pub attrs: Attrs, pub attrs: Attrs,
pub visibility: RawVisibility, pub visibility: RawVisibility,
pub abi: Option<Interned<str>>, pub abi: Option<Symbol>,
pub legacy_const_generics_indices: Box<[u32]>, pub legacy_const_generics_indices: Box<[u32]>,
pub rustc_allow_incoherent_impl: bool, pub rustc_allow_incoherent_impl: bool,
flags: FnFlags, flags: FnFlags,
@ -92,12 +92,12 @@ impl FunctionData {
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()); let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let legacy_const_generics_indices = attrs let legacy_const_generics_indices = attrs
.by_key("rustc_legacy_const_generics") .by_key(&sym::rustc_legacy_const_generics)
.tt_values() .tt_values()
.next() .next()
.map(parse_rustc_legacy_const_generics) .map(parse_rustc_legacy_const_generics)
.unwrap_or_default(); .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 { Arc::new(FunctionData {
name: func.name.clone(), name: func.name.clone(),
@ -200,8 +200,8 @@ impl TypeAliasData {
ModItem::from(loc.id.value).into(), ModItem::from(loc.id.value).into(),
); );
let rustc_has_incoherent_inherent_impls = let rustc_has_incoherent_inherent_impls =
attrs.by_key("rustc_has_incoherent_inherent_impls").exists(); attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
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(TypeAliasData { Arc::new(TypeAliasData {
name: typ.name.clone(), name: typ.name.clone(),
@ -251,10 +251,10 @@ impl TraitData {
let visibility = item_tree[tr_def.visibility].clone(); let visibility = item_tree[tr_def.visibility].clone();
let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into()); let attrs = item_tree.attrs(db, module_id.krate(), ModItem::from(tree_id.value).into());
let skip_array_during_method_dispatch = 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 = let rustc_has_incoherent_inherent_impls =
attrs.by_key("rustc_has_incoherent_inherent_impls").exists(); attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists();
let fundamental = attrs.by_key("fundamental").exists(); let fundamental = attrs.by_key(&sym::fundamental).exists();
let mut collector = let mut collector =
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr)); AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items); collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
@ -393,7 +393,7 @@ impl Macro2Data {
let helpers = item_tree let helpers = item_tree
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
.by_key("rustc_builtin_macro") .by_key(&sym::rustc_builtin_macro)
.tt_values() .tt_values()
.next() .next()
.and_then(|attr| parse_macro_name_and_helper_attrs(&attr.token_trees)) .and_then(|attr| parse_macro_name_and_helper_attrs(&attr.token_trees))
@ -423,7 +423,7 @@ impl MacroRulesData {
let macro_export = item_tree let macro_export = item_tree
.attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into()) .attrs(db, loc.container.krate(), ModItem::from(loc.id.value).into())
.by_key("macro_export") .by_key(&sym::macro_export)
.exists(); .exists();
Arc::new(MacroRulesData { name: makro.name.clone(), macro_export }) Arc::new(MacroRulesData { name: makro.name.clone(), macro_export })
@ -526,7 +526,7 @@ impl ConstData {
let rustc_allow_incoherent_impl = item_tree let rustc_allow_incoherent_impl = item_tree
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into()) .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(); .exists();
Arc::new(ConstData { Arc::new(ConstData {

View file

@ -95,7 +95,7 @@ fn repr_from_value(
item_tree: &ItemTree, item_tree: &ItemTree,
of: AttrOwner, of: AttrOwner,
) -> Option<ReprOptions> { ) -> 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> { 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 attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let mut flags = StructFlags::NO_FLAGS; 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; 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; flags |= StructFlags::IS_FUNDAMENTAL;
} }
if let Some(lang) = attrs.lang_item() { 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 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 attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let mut flags = StructFlags::NO_FLAGS; 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; 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; 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 repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let rustc_has_incoherent_inherent_impls = item_tree let rustc_has_incoherent_inherent_impls = item_tree
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into()) .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(); .exists();
let enum_ = &item_tree[loc.id.value]; let enum_ = &item_tree[loc.id.value];

View file

@ -18,7 +18,7 @@ pub mod type_ref;
use std::fmt; use std::fmt;
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::Interned; use intern::{Interned, Symbol};
use la_arena::{Idx, RawIdx}; use la_arena::{Idx, RawIdx};
use rustc_apfloat::ieee::{Half as f16, Quad as f128}; use rustc_apfloat::ieee::{Half as f16, Quad as f128};
use smallvec::SmallVec; use smallvec::SmallVec;
@ -60,41 +60,41 @@ pub type LabelId = Idx<Label>;
// We leave float values as a string to avoid double rounding. // We leave float values as a string to avoid double rounding.
// For PartialEq, string comparison should work, as ordering is not important // For PartialEq, string comparison should work, as ordering is not important
// https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360 // https://github.com/rust-lang/rust-analyzer/issues/12380#issuecomment-1137284360
#[derive(Default, Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct FloatTypeWrapper(Box<str>); pub struct FloatTypeWrapper(Symbol);
// FIXME(#17451): Use builtin types once stabilised. // FIXME(#17451): Use builtin types once stabilised.
impl FloatTypeWrapper { impl FloatTypeWrapper {
pub fn new(value: String) -> Self { pub fn new(sym: Symbol) -> Self {
Self(value.into()) Self(sym)
} }
pub fn to_f128(&self) -> f128 { 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 { 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 { 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 { 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 { impl fmt::Display for FloatTypeWrapper {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum Literal { pub enum Literal {
String(Box<str>), String(Symbol),
ByteString(Box<[u8]>), ByteString(Box<[u8]>),
CString(Box<[u8]>), CString(Box<[u8]>),
Char(char), Char(char),
@ -130,7 +130,10 @@ impl From<ast::LiteralKind> for Literal {
match ast_lit_kind { match ast_lit_kind {
LiteralKind::IntNumber(lit) => { LiteralKind::IntNumber(lit) => {
if let builtin @ Some(_) = lit.suffix().and_then(BuiltinFloat::from_suffix) { 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) { } else if let builtin @ Some(_) = lit.suffix().and_then(BuiltinUint::from_suffix) {
Literal::Uint(lit.value().unwrap_or(0), builtin) Literal::Uint(lit.value().unwrap_or(0), builtin)
} else { } else {
@ -140,14 +143,14 @@ impl From<ast::LiteralKind> for Literal {
} }
LiteralKind::FloatNumber(lit) => { LiteralKind::FloatNumber(lit) => {
let ty = lit.suffix().and_then(BuiltinFloat::from_suffix); 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) => { LiteralKind::ByteString(bs) => {
let text = bs.value().map_or_else(|_| Default::default(), Box::from); let text = bs.value().map_or_else(|_| Default::default(), Box::from);
Literal::ByteString(text) Literal::ByteString(text)
} }
LiteralKind::String(s) => { 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) Literal::String(text)
} }
LiteralKind::CString(s) => { LiteralKind::CString(s) => {

View file

@ -1,7 +1,7 @@
//! Parses `format_args` input. //! Parses `format_args` input.
use std::mem;
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::Symbol;
use rustc_parse_format as parse; use rustc_parse_format as parse;
use span::SyntaxContextId; use span::SyntaxContextId;
use stdx::TupleExt; use stdx::TupleExt;
@ -29,7 +29,7 @@ pub struct FormatArguments {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum FormatArgsPiece { pub enum FormatArgsPiece {
Literal(Box<str>), Literal(Symbol),
Placeholder(FormatPlaceholder), Placeholder(FormatPlaceholder),
} }
@ -291,9 +291,8 @@ pub(crate) fn parse(
parse::Piece::NextArgument(arg) => { parse::Piece::NextArgument(arg) => {
let parse::Argument { position, position_span, format } = *arg; let parse::Argument { position, position_span, format } = *arg;
if !unfinished_literal.is_empty() { if !unfinished_literal.is_empty() {
template.push(FormatArgsPiece::Literal( template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
mem::take(&mut unfinished_literal).into_boxed_str(), unfinished_literal.clear();
));
} }
let span = parser.arg_places.get(placeholder_index).and_then(|&s| to_span(s)); 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() { 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() { if !invalid_refs.is_empty() {

View file

@ -9,7 +9,7 @@ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
AstId, AstId,
}; };
use intern::Interned; use intern::{sym, Interned, Symbol};
use syntax::ast::{self, HasGenericArgs, HasName, IsString}; use syntax::ast::{self, HasGenericArgs, HasName, IsString};
use crate::{ use crate::{
@ -122,9 +122,9 @@ pub enum TypeRef {
/// A fn pointer. Last element of the vector is the return type. /// A fn pointer. Last element of the vector is the return type.
Fn( Fn(
Vec<(Option<Name>, TypeRef)>, Vec<(Option<Name>, TypeRef)>,
bool, /*varargs*/ bool, /*varargs*/
bool, /*is_unsafe*/ bool, /*is_unsafe*/
Option<Interned<str>>, /* abi */ Option<Symbol>, /* abi */
), ),
ImplTrait(Vec<Interned<TypeBound>>), ImplTrait(Vec<Interned<TypeBound>>),
DynTrait(Vec<Interned<TypeBound>>), DynTrait(Vec<Interned<TypeBound>>),
@ -230,11 +230,11 @@ impl TypeRef {
} else { } else {
Vec::new() Vec::new()
}; };
fn lower_abi(abi: ast::Abi) -> Interned<str> { fn lower_abi(abi: ast::Abi) -> Symbol {
match abi.abi_string() { 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"`. // `extern` default to be `extern "C"`.
_ => Interned::new_str("C"), _ => sym::C.clone(),
} }
} }

View file

@ -46,7 +46,7 @@ use ast::{AstNode, StructKind};
use base_db::CrateId; use base_db::CrateId;
use either::Either; use either::Either;
use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile}; 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 la_arena::{Arena, Idx, IdxRange, RawIdx};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
@ -712,7 +712,7 @@ pub struct ExternCrate {
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub struct ExternBlock { pub struct ExternBlock {
pub abi: Option<Interned<str>>, pub abi: Option<Symbol>,
pub ast_id: FileAstId<ast::ExternBlock>, pub ast_id: FileAstId<ast::ExternBlock>,
pub children: Box<[ModItem]>, pub children: Box<[ModItem]>,
} }
@ -722,7 +722,7 @@ pub struct Function {
pub name: Name, pub name: Name,
pub visibility: RawVisibilityId, pub visibility: RawVisibilityId,
pub explicit_generic_params: Interned<GenericParams>, pub explicit_generic_params: Interned<GenericParams>,
pub abi: Option<Interned<str>>, pub abi: Option<Symbol>,
pub params: IdxRange<Param>, pub params: IdxRange<Param>,
pub ret_type: Interned<TypeRef>, pub ret_type: Interned<TypeRef>,
pub ast_id: FileAstId<ast::Fn>, pub ast_id: FileAstId<ast::Fn>,

View file

@ -3,7 +3,7 @@
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use hir_expand::{mod_path::path, name::AsName, span_map::SpanMapRef, HirFileId}; use hir_expand::{mod_path::path, name::AsName, span_map::SpanMapRef, HirFileId};
use intern::sym; use intern::{sym, Symbol};
use la_arena::Arena; use la_arena::Arena;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use span::{AstIdMap, SyntaxContextId}; use span::{AstIdMap, SyntaxContextId};
@ -766,11 +766,11 @@ enum HasImplicitSelf {
No, No,
} }
fn lower_abi(abi: ast::Abi) -> Interned<str> { fn lower_abi(abi: ast::Abi) -> Symbol {
match abi.abi_string() { 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"`. // `extern` default to be `extern "C"`.
_ => Interned::new_str("C"), _ => sym::C.clone(),
} }
} }

View file

@ -5,7 +5,6 @@
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::{sym, Symbol}; use intern::{sym, Symbol};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use syntax::SmolStr;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
@ -253,9 +252,9 @@ macro_rules! language_item_table {
} }
impl LangItem { impl LangItem {
pub fn name(self) -> SmolStr { pub fn name(self) -> &'static str {
match self { match self {
$( LangItem::$variant => SmolStr::new(stringify!($name)), )* $( LangItem::$variant => stringify!($name), )*
} }
} }

View file

@ -296,13 +296,13 @@ impl DefCollector<'_> {
match () { match () {
() if *attr_name == sym::recursion_limit.clone() => { () if *attr_name == sym::recursion_limit.clone() => {
if let Some(limit) = attr.string_value() { 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); crate_data.recursion_limit = Some(limit);
} }
} }
} }
() if *attr_name == sym::crate_type.clone() => { () 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; self.is_proc_macro = true;
} }
} }
@ -1599,7 +1599,7 @@ impl ModCollector<'_, '_> {
id: ItemTreeId::new(self.tree_id, item_tree_id), id: ItemTreeId::new(self.tree_id, item_tree_id),
} }
.intern(db); .intern(db);
let is_prelude = attrs.by_key("prelude_import").exists(); let is_prelude = attrs.by_key(&sym::prelude_import).exists();
Import::from_use( Import::from_use(
self.item_tree, self.item_tree,
ItemTreeId::new(self.tree_id, item_tree_id), ItemTreeId::new(self.tree_id, item_tree_id),
@ -1624,7 +1624,7 @@ impl ModCollector<'_, '_> {
self.process_macro_use_extern_crate( self.process_macro_use_extern_crate(
item_tree_id, item_tree_id,
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) { fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
let path_attr = attrs.by_key("path").string_value_unescape(); let path_attr = attrs.by_key(&sym::path).string_value_unescape();
let is_macro_use = attrs.by_key("macro_use").exists(); let is_macro_use = attrs.by_key(&sym::macro_use).exists();
let module = &self.item_tree[module_id]; let module = &self.item_tree[module_id];
match &module.kind { match &module.kind {
// inline module, just recurse // inline module, just recurse
@ -1974,7 +1974,7 @@ impl ModCollector<'_, '_> {
let is_macro_use = is_macro_use let is_macro_use = is_macro_use
|| item_tree || item_tree
.top_level_attrs(db, krate) .top_level_attrs(db, krate)
.by_key("macro_use") .by_key(&sym::macro_use)
.exists(); .exists();
if is_macro_use { if is_macro_use {
self.import_all_legacy_macros(module_id); 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 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 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 is_export = export_attr.exists();
let local_inner = if is_export { let local_inner = if is_export {
@ -2137,17 +2137,17 @@ impl ModCollector<'_, '_> {
}; };
// Case 1: builtin macros // 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. // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
let 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)) => { Some((it, span)) => {
name = Name::new(it, tt::IdentIsRaw::No, span.ctx); name = Name::new_symbol(it.clone(), span.ctx);
&name &name
} }
None => { None => {
let explicit_name = 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() { match tt.token_trees.first() {
Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name), Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
_ => None, _ => None,
@ -2177,7 +2177,7 @@ impl ModCollector<'_, '_> {
// Case 2: normal `macro_rules!` macro // Case 2: normal `macro_rules!` macro
MacroExpander::Declarative 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(); let mut flags = MacroRulesLocFlags::empty();
flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner); flags.set(MacroRulesLocFlags::LOCAL_INNER, local_inner);
@ -2207,14 +2207,14 @@ impl ModCollector<'_, '_> {
// Case 1: builtin macros // Case 1: builtin macros
let mut helpers_opt = None; let mut helpers_opt = None;
let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); 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) { if let Some(expander) = find_builtin_macro(&mac.name) {
match expander { match expander {
Either::Left(it) => MacroExpander::BuiltIn(it), Either::Left(it) => MacroExpander::BuiltIn(it),
Either::Right(it) => MacroExpander::BuiltInEager(it), Either::Right(it) => MacroExpander::BuiltInEager(it),
} }
} else if let Some(expander) = find_builtin_derive(&mac.name) { } 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]`, // 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 // in which case rustc ignores the helper attributes from the latter, but it
// "doesn't make sense in practice" (see rust-lang/rust#87027). // "doesn't make sense in practice" (see rust-lang/rust#87027).
@ -2247,7 +2247,7 @@ impl ModCollector<'_, '_> {
// Case 2: normal `macro` // Case 2: normal `macro`
MacroExpander::Declarative 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 { let macro_id = Macro2Loc {
container: module, container: module,

View file

@ -36,8 +36,8 @@ impl Attrs {
Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Bang }) Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Bang })
} else if self.is_proc_macro_attribute() { } else if self.is_proc_macro_attribute() {
Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr }) Some(ProcMacroDef { name: func_name.clone(), kind: ProcMacroKind::Attr })
} else if self.by_key("proc_macro_derive").exists() { } else if self.by_key(&sym::proc_macro_derive).exists() {
let derive = self.by_key("proc_macro_derive").tt_values().next()?; let derive = self.by_key(&sym::proc_macro_derive).tt_values().next()?;
let def = parse_macro_name_and_helper_attrs(&derive.token_trees) let def = parse_macro_name_and_helper_attrs(&derive.token_trees)
.map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::Derive { helpers } }); .map(|(name, helpers)| ProcMacroDef { name, kind: ProcMacroKind::Derive { helpers } });

View file

@ -200,7 +200,7 @@ pub(crate) fn print_type_ref(
} }
if let Some(abi) = abi { if let Some(abi) = abi {
buf.write_str("extern ")?; buf.write_str("extern ")?;
buf.write_str(abi)?; buf.write_str(abi.as_str())?;
buf.write_char(' ')?; buf.write_char(' ')?;
} }
write!(buf, "fn(")?; write!(buf, "fn(")?;

View file

@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt, ops};
use base_db::CrateId; use base_db::CrateId;
use cfg::CfgExpr; use cfg::CfgExpr;
use either::Either; use either::Either;
use intern::{sym, Interned}; use intern::{sym, Interned, Symbol};
use mbe::{ use mbe::{
desugar_doc_comment_text, syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, desugar_doc_comment_text, syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode,
@ -310,26 +310,26 @@ impl Attr {
impl Attr { impl Attr {
/// #[path = "string"] /// #[path = "string"]
pub fn string_value(&self) -> Option<&str> { pub fn string_value(&self) -> Option<&Symbol> {
match self.input.as_deref()? { match self.input.as_deref()? {
AttrInput::Literal(tt::Literal { AttrInput::Literal(tt::Literal {
symbol: text, symbol: text,
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
.. ..
}) => Some(text.as_str()), }) => Some(text),
_ => None, _ => None,
} }
} }
/// #[path = "string"] /// #[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()? { match self.input.as_deref()? {
AttrInput::Literal(tt::Literal { AttrInput::Literal(tt::Literal {
symbol: text, symbol: text,
kind: tt::LitKind::Str | tt::LitKind::StrRaw(_), kind: tt::LitKind::Str | tt::LitKind::StrRaw(_),
span, span,
suffix: _, suffix: _,
}) => Some((text.as_str(), *span)), }) => Some((text, *span)),
_ => None, _ => None,
} }
} }

View file

@ -24,6 +24,7 @@ use hir_expand::{
name::{AsName, Name}, name::{AsName, Name},
HirFileId, MacroFileIdExt, HirFileId, MacroFileIdExt,
}; };
use intern::sym;
use stdx::{always, never}; use stdx::{always, never};
use syntax::{ use syntax::{
ast::{self, HasName}, ast::{self, HasName},
@ -163,8 +164,8 @@ impl<'a> DeclValidator<'a> {
let is_allowed = |def_id| { let is_allowed = |def_id| {
let attrs = self.db.attrs(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 // 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()) (!recursing && attrs.by_key(&sym::no_mangle).exists())
|| attrs.by_key("allow").tt_values().any(|tt| { || attrs.by_key(&sym::allow).tt_values().any(|tt| {
let allows = tt.to_string(); let allows = tt.to_string();
allows.contains(allow_name) allows.contains(allow_name)
|| allows.contains(allow::BAD_STYLE) || allows.contains(allow::BAD_STYLE)

View file

@ -101,7 +101,7 @@ impl<'db> MatchCheckCtx<'db> {
/// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`. /// Returns whether the given ADT is from another crate declared `#[non_exhaustive]`.
fn is_foreign_non_exhaustive(&self, adt: hir_def::AdtId) -> bool { fn is_foreign_non_exhaustive(&self, adt: hir_def::AdtId) -> bool {
let is_local = adt.krate(self.db.upcast()) == self.module.krate(); 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( fn variant_id_for_adt(

View file

@ -1935,7 +1935,7 @@ impl HirDisplay for TypeRef {
} }
if let Some(abi) = abi { if let Some(abi) = abi {
f.write_str("extern \"")?; f.write_str("extern \"")?;
f.write_str(abi)?; f.write_str(abi.as_str())?;
f.write_str("\" ")?; f.write_str("\" ")?;
} }
write!(f, "fn(")?; write!(f, "fn(")?;
@ -2044,7 +2044,7 @@ impl HirDisplay for Path {
.display_name .display_name
.as_ref() .as_ref()
.map(|name| name.canonical_name()) .map(|name| name.canonical_name())
.unwrap_or("$crate"); .unwrap_or(&sym::dollar_crate);
write!(f, "{name}")? write!(f, "{name}")?
} }
} }

View file

@ -6,6 +6,7 @@ use chalk_ir::{
DebruijnIndex, DebruijnIndex,
}; };
use hir_def::{visibility::Visibility, AdtId, EnumVariantId, HasModule, ModuleId, VariantId}; use hir_def::{visibility::Visibility, AdtId, EnumVariantId, HasModule, ModuleId, VariantId};
use intern::sym;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use crate::{ use crate::{
@ -118,7 +119,7 @@ impl UninhabitedFrom<'_> {
subst: &Substitution, subst: &Substitution,
) -> ControlFlow<VisiblyUninhabited> { ) -> ControlFlow<VisiblyUninhabited> {
let is_local = variant.krate(self.db.upcast()) == self.target_mod.krate(); 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; return CONTINUE_OPAQUELY_INHABITED;
} }

View file

@ -8,6 +8,7 @@ use hir_def::{
layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout}, layout::{Integer, LayoutCalculator, ReprOptions, TargetDataLayout},
AdtId, VariantId, AdtId, VariantId,
}; };
use intern::sym;
use rustc_index::IndexVec; use rustc_index::IndexVec;
use smallvec::SmallVec; use smallvec::SmallVec;
use triomphe::Arc; use triomphe::Arc;
@ -129,7 +130,10 @@ fn layout_scalar_valid_range(db: &dyn HirDatabase, def: AdtId) -> (Bound<u128>,
} }
Bound::Unbounded 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( pub fn layout_of_adt_recover(

View file

@ -62,7 +62,7 @@ use chalk_ir::{
use either::Either; use either::Either;
use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId}; use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::sym; use intern::{sym, Symbol};
use la_arena::{Arena, Idx}; use la_arena::{Arena, Idx};
use mir::{MirEvalError, VTableMap}; use mir::{MirEvalError, VTableMap};
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
@ -423,45 +423,45 @@ impl Hash for FnAbi {
} }
impl FnAbi { impl FnAbi {
#[allow(clippy::should_implement_trait)] #[rustfmt::skip]
pub fn from_str(s: &str) -> FnAbi { pub fn from_symbol(s: &Symbol) -> FnAbi {
match s { match s {
"aapcs-unwind" => FnAbi::AapcsUnwind, s if *s == sym::aapcs_dash_unwind => FnAbi::AapcsUnwind,
"aapcs" => FnAbi::Aapcs, s if *s == sym::aapcs => FnAbi::Aapcs,
"avr-interrupt" => FnAbi::AvrInterrupt, s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
"avr-non-blocking-interrupt" => FnAbi::AvrNonBlockingInterrupt, s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
"C-cmse-nonsecure-call" => FnAbi::CCmseNonsecureCall, s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
"C-unwind" => FnAbi::CUnwind, s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
"C" => FnAbi::C, s if *s == sym::C => FnAbi::C,
"cdecl-unwind" => FnAbi::CDeclUnwind, s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
"cdecl" => FnAbi::CDecl, s if *s == sym::cdecl => FnAbi::CDecl,
"efiapi" => FnAbi::Efiapi, s if *s == sym::efiapi => FnAbi::Efiapi,
"fastcall-unwind" => FnAbi::FastcallUnwind, s if *s == sym::fastcall_dash_unwind => FnAbi::FastcallUnwind,
"fastcall" => FnAbi::Fastcall, s if *s == sym::fastcall => FnAbi::Fastcall,
"msp430-interrupt" => FnAbi::Msp430Interrupt, s if *s == sym::msp430_dash_interrupt => FnAbi::Msp430Interrupt,
"platform-intrinsic" => FnAbi::PlatformIntrinsic, s if *s == sym::platform_dash_intrinsic => FnAbi::PlatformIntrinsic,
"ptx-kernel" => FnAbi::PtxKernel, s if *s == sym::ptx_dash_kernel => FnAbi::PtxKernel,
"riscv-interrupt-m" => FnAbi::RiscvInterruptM, s if *s == sym::riscv_dash_interrupt_dash_m => FnAbi::RiscvInterruptM,
"riscv-interrupt-s" => FnAbi::RiscvInterruptS, s if *s == sym::riscv_dash_interrupt_dash_s => FnAbi::RiscvInterruptS,
"rust-call" => FnAbi::RustCall, s if *s == sym::rust_dash_call => FnAbi::RustCall,
"rust-cold" => FnAbi::RustCold, s if *s == sym::rust_dash_cold => FnAbi::RustCold,
"rust-intrinsic" => FnAbi::RustIntrinsic, s if *s == sym::rust_dash_intrinsic => FnAbi::RustIntrinsic,
"Rust" => FnAbi::Rust, s if *s == sym::Rust => FnAbi::Rust,
"stdcall-unwind" => FnAbi::StdcallUnwind, s if *s == sym::stdcall_dash_unwind => FnAbi::StdcallUnwind,
"stdcall" => FnAbi::Stdcall, s if *s == sym::stdcall => FnAbi::Stdcall,
"system-unwind" => FnAbi::SystemUnwind, s if *s == sym::system_dash_unwind => FnAbi::SystemUnwind,
"system" => FnAbi::System, s if *s == sym::system => FnAbi::System,
"sysv64-unwind" => FnAbi::Sysv64Unwind, s if *s == sym::sysv64_dash_unwind => FnAbi::Sysv64Unwind,
"sysv64" => FnAbi::Sysv64, s if *s == sym::sysv64 => FnAbi::Sysv64,
"thiscall-unwind" => FnAbi::ThiscallUnwind, s if *s == sym::thiscall_dash_unwind => FnAbi::ThiscallUnwind,
"thiscall" => FnAbi::Thiscall, s if *s == sym::thiscall => FnAbi::Thiscall,
"unadjusted" => FnAbi::Unadjusted, s if *s == sym::unadjusted => FnAbi::Unadjusted,
"vectorcall-unwind" => FnAbi::VectorcallUnwind, s if *s == sym::vectorcall_dash_unwind => FnAbi::VectorcallUnwind,
"vectorcall" => FnAbi::Vectorcall, s if *s == sym::vectorcall => FnAbi::Vectorcall,
"wasm" => FnAbi::Wasm, s if *s == sym::wasm => FnAbi::Wasm,
"win64-unwind" => FnAbi::Win64Unwind, s if *s == sym::win64_dash_unwind => FnAbi::Win64Unwind,
"win64" => FnAbi::Win64, s if *s == sym::win64 => FnAbi::Win64,
"x86-interrupt" => FnAbi::X86Interrupt, s if *s == sym::x86_dash_interrupt => FnAbi::X86Interrupt,
_ => FnAbi::Unknown, _ => FnAbi::Unknown,
} }
} }

View file

@ -298,7 +298,7 @@ impl<'a> TyLoweringContext<'a> {
TyKind::Function(FnPointer { TyKind::Function(FnPointer {
num_binders: 0, // FIXME lower `for<'a> fn()` correctly num_binders: 0, // FIXME lower `for<'a> fn()` correctly
sig: FnSig { 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 }, safety: if is_unsafe { Safety::Unsafe } else { Safety::Safe },
variadic, variadic,
}, },
@ -1858,7 +1858,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
ret, ret,
data.is_varargs(), data.is_varargs(),
if data.has_unsafe_kw() { Safety::Unsafe } else { Safety::Safe }, 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) make_binders(db, &generics, sig)
} }

View file

@ -13,6 +13,7 @@ use hir_def::{
ModuleId, TraitId, ModuleId, TraitId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::sym;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use span::Edition; use span::Edition;
@ -200,7 +201,7 @@ impl TraitImpls {
// FIXME: Reservation impls should be considered during coherence checks. If we are // 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 // (ever) to implement coherence checks, this filtering should be done by the trait
// solver. // 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; continue;
} }
let target_trait = match db.impl_trait(impl_id) { let target_trait = match db.impl_trait(impl_id) {

View file

@ -15,7 +15,7 @@ use hir_def::{
StaticId, VariantId, StaticId, VariantId,
}; };
use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile}; use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile};
use intern::{sym, Interned}; use intern::sym;
use la_arena::ArenaMap; use la_arena::ArenaMap;
use rustc_abi::TargetDataLayout; use rustc_abi::TargetDataLayout;
use rustc_apfloat::{ use rustc_apfloat::{

View file

@ -15,9 +15,9 @@ use crate::{
error_lifetime, error_lifetime,
mir::eval::{ mir::eval::{
pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay, pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId,
ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Substitution,
Result, Substitution, Ty, TyBuilder, TyExt, Ty, TyBuilder, TyExt,
}, },
}; };
@ -54,12 +54,12 @@ impl Evaluator<'_> {
let function_data = self.db.function_data(def); let function_data = self.db.function_data(def);
let is_intrinsic = match &function_data.abi { 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 { None => match def.lookup(self.db.upcast()).container {
hir_def::ItemContainerId::ExternBlockId(block) => { hir_def::ItemContainerId::ExternBlockId(block) => {
let id = block.lookup(self.db.upcast()).id; let id = block.lookup(self.db.upcast()).id;
id.item_tree(self.db.upcast())[id.value].abi.as_deref() id.item_tree(self.db.upcast())[id.value].abi.as_ref()
== Some("rust-intrinsic") == Some(&sym::rust_dash_intrinsic)
} }
_ => false, _ => false,
}, },
@ -76,12 +76,12 @@ impl Evaluator<'_> {
return Ok(true); return Ok(true);
} }
let is_platform_intrinsic = match &function_data.abi { 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 { None => match def.lookup(self.db.upcast()).container {
hir_def::ItemContainerId::ExternBlockId(block) => { hir_def::ItemContainerId::ExternBlockId(block) => {
let id = block.lookup(self.db.upcast()).id; let id = block.lookup(self.db.upcast()).id;
id.item_tree(self.db.upcast())[id.value].abi.as_deref() id.item_tree(self.db.upcast())[id.value].abi.as_ref()
== Some("platform-intrinsic") == Some(&sym::platform_dash_intrinsic)
} }
_ => false, _ => false,
}, },
@ -100,7 +100,7 @@ impl Evaluator<'_> {
let is_extern_c = match def.lookup(self.db.upcast()).container { let is_extern_c = match def.lookup(self.db.upcast()).container {
hir_def::ItemContainerId::ExternBlockId(block) => { hir_def::ItemContainerId::ExternBlockId(block) => {
let id = block.lookup(self.db.upcast()).id; 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, _ => false,
}; };
@ -314,7 +314,7 @@ impl Evaluator<'_> {
use LangItem::*; use LangItem::*;
let attrs = self.db.attrs(def.into()); 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. // `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
return Some(LangItem::BeginPanic); return Some(LangItem::BeginPanic);
} }

View file

@ -1406,6 +1406,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
const USIZE_SIZE: usize = mem::size_of::<usize>(); const USIZE_SIZE: usize = mem::size_of::<usize>();
let bytes: Box<[_]> = match l { let bytes: Box<[_]> = match l {
hir_def::hir::Literal::String(b) => { hir_def::hir::Literal::String(b) => {
let b = b.as_str();
let mut data = [0; { 2 * USIZE_SIZE }]; let mut data = [0; { 2 * USIZE_SIZE }];
data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes()); data[..USIZE_SIZE].copy_from_slice(&0usize.to_le_bytes());
data[USIZE_SIZE..].copy_from_slice(&b.len().to_le_bytes()); data[USIZE_SIZE..].copy_from_slice(&b.len().to_le_bytes());

View file

@ -18,6 +18,7 @@ use hir_def::{
TypeOrConstParamId, TypeOrConstParamId,
}; };
use hir_expand::name::Name; use hir_expand::name::Name;
use intern::sym;
use rustc_abi::TargetDataLayout; use rustc_abi::TargetDataLayout;
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec}; 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); let data = db.function_data(func);
if data.has_unsafe_kw() { if data.has_unsafe_kw() {
// Functions that are `#[rustc_deprecated_safe_2024]` are safe to call before 2024. // 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. // FIXME: Properly check the caller span and mark it as unsafe after 2024.
return false; 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 id = block.lookup(db.upcast()).id;
let is_intrinsic = 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 { if is_intrinsic {
// Intrinsics are unsafe unless they have the rustc_safe_intrinsic attribute // 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 { } else {
// Extern items are always unsafe // Extern items are always unsafe
true true

View file

@ -82,8 +82,7 @@ impl HirDisplay for Function {
f.write_str("unsafe ")?; f.write_str("unsafe ")?;
} }
if let Some(abi) = &data.abi { if let Some(abi) = &data.abi {
// FIXME: String escape? write!(f, "extern \"{}\" ", abi.as_str())?;
write!(f, "extern \"{}\" ", &**abi)?;
} }
write!(f, "fn {}", data.name.display(f.db.upcast()))?; write!(f, "fn {}", data.name.display(f.db.upcast()))?;

View file

@ -259,7 +259,7 @@ impl Crate {
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> { pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
// Look for #![doc(html_root_url = "...")] // Look for #![doc(html_root_url = "...")]
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into())); 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() + "/") doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
} }
@ -677,9 +677,9 @@ impl Module {
TypeOrConstParamId { parent, local_id }, TypeOrConstParamId { parent, local_id },
)) ))
}); });
let res = type_params let res = type_params.chain(lifetime_params).any(|p| {
.chain(lifetime_params) db.attrs(AttrDefId::GenericParamId(p)).by_key(&sym::may_dangle).exists()
.any(|p| db.attrs(AttrDefId::GenericParamId(p)).by_key("may_dangle").exists()); });
Some(res) Some(res)
})() })()
.unwrap_or(false); .unwrap_or(false);
@ -2088,14 +2088,14 @@ impl Function {
/// is this a `fn main` or a function with an `export_name` of `main`? /// is this a `fn main` or a function with an `export_name` of `main`?
pub fn is_main(self, db: &dyn HirDatabase) -> bool { pub fn is_main(self, db: &dyn HirDatabase) -> bool {
let data = db.function_data(self.id); let data = db.function_data(self.id);
data.attrs.export_name() == Some("main") data.attrs.export_name() == Some(&sym::main)
|| self.module(db).is_crate_root() && data.name.to_smol_str() == "main" || self.module(db).is_crate_root() && data.name == sym::main
} }
/// Is this a function with an `export_name` of `main`? /// Is this a function with an `export_name` of `main`?
pub fn exported_main(self, db: &dyn HirDatabase) -> bool { pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
let data = db.function_data(self.id); 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? /// Does this function have the ignore attribute?

View file

@ -293,7 +293,7 @@ impl<'a> SymbolCollector<'a> {
if let Some(attrs) = def.attrs(self.db) { if let Some(attrs) = def.attrs(self.db) {
for alias in attrs.doc_aliases() { for alias in attrs.doc_aliases() {
self.symbols.push(FileSymbol { self.symbols.push(FileSymbol {
name: alias, name: alias.as_str().into(),
def, def,
loc: dec_loc.clone(), loc: dec_loc.clone(),
container_name: self.current_container_name.clone(), container_name: self.current_container_name.clone(),
@ -330,7 +330,7 @@ impl<'a> SymbolCollector<'a> {
if let Some(attrs) = def.attrs(self.db) { if let Some(attrs) = def.attrs(self.db) {
for alias in attrs.doc_aliases() { for alias in attrs.doc_aliases() {
self.symbols.push(FileSymbol { self.symbols.push(FileSymbol {
name: alias, name: alias.as_str().into(),
def, def,
loc: dec_loc.clone(), loc: dec_loc.clone(),
container_name: self.current_container_name.clone(), container_name: self.current_container_name.clone(),

View file

@ -1,7 +1,7 @@
use std::iter::{self, Peekable}; use std::iter::{self, Peekable};
use either::Either; 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::RootDatabase;
use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast};
use itertools::Itertools; use itertools::Itertools;
@ -381,7 +381,7 @@ impl ExtendedEnum {
fn is_non_exhaustive(self, db: &RootDatabase, krate: Crate) -> bool { fn is_non_exhaustive(self, db: &RootDatabase, krate: Crate) -> bool {
match self { match self {
ExtendedEnum::Enum(e) => { 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, _ => false,
} }

View file

@ -1,4 +1,4 @@
use hir::{HasVisibility, ImportPathConfig}; use hir::{sym, HasVisibility, ImportPathConfig};
use ide_db::{ use ide_db::{
assists::{AssistId, AssistKind}, assists::{AssistId, AssistKind},
defs::Definition, defs::Definition,
@ -98,7 +98,7 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
let kind = struct_type.kind(ctx.db()); let kind = struct_type.kind(ctx.db());
let struct_def_path = module.find_path(ctx.db(), struct_def, cfg)?; 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 = let is_foreign_crate =
struct_def.module(ctx.db()).map_or(false, |m| m.krate() != module.krate()); struct_def.module(ctx.db()).map_or(false, |m| m.krate() != module.krate());

View file

@ -1,7 +1,7 @@
use std::iter; use std::iter;
use ast::edit::IndentLevel; use ast::edit::IndentLevel;
use hir::HasAttrs; use hir::{sym, HasAttrs};
use ide_db::base_db::AnchoredPathBuf; use ide_db::base_db::AnchoredPathBuf;
use itertools::Itertools; use itertools::Itertools;
use stdx::format_to; 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) if !parent_module.is_mod_rs(db)
&& parent_module && parent_module
.attrs(db) .attrs(db)
.by_key("path") .by_key(&sym::path)
.string_value_unescape() .string_value_unescape()
.is_none() => .is_none() =>
{ {

View file

@ -519,7 +519,7 @@ impl CompletionContext<'_> {
I: hir::HasAttrs + Copy, I: hir::HasAttrs + Copy,
{ {
let attrs = item.attrs(self.db); 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)]`. /// Check if an item is `#[doc(hidden)]`.
@ -543,7 +543,7 @@ impl CompletionContext<'_> {
/// Whether the given trait is an operator trait or not. /// Whether the given trait is an operator trait or not.
pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool { pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
match trait_.attrs(self.db).lang() { 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, None => false,
} }
} }
@ -643,7 +643,7 @@ impl CompletionContext<'_> {
pub(crate) fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> { pub(crate) fn doc_aliases_in_scope(&self, scope_def: ScopeDef) -> Vec<SmolStr> {
if let Some(attrs) = scope_def.attrs(self.db) { if let Some(attrs) = scope_def.attrs(self.db) {
attrs.doc_aliases().collect() attrs.doc_aliases().map(|it| it.as_str().into()).collect()
} else { } else {
vec![] vec![]
} }

View file

@ -10,7 +10,7 @@ pub(crate) mod type_alias;
pub(crate) mod union_literal; pub(crate) mod union_literal;
pub(crate) mod variant; 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::{ use ide_db::{
documentation::{Documentation, HasDocs}, documentation::{Documentation, HasDocs},
helpers::item_name, helpers::item_name,
@ -95,7 +95,7 @@ impl<'a> RenderContext<'a> {
fn is_deprecated(&self, def: impl HasAttrs) -> bool { fn is_deprecated(&self, def: impl HasAttrs) -> bool {
let attrs = def.attrs(self.db()); 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 { fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {

View file

@ -1,7 +1,7 @@
//! Code common to structs, unions, and enum variants. //! Code common to structs, unions, and enum variants.
use crate::context::CompletionContext; 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 ide_db::SnippetCap;
use itertools::Itertools; use itertools::Itertools;
use syntax::SmolStr; use syntax::SmolStr;
@ -86,7 +86,7 @@ pub(crate) fn visible_fields(
.copied() .copied()
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let has_invisible_field = n_fields - fields.len() > 0; 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(); && item.krate(ctx.db) != module.krate();
let fields_omitted = has_invisible_field || is_foreign_non_exhaustive; let fields_omitted = has_invisible_field || is_foreign_non_exhaustive;
Some((fields, fields_omitted)) Some((fields, fields_omitted))

View file

@ -2,7 +2,7 @@
use either::Either; use either::Either;
use hir::{ use hir::{
db::{DefDatabase, HirDatabase}, 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 itertools::Itertools;
use syntax::{ use syntax::{
@ -92,7 +92,7 @@ pub fn docs_with_rangemap(
attrs: &AttrsWithOwner, attrs: &AttrsWithOwner,
) -> Option<(Documentation, DocsRangeMap)> { ) -> Option<(Documentation, DocsRangeMap)> {
let docs = attrs let docs = attrs
.by_key("doc") .by_key(&sym::doc)
.attrs() .attrs()
.filter_map(|attr| attr.string_value_unescape().map(|s| (s, attr.id))); .filter_map(|attr| attr.string_value_unescape().map(|s| (s, attr.id)));
let indent = doc_indent(attrs); let indent = doc_indent(attrs);
@ -134,7 +134,7 @@ pub fn docs_with_rangemap(
} }
pub fn docs_from_attrs(attrs: &hir::Attrs) -> Option<String> { 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 indent = doc_indent(attrs);
let mut buf = String::new(); let mut buf = String::new();
for doc in docs { 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 { fn doc_indent(attrs: &hir::Attrs) -> usize {
let mut min = !0; 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) = if let Some(m) =
val.lines().filter_map(|line| line.chars().position(|c| !c.is_whitespace())).min() val.lines().filter_map(|line| line.chars().position(|c| !c.is_whitespace())).min()
{ {

View file

@ -8,7 +8,7 @@ use std::mem;
use base_db::{salsa::Database, FileId, FileRange, SourceDatabase, SourceDatabaseExt}; use base_db::{salsa::Database, FileId, FileRange, SourceDatabase, SourceDatabaseExt};
use hir::{ use hir::{
AsAssocItem, DefWithBody, DescendPreference, HasAttrs, HasSource, HirFileIdExt, InFile, sym, AsAssocItem, DefWithBody, DescendPreference, HasAttrs, HasSource, HirFileIdExt, InFile,
InRealFile, ModuleSource, PathResolution, Semantics, Visibility, InRealFile, ModuleSource, PathResolution, Semantics, Visibility,
}; };
use memchr::memmem::Finder; use memchr::memmem::Finder;
@ -333,7 +333,7 @@ impl Definition {
if let Definition::Macro(macro_def) = self { if let Definition::Macro(macro_def) = self {
return match macro_def.kind(db) { return match macro_def.kind(db) {
hir::MacroKind::Declarative => { 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()) SearchScope::reverse_dependencies(db, module.krate())
} else { } else {
SearchScope::krate(db, module.krate()) SearchScope::krate(db, module.krate())
@ -456,7 +456,7 @@ impl<'a> FindUsages<'a> {
module module
.krate() .krate()
.display_name(self.sema.db) .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 = || { let self_kw_refs = || {

View file

@ -11,7 +11,8 @@ use stdx::format_to;
use url::Url; use url::Url;
use hir::{ use hir::{
db::HirDatabase, Adt, AsAssocItem, AssocItem, AssocItemContainer, DescendPreference, HasAttrs, db::HirDatabase, sym, Adt, AsAssocItem, AssocItem, AssocItemContainer, DescendPreference,
HasAttrs,
}; };
use ide_db::{ use ide_db::{
base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, SourceDatabase}, base_db::{CrateOrigin, LangCrateOrigin, ReleaseChannel, SourceDatabase},
@ -593,12 +594,14 @@ fn filename_and_frag_for_def(
}, },
Definition::Module(m) => match m.name(db) { Definition::Module(m) => match m.name(db) {
// `#[doc(keyword = "...")]` is internal used only by rust compiler // `#[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(name) => {
Some(kw) => { match m.attrs(db).by_key(&sym::doc).find_string_value_in_tt(&sym::keyword) {
format!("keyword.{}.html", kw.trim_matches('"')) 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"), None => String::from("index.html"),
}, },
Definition::Trait(t) => format!("trait.{}.html", t.name(db).display(db.upcast())), Definition::Trait(t) => format!("trait.{}.html", t.name(db).display(db.upcast())),

View file

@ -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> { 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())
} }

View file

@ -408,7 +408,7 @@ pub(crate) fn def_to_moniker(
}), }),
), ),
}; };
PackageInformation { name, repo, version } PackageInformation { name: name.as_str().to_owned(), repo, version }
}, },
}) })
} }

View file

@ -3,7 +3,7 @@
use std::mem; use std::mem;
use either::Either; use either::Either;
use hir::{InFile, Semantics}; use hir::{sym, InFile, Semantics};
use ide_db::{ use ide_db::{
active_parameter::ActiveParameter, base_db::FileId, defs::Definition, active_parameter::ActiveParameter, base_db::FileId, defs::Definition,
documentation::docs_with_rangemap, rust_doc::is_rust_fence, SymbolKind, 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 new_comments = Vec::new();
let mut string; 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); let InFile { file_id, value: src } = attrs_source_map.source_of(attr);
if file_id != src_file_id { if file_id != src_file_id {
continue; continue;
@ -271,7 +271,7 @@ fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::Stri
// #[cfg_attr(..., doc = "", ...)] // #[cfg_attr(..., doc = "", ...)]
None => { None => {
// We gotta hunt the string token manually here // 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 // 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 // This means technically we might highlight the wrong one
it.syntax() it.syntax()

View file

@ -12,7 +12,7 @@ use crate::{
}; };
macro_rules! define_symbols { 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 // 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 // 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 // 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! { define_symbols! {
@WITH_NAME: @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_0 = "0",
INTEGER_1 = "1", INTEGER_1 = "1",
INTEGER_2 = "2", INTEGER_2 = "2",
@ -81,6 +72,15 @@ define_symbols! {
INTEGER_13 = "13", INTEGER_13 = "13",
INTEGER_14 = "14", INTEGER_14 = "14",
INTEGER_15 = "15", 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", fn_ = "fn",
crate_ = "crate", crate_ = "crate",
underscore = "_", underscore = "_",
@ -88,16 +88,43 @@ define_symbols! {
false_ = "false", false_ = "false",
let_ = "let", let_ = "let",
const_ = "const", 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: @PLAIN:
__ra_fixup, __ra_fixup,
aapcs,
add_assign, add_assign,
add, add,
alias,
align_offset, align_offset,
align, align,
all, all,
alloc_layout, alloc_layout,
alloc, alloc,
allow_internal_unsafe,
allow,
any, any,
as_str, as_str,
asm, asm,
@ -122,6 +149,7 @@ define_symbols! {
call_mut, call_mut,
call_once, call_once,
call, call,
cdecl,
Center, Center,
cfg_accessible, cfg_accessible,
cfg_attr, cfg_attr,
@ -154,6 +182,7 @@ define_symbols! {
Debug, Debug,
default, default,
Default, Default,
deprecated,
deref_mut, deref_mut,
deref_target, deref_target,
deref, deref,
@ -168,6 +197,7 @@ define_symbols! {
drop_in_place, drop_in_place,
drop, drop,
dyn_metadata, dyn_metadata,
efiapi,
eh_catch_typeinfo, eh_catch_typeinfo,
eh_personality, eh_personality,
env, env,
@ -176,10 +206,12 @@ define_symbols! {
Err, Err,
exchange_malloc, exchange_malloc,
exhaustive_patterns, exhaustive_patterns,
export_name,
f128, f128,
f16, f16,
f32, f32,
f64, f64,
fastcall,
feature, feature,
file, file,
filter_map, filter_map,
@ -203,6 +235,7 @@ define_symbols! {
from_residual, from_residual,
from_usize, from_usize,
from_yeet, from_yeet,
fundamental,
future_trait, future_trait,
future, future,
Future, Future,
@ -213,6 +246,7 @@ define_symbols! {
gt, gt,
Hash, Hash,
hidden, hidden,
html_root_url,
i128, i128,
i16, i16,
i32, i32,
@ -238,6 +272,8 @@ define_symbols! {
iter_mut, iter_mut,
iter, iter,
Iterator, Iterator,
keyword,
lang,
le, le,
Left, Left,
len, len,
@ -246,8 +282,12 @@ define_symbols! {
local_inner_macros, local_inner_macros,
log_syntax, log_syntax,
lt, lt,
macro_export,
macro_rules, macro_rules,
macro_use,
main,
manually_drop, manually_drop,
may_dangle,
maybe_uninit, maybe_uninit,
metadata_type, metadata_type,
min_exhaustive_patterns, min_exhaustive_patterns,
@ -273,7 +313,9 @@ define_symbols! {
new, new,
next, next,
no_core, no_core,
no_mangle,
no_std, no_std,
non_exhaustive,
none, none,
None, None,
not, not,
@ -305,6 +347,7 @@ define_symbols! {
partial_ord, partial_ord,
PartialEq, PartialEq,
PartialOrd, PartialOrd,
path,
Pending, Pending,
phantom_data, phantom_data,
pieces, pieces,
@ -313,7 +356,11 @@ define_symbols! {
pointer_like, pointer_like,
poll, poll,
Poll, Poll,
prelude_import,
prelude, prelude,
proc_macro_attribute,
proc_macro_derive,
proc_macro,
quote, quote,
range_inclusive_new, range_inclusive_new,
Range, Range,
@ -329,6 +376,7 @@ define_symbols! {
register_tool, register_tool,
rem_assign, rem_assign,
rem, rem,
repr,
result, result,
Result, Result,
ResumeTy, ResumeTy,
@ -338,8 +386,20 @@ define_symbols! {
rust_2021, rust_2021,
rust_2024, rust_2024,
rust_analyzer, rust_analyzer,
Rust,
rustc_allow_incoherent_impl,
rustc_builtin_macro,
rustc_coherence_is_core, 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_macro_transparency,
rustc_reservation_impl,
rustc_safe_intrinsic,
rustc_skip_array_during_method_dispatch,
semitransparent, semitransparent,
shl_assign, shl_assign,
shl, shl,
@ -352,6 +412,7 @@ define_symbols! {
start, start,
std_panic, std_panic,
std, std,
stdcall,
str, str,
string, string,
String, String,
@ -361,10 +422,13 @@ define_symbols! {
sub_assign, sub_assign,
sub, sub,
sync, sync,
system,
sysv64,
Target, Target,
termination, termination,
test_case, test_case,
test, test,
thiscall,
trace_macros, trace_macros,
transmute_opts, transmute_opts,
transmute_trait, transmute_trait,
@ -376,6 +440,7 @@ define_symbols! {
u32, u32,
u64, u64,
u8, u8,
unadjusted,
Unknown, Unknown,
unpin, unpin,
unreachable_2015, unreachable_2015,
@ -383,7 +448,11 @@ define_symbols! {
unreachable, unreachable,
unsafe_cell, unsafe_cell,
unsize, unsize,
unstable,
usize, usize,
v1, v1,
va_list va_list,
vectorcall,
wasm,
win64,
} }

View file

@ -224,6 +224,7 @@ impl ProjectJson {
Crate { Crate {
display_name: crate_data display_name: crate_data
.display_name .display_name
.as_deref()
.map(CrateDisplayName::from_canonical_name), .map(CrateDisplayName::from_canonical_name),
root_module, root_module,
edition: crate_data.edition.into(), edition: crate_data.edition.into(),

View file

@ -894,7 +894,10 @@ fn project_json_to_crate_graph(
.collect(); .collect();
override_cfg.apply( override_cfg.apply(
&mut cfg_options, &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( let crate_graph_crate_id = crate_graph.add_crate_root(
file_id, file_id,
@ -917,7 +920,7 @@ fn project_json_to_crate_graph(
if *is_proc_macro { if *is_proc_macro {
if let Some(path) = proc_macro_dylib_path.clone() { if let Some(path) = proc_macro_dylib_path.clone() {
let node = Ok(( 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, path,
)); ));
proc_macros.insert(crate_graph_crate_id, node); proc_macros.insert(crate_graph_crate_id, node);
@ -1014,12 +1017,12 @@ fn cargo_to_crate_graph(
if pkg_data.is_local { if pkg_data.is_local {
CrateOrigin::Local { CrateOrigin::Local {
repo: pkg_data.repository.clone(), repo: pkg_data.repository.clone(),
name: Some(pkg_data.name.clone()), name: Some(Symbol::intern(&pkg_data.name)),
} }
} else { } else {
CrateOrigin::Library { CrateOrigin::Library {
repo: pkg_data.repository.clone(), 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()); return (crate_graph, FxHashMap::default());
} }
}; };
let display_name = detached_file let display_name = detached_file.file_stem().map(CrateDisplayName::from_canonical_name);
.file_stem()
.map(|file_stem| CrateDisplayName::from_canonical_name(file_stem.to_owned()));
let detached_file_crate = crate_graph.add_crate_root( let detached_file_crate = crate_graph.add_crate_root(
file_id, file_id,
Edition::CURRENT, Edition::CURRENT,
@ -1232,7 +1233,7 @@ fn handle_rustc_crates(
file_id, file_id,
&rustc_workspace[tgt].name, &rustc_workspace[tgt].name,
kind, 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); pkg_to_lib_crate.insert(pkg, crate_id);
// Add dependencies on core / std / alloc for this crate // 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( let crate_id = crate_graph.add_crate_root(
file_id, file_id,
edition, edition,
Some(CrateDisplayName::from_canonical_name(cargo_name.to_owned())), Some(CrateDisplayName::from_canonical_name(cargo_name)),
Some(pkg.version.to_string()), Some(pkg.version.to_string()),
Arc::new(cfg_options), Arc::new(cfg_options),
potential_cfg_options.map(Arc::new), potential_cfg_options.map(Arc::new),
@ -1402,7 +1403,7 @@ fn sysroot_to_crate_graph(
// patch the origin // patch the origin
if c.origin.is_local() { if c.origin.is_local() {
let lang_crate = LangCrateOrigin::from( 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); c.origin = CrateOrigin::Lang(lang_crate);
match lang_crate { match lang_crate {
@ -1459,8 +1460,7 @@ fn sysroot_to_crate_graph(
.filter_map(|krate| { .filter_map(|krate| {
let file_id = load(&stitched[krate].root)?; let file_id = load(&stitched[krate].root)?;
let display_name = let display_name = CrateDisplayName::from_canonical_name(&stitched[krate].name);
CrateDisplayName::from_canonical_name(stitched[krate].name.clone());
let crate_id = crate_graph.add_crate_root( let crate_id = crate_graph.add_crate_root(
file_id, file_id,
Edition::CURRENT, Edition::CURRENT,

View file

@ -621,7 +621,7 @@ impl flags::AnalysisStats {
module module
.krate() .krate()
.display_name(db) .display_name(db)
.map(|it| it.canonical_name().to_owned()) .map(|it| it.canonical_name().as_str().to_owned())
.into_iter() .into_iter()
.chain( .chain(
module module
@ -912,7 +912,7 @@ impl flags::AnalysisStats {
module module
.krate() .krate()
.display_name(db) .display_name(db)
.map(|it| it.canonical_name().to_owned()) .map(|it| it.canonical_name().as_str().to_owned())
.into_iter() .into_iter()
.chain( .chain(
module module

View file

@ -267,7 +267,7 @@ impl ChangeFixture {
let core_crate = crate_graph.add_crate_root( let core_crate = crate_graph.add_crate_root(
core_file, core_file,
Edition::CURRENT, Edition::CURRENT,
Some(CrateDisplayName::from_canonical_name("core".to_owned())), Some(CrateDisplayName::from_canonical_name("core")),
None, None,
Default::default(), Default::default(),
Default::default(), Default::default(),
@ -314,7 +314,7 @@ impl ChangeFixture {
let proc_macros_crate = crate_graph.add_crate_root( let proc_macros_crate = crate_graph.add_crate_root(
proc_lib_file, proc_lib_file,
Edition::CURRENT, Edition::CURRENT,
Some(CrateDisplayName::from_canonical_name("proc_macros".to_owned())), Some(CrateDisplayName::from_canonical_name("proc_macros")),
None, None,
Default::default(), Default::default(),
Default::default(), Default::default(),
@ -530,7 +530,7 @@ fn parse_crate(
let origin = match LangCrateOrigin::from(&*name) { let origin = match LangCrateOrigin::from(&*name) {
LangCrateOrigin::Other => { LangCrateOrigin::Other => {
let name = name.clone(); let name = Symbol::intern(&name);
if non_workspace_member { if non_workspace_member {
CrateOrigin::Library { repo, name } CrateOrigin::Library { repo, name }
} else { } else {