mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
More symbol usage
This commit is contained in:
parent
c30bdfcc84
commit
df5f1777b8
50 changed files with 388 additions and 303 deletions
|
@ -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()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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), )*
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 } });
|
||||
|
||||
|
|
|
@ -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(")?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue