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

View file

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

View file

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

View file

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

View file

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

View file

@ -95,7 +95,7 @@ fn repr_from_value(
item_tree: &ItemTree,
of: AttrOwner,
) -> Option<ReprOptions> {
item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
item_tree.attrs(db, krate, of).by_key(&sym::repr).tt_values().find_map(parse_repr_tt)
}
fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
@ -194,10 +194,10 @@ impl StructData {
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let mut flags = StructFlags::NO_FLAGS;
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
}
if attrs.by_key("fundamental").exists() {
if attrs.by_key(&sym::fundamental).exists() {
flags |= StructFlags::IS_FUNDAMENTAL;
}
if let Some(lang) = attrs.lang_item() {
@ -248,10 +248,10 @@ impl StructData {
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
let mut flags = StructFlags::NO_FLAGS;
if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
if attrs.by_key(&sym::rustc_has_incoherent_inherent_impls).exists() {
flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
}
if attrs.by_key("fundamental").exists() {
if attrs.by_key(&sym::fundamental).exists() {
flags |= StructFlags::IS_FUNDAMENTAL;
}
@ -287,7 +287,7 @@ impl EnumData {
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let rustc_has_incoherent_inherent_impls = item_tree
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
.by_key("rustc_has_incoherent_inherent_impls")
.by_key(&sym::rustc_has_incoherent_inherent_impls)
.exists();
let enum_ = &item_tree[loc.id.value];

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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