mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 13:48:50 +00:00
Auto merge of #17584 - Veykril:landing-page, r=Veykril
Implement symbol interning infra Will fix https://github.com/rust-lang/rust-analyzer/issues/15590 My unsafe-fu is not the best but it does satisfy miri. There is still some follow up work to do, notably a lot of places using strings instead of symbols/names, most notably the token tree.
This commit is contained in:
commit
5784915618
86 changed files with 1415 additions and 789 deletions
|
@ -14,6 +14,8 @@ extend-ignore-re = [
|
|||
"\\w*\\.{3,4}\\w*",
|
||||
'"flate2"',
|
||||
"raison d'être",
|
||||
"inout",
|
||||
"optin"
|
||||
]
|
||||
|
||||
[default.extend-words]
|
||||
|
|
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -835,6 +835,7 @@ dependencies = [
|
|||
"dashmap",
|
||||
"hashbrown",
|
||||
"rustc-hash",
|
||||
"sptr",
|
||||
"triomphe",
|
||||
]
|
||||
|
||||
|
@ -1885,6 +1886,12 @@ dependencies = [
|
|||
"vfs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sptr"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a"
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
|
|
@ -9,6 +9,7 @@ use hir_expand::{
|
|||
attrs::{collect_attrs, Attr, AttrId, RawAttrs},
|
||||
HirFileId, InFile,
|
||||
};
|
||||
use intern::{sym, Symbol};
|
||||
use la_arena::{ArenaMap, Idx, RawIdx};
|
||||
use mbe::DelimiterKind;
|
||||
use syntax::{
|
||||
|
@ -152,7 +153,7 @@ impl Attrs {
|
|||
}
|
||||
|
||||
pub fn lang_item(&self) -> Option<LangItem> {
|
||||
self.by_key("lang").string_value().and_then(LangItem::from_str)
|
||||
self.by_key("lang").string_value().and_then(|it| LangItem::from_symbol(&Symbol::intern(it)))
|
||||
}
|
||||
|
||||
pub fn has_doc_hidden(&self) -> bool {
|
||||
|
@ -199,8 +200,12 @@ impl Attrs {
|
|||
.segments()
|
||||
.iter()
|
||||
.rev()
|
||||
.zip(["core", "prelude", "v1", "test"].iter().rev())
|
||||
.all(|it| it.0.as_str() == Some(it.1))
|
||||
.zip(
|
||||
[sym::core.clone(), sym::prelude.clone(), sym::v1.clone(), sym::test.clone()]
|
||||
.iter()
|
||||
.rev(),
|
||||
)
|
||||
.all(|it| it.0 == it.1)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -568,6 +573,10 @@ impl<'attr> AttrQuery<'attr> {
|
|||
self.attrs().find_map(|attr| attr.string_value())
|
||||
}
|
||||
|
||||
pub fn string_value_with_span(self) -> Option<(&'attr str, span::Span)> {
|
||||
self.attrs().find_map(|attr| attr.string_value_with_span())
|
||||
}
|
||||
|
||||
pub fn string_value_unescape(self) -> Option<Cow<'attr, str>> {
|
||||
self.attrs().find_map(|attr| attr.string_value_unescape())
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ use std::mem;
|
|||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{
|
||||
name::{name, AsName, Name},
|
||||
name::{AsName, Name},
|
||||
ExpandError, InFile,
|
||||
};
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use span::AstIdMap;
|
||||
|
@ -187,8 +187,10 @@ impl ExprCollector<'_> {
|
|||
{
|
||||
let is_mutable =
|
||||
self_param.mut_token().is_some() && self_param.amp_token().is_none();
|
||||
let binding_id: la_arena::Idx<Binding> =
|
||||
self.alloc_binding(name![self], BindingAnnotation::new(is_mutable, false));
|
||||
let binding_id: la_arena::Idx<Binding> = self.alloc_binding(
|
||||
Name::new_symbol_root(sym::self_.clone()),
|
||||
BindingAnnotation::new(is_mutable, false),
|
||||
);
|
||||
self.body.self_param = Some(binding_id);
|
||||
self.source_map.self_param = Some(self.expander.in_file(AstPtr::new(&self_param)));
|
||||
}
|
||||
|
@ -1588,18 +1590,22 @@ impl ExprCollector<'_> {
|
|||
});
|
||||
let mut mappings = vec![];
|
||||
let fmt = match template.and_then(|it| self.expand_macros_to_string(it)) {
|
||||
Some((s, is_direct_literal)) => format_args::parse(
|
||||
&s,
|
||||
fmt_snippet,
|
||||
args,
|
||||
is_direct_literal,
|
||||
|name| self.alloc_expr_desugared(Expr::Path(Path::from(name))),
|
||||
|name, span| {
|
||||
if let Some(span) = span {
|
||||
mappings.push((span, name))
|
||||
}
|
||||
},
|
||||
),
|
||||
Some((s, is_direct_literal)) => {
|
||||
let call_ctx = self.expander.syntax_context();
|
||||
format_args::parse(
|
||||
&s,
|
||||
fmt_snippet,
|
||||
args,
|
||||
is_direct_literal,
|
||||
|name| self.alloc_expr_desugared(Expr::Path(Path::from(name))),
|
||||
|name, span| {
|
||||
if let Some(span) = span {
|
||||
mappings.push((span, name))
|
||||
}
|
||||
},
|
||||
call_ctx,
|
||||
)
|
||||
}
|
||||
None => FormatArgs {
|
||||
template: Default::default(),
|
||||
arguments: args.finish(),
|
||||
|
@ -1723,14 +1729,18 @@ impl ExprCollector<'_> {
|
|||
// unsafe { ::core::fmt::UnsafeArg::new() }
|
||||
// )
|
||||
|
||||
let Some(new_v1_formatted) =
|
||||
LangItem::FormatArguments.ty_rel_path(self.db, self.krate, name![new_v1_formatted])
|
||||
else {
|
||||
let Some(new_v1_formatted) = LangItem::FormatArguments.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
Name::new_symbol_root(sym::new_v1_formatted.clone()),
|
||||
) else {
|
||||
return self.missing_expr();
|
||||
};
|
||||
let Some(unsafe_arg_new) =
|
||||
LangItem::FormatUnsafeArg.ty_rel_path(self.db, self.krate, name![new])
|
||||
else {
|
||||
let Some(unsafe_arg_new) = LangItem::FormatUnsafeArg.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
Name::new_symbol_root(sym::new.clone()),
|
||||
) else {
|
||||
return self.missing_expr();
|
||||
};
|
||||
let new_v1_formatted = self.alloc_expr_desugared(Expr::Path(new_v1_formatted));
|
||||
|
@ -1812,10 +1822,10 @@ impl ExprCollector<'_> {
|
|||
self.db,
|
||||
self.krate,
|
||||
match alignment {
|
||||
Some(FormatAlignment::Left) => name![Left],
|
||||
Some(FormatAlignment::Right) => name![Right],
|
||||
Some(FormatAlignment::Center) => name![Center],
|
||||
None => name![Unknown],
|
||||
Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left.clone()),
|
||||
Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right.clone()),
|
||||
Some(FormatAlignment::Center) => Name::new_symbol_root(sym::Center.clone()),
|
||||
None => Name::new_symbol_root(sym::Unknown.clone()),
|
||||
},
|
||||
);
|
||||
match align {
|
||||
|
@ -1838,8 +1848,11 @@ impl ExprCollector<'_> {
|
|||
let width = self.make_count(width, argmap);
|
||||
|
||||
let format_placeholder_new = {
|
||||
let format_placeholder_new =
|
||||
LangItem::FormatPlaceholder.ty_rel_path(self.db, self.krate, name![new]);
|
||||
let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
Name::new_symbol_root(sym::new.clone()),
|
||||
);
|
||||
match format_placeholder_new {
|
||||
Some(path) => self.alloc_expr_desugared(Expr::Path(path)),
|
||||
None => self.missing_expr(),
|
||||
|
@ -1883,11 +1896,14 @@ impl ExprCollector<'_> {
|
|||
*n as u128,
|
||||
Some(BuiltinUint::Usize),
|
||||
)));
|
||||
let count_is =
|
||||
match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Is]) {
|
||||
Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
|
||||
None => self.missing_expr(),
|
||||
};
|
||||
let count_is = match LangItem::FormatCount.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
Name::new_symbol_root(sym::Is.clone()),
|
||||
) {
|
||||
Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
|
||||
None => self.missing_expr(),
|
||||
};
|
||||
self.alloc_expr_desugared(Expr::Call {
|
||||
callee: count_is,
|
||||
args: Box::new([args]),
|
||||
|
@ -1905,7 +1921,7 @@ impl ExprCollector<'_> {
|
|||
let count_param = match LangItem::FormatCount.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
name![Param],
|
||||
Name::new_symbol_root(sym::Param.clone()),
|
||||
) {
|
||||
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
|
||||
None => self.missing_expr(),
|
||||
|
@ -1921,7 +1937,11 @@ impl ExprCollector<'_> {
|
|||
self.missing_expr()
|
||||
}
|
||||
}
|
||||
None => match LangItem::FormatCount.ty_rel_path(self.db, self.krate, name![Implied]) {
|
||||
None => match LangItem::FormatCount.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
Name::new_symbol_root(sym::Implied.clone()),
|
||||
) {
|
||||
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
|
||||
None => self.missing_expr(),
|
||||
},
|
||||
|
@ -1942,18 +1962,18 @@ impl ExprCollector<'_> {
|
|||
let new_fn = match LangItem::FormatArgument.ty_rel_path(
|
||||
self.db,
|
||||
self.krate,
|
||||
match ty {
|
||||
Format(Display) => name![new_display],
|
||||
Format(Debug) => name![new_debug],
|
||||
Format(LowerExp) => name![new_lower_exp],
|
||||
Format(UpperExp) => name![new_upper_exp],
|
||||
Format(Octal) => name![new_octal],
|
||||
Format(Pointer) => name![new_pointer],
|
||||
Format(Binary) => name![new_binary],
|
||||
Format(LowerHex) => name![new_lower_hex],
|
||||
Format(UpperHex) => name![new_upper_hex],
|
||||
Usize => name![from_usize],
|
||||
},
|
||||
Name::new_symbol_root(match ty {
|
||||
Format(Display) => sym::new_display.clone(),
|
||||
Format(Debug) => sym::new_debug.clone(),
|
||||
Format(LowerExp) => sym::new_lower_exp.clone(),
|
||||
Format(UpperExp) => sym::new_upper_exp.clone(),
|
||||
Format(Octal) => sym::new_octal.clone(),
|
||||
Format(Pointer) => sym::new_pointer.clone(),
|
||||
Format(Binary) => sym::new_binary.clone(),
|
||||
Format(LowerHex) => sym::new_lower_hex.clone(),
|
||||
Format(UpperHex) => sym::new_upper_hex.clone(),
|
||||
Usize => sym::from_usize.clone(),
|
||||
}),
|
||||
) {
|
||||
Some(new_fn) => self.alloc_expr_desugared(Expr::Path(new_fn)),
|
||||
None => self.missing_expr(),
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use hir_expand::name::{name, AsName, Name};
|
||||
use hir_expand::name::{AsName, Name};
|
||||
use intern::sym;
|
||||
/// Different signed int types.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum BuiltinInt {
|
||||
|
@ -48,63 +49,67 @@ pub enum BuiltinType {
|
|||
|
||||
impl BuiltinType {
|
||||
#[rustfmt::skip]
|
||||
pub const ALL: &'static [(Name, BuiltinType)] = &[
|
||||
(name![char], BuiltinType::Char),
|
||||
(name![bool], BuiltinType::Bool),
|
||||
(name![str], BuiltinType::Str),
|
||||
pub fn all_builtin_types() -> [(Name, BuiltinType); 19] {
|
||||
[
|
||||
(Name::new_symbol_root(sym::char.clone()), BuiltinType::Char),
|
||||
(Name::new_symbol_root(sym::bool.clone()), BuiltinType::Bool),
|
||||
(Name::new_symbol_root(sym::str.clone()), BuiltinType::Str),
|
||||
|
||||
(name![isize], BuiltinType::Int(BuiltinInt::Isize)),
|
||||
(name![i8], BuiltinType::Int(BuiltinInt::I8)),
|
||||
(name![i16], BuiltinType::Int(BuiltinInt::I16)),
|
||||
(name![i32], BuiltinType::Int(BuiltinInt::I32)),
|
||||
(name![i64], BuiltinType::Int(BuiltinInt::I64)),
|
||||
(name![i128], BuiltinType::Int(BuiltinInt::I128)),
|
||||
(Name::new_symbol_root(sym::isize.clone()), BuiltinType::Int(BuiltinInt::Isize)),
|
||||
(Name::new_symbol_root(sym::i8.clone()), BuiltinType::Int(BuiltinInt::I8)),
|
||||
(Name::new_symbol_root(sym::i16.clone()), BuiltinType::Int(BuiltinInt::I16)),
|
||||
(Name::new_symbol_root(sym::i32.clone()), BuiltinType::Int(BuiltinInt::I32)),
|
||||
(Name::new_symbol_root(sym::i64.clone()), BuiltinType::Int(BuiltinInt::I64)),
|
||||
(Name::new_symbol_root(sym::i128.clone()), BuiltinType::Int(BuiltinInt::I128)),
|
||||
|
||||
(name![usize], BuiltinType::Uint(BuiltinUint::Usize)),
|
||||
(name![u8], BuiltinType::Uint(BuiltinUint::U8)),
|
||||
(name![u16], BuiltinType::Uint(BuiltinUint::U16)),
|
||||
(name![u32], BuiltinType::Uint(BuiltinUint::U32)),
|
||||
(name![u64], BuiltinType::Uint(BuiltinUint::U64)),
|
||||
(name![u128], BuiltinType::Uint(BuiltinUint::U128)),
|
||||
(Name::new_symbol_root(sym::usize.clone()), BuiltinType::Uint(BuiltinUint::Usize)),
|
||||
(Name::new_symbol_root(sym::u8.clone()), BuiltinType::Uint(BuiltinUint::U8)),
|
||||
(Name::new_symbol_root(sym::u16.clone()), BuiltinType::Uint(BuiltinUint::U16)),
|
||||
(Name::new_symbol_root(sym::u32.clone()), BuiltinType::Uint(BuiltinUint::U32)),
|
||||
(Name::new_symbol_root(sym::u64.clone()), BuiltinType::Uint(BuiltinUint::U64)),
|
||||
(Name::new_symbol_root(sym::u128.clone()), BuiltinType::Uint(BuiltinUint::U128)),
|
||||
|
||||
(name![f16], BuiltinType::Float(BuiltinFloat::F16)),
|
||||
(name![f32], BuiltinType::Float(BuiltinFloat::F32)),
|
||||
(name![f64], BuiltinType::Float(BuiltinFloat::F64)),
|
||||
(name![f128], BuiltinType::Float(BuiltinFloat::F128)),
|
||||
];
|
||||
(Name::new_symbol_root(sym::f16.clone()), BuiltinType::Float(BuiltinFloat::F16)),
|
||||
(Name::new_symbol_root(sym::f32.clone()), BuiltinType::Float(BuiltinFloat::F32)),
|
||||
(Name::new_symbol_root(sym::f64.clone()), BuiltinType::Float(BuiltinFloat::F64)),
|
||||
(Name::new_symbol_root(sym::f128.clone()), BuiltinType::Float(BuiltinFloat::F128)),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn by_name(name: &Name) -> Option<Self> {
|
||||
Self::ALL.iter().find_map(|(n, ty)| if n == name { Some(*ty) } else { None })
|
||||
Self::all_builtin_types()
|
||||
.iter()
|
||||
.find_map(|(n, ty)| if n == name { Some(*ty) } else { None })
|
||||
}
|
||||
}
|
||||
|
||||
impl AsName for BuiltinType {
|
||||
fn as_name(&self) -> Name {
|
||||
match self {
|
||||
BuiltinType::Char => name![char],
|
||||
BuiltinType::Bool => name![bool],
|
||||
BuiltinType::Str => name![str],
|
||||
BuiltinType::Char => Name::new_symbol_root(sym::char.clone()),
|
||||
BuiltinType::Bool => Name::new_symbol_root(sym::bool.clone()),
|
||||
BuiltinType::Str => Name::new_symbol_root(sym::str.clone()),
|
||||
BuiltinType::Int(it) => match it {
|
||||
BuiltinInt::Isize => name![isize],
|
||||
BuiltinInt::I8 => name![i8],
|
||||
BuiltinInt::I16 => name![i16],
|
||||
BuiltinInt::I32 => name![i32],
|
||||
BuiltinInt::I64 => name![i64],
|
||||
BuiltinInt::I128 => name![i128],
|
||||
BuiltinInt::Isize => Name::new_symbol_root(sym::isize.clone()),
|
||||
BuiltinInt::I8 => Name::new_symbol_root(sym::i8.clone()),
|
||||
BuiltinInt::I16 => Name::new_symbol_root(sym::i16.clone()),
|
||||
BuiltinInt::I32 => Name::new_symbol_root(sym::i32.clone()),
|
||||
BuiltinInt::I64 => Name::new_symbol_root(sym::i64.clone()),
|
||||
BuiltinInt::I128 => Name::new_symbol_root(sym::i128.clone()),
|
||||
},
|
||||
BuiltinType::Uint(it) => match it {
|
||||
BuiltinUint::Usize => name![usize],
|
||||
BuiltinUint::U8 => name![u8],
|
||||
BuiltinUint::U16 => name![u16],
|
||||
BuiltinUint::U32 => name![u32],
|
||||
BuiltinUint::U64 => name![u64],
|
||||
BuiltinUint::U128 => name![u128],
|
||||
BuiltinUint::Usize => Name::new_symbol_root(sym::usize.clone()),
|
||||
BuiltinUint::U8 => Name::new_symbol_root(sym::u8.clone()),
|
||||
BuiltinUint::U16 => Name::new_symbol_root(sym::u16.clone()),
|
||||
BuiltinUint::U32 => Name::new_symbol_root(sym::u32.clone()),
|
||||
BuiltinUint::U64 => Name::new_symbol_root(sym::u64.clone()),
|
||||
BuiltinUint::U128 => Name::new_symbol_root(sym::u128.clone()),
|
||||
},
|
||||
BuiltinType::Float(it) => match it {
|
||||
BuiltinFloat::F16 => name![f16],
|
||||
BuiltinFloat::F32 => name![f32],
|
||||
BuiltinFloat::F64 => name![f64],
|
||||
BuiltinFloat::F128 => name![f128],
|
||||
BuiltinFloat::F16 => Name::new_symbol_root(sym::f16.clone()),
|
||||
BuiltinFloat::F32 => Name::new_symbol_root(sym::f32.clone()),
|
||||
BuiltinFloat::F64 => Name::new_symbol_root(sym::f64.clone()),
|
||||
BuiltinFloat::F128 => Name::new_symbol_root(sym::f128.clone()),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use base_db::CrateId;
|
|||
use hir_expand::{
|
||||
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
|
||||
};
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use smallvec::SmallVec;
|
||||
use syntax::{ast, Parse};
|
||||
use triomphe::Arc;
|
||||
|
@ -485,7 +485,7 @@ impl ExternCrateDeclData {
|
|||
|
||||
let name = extern_crate.name.clone();
|
||||
let krate = loc.container.krate();
|
||||
let crate_id = if name == hir_expand::name![self] {
|
||||
let crate_id = if name == sym::self_.clone() {
|
||||
Some(krate)
|
||||
} else {
|
||||
db.crate_def_map(krate)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use base_db::{salsa, CrateId, FileId, SourceDatabase, Upcast};
|
||||
use either::Either;
|
||||
use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId};
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use la_arena::ArenaMap;
|
||||
use span::MacroCallId;
|
||||
use syntax::{ast, AstPtr};
|
||||
|
@ -261,9 +261,9 @@ fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
|
|||
let item_tree = db.file_item_tree(file.into());
|
||||
let attrs = item_tree.raw_attrs(AttrOwner::TopLevel);
|
||||
for attr in &**attrs {
|
||||
match attr.path().as_ident().and_then(|id| id.as_text()) {
|
||||
Some(ident) if ident == "no_std" => return true,
|
||||
Some(ident) if ident == "cfg_attr" => {}
|
||||
match attr.path().as_ident() {
|
||||
Some(ident) if *ident == sym::no_std.clone() => return true,
|
||||
Some(ident) if *ident == sym::cfg_attr.clone() => {}
|
||||
_ => continue,
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ use hir_expand::{
|
|||
InFile, MacroCallId,
|
||||
};
|
||||
use limit::Limit;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::{ast, Parse};
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -52,6 +53,11 @@ impl Expander {
|
|||
self.module.krate
|
||||
}
|
||||
|
||||
pub fn syntax_context(&self) -> SyntaxContextId {
|
||||
// FIXME:
|
||||
SyntaxContextId::ROOT
|
||||
}
|
||||
|
||||
pub fn enter_expand<T: ast::AstNode>(
|
||||
&mut self,
|
||||
db: &dyn DefDatabase,
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
use std::{cell::Cell, cmp::Ordering, iter};
|
||||
|
||||
use hir_expand::{
|
||||
name::{known, AsName, Name},
|
||||
name::{AsName, Name},
|
||||
Lookup,
|
||||
};
|
||||
use intern::{sym, Symbol};
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::{
|
||||
|
@ -414,13 +415,13 @@ fn select_best_path(
|
|||
(Unstable, Stable) => return new_path,
|
||||
_ => {}
|
||||
}
|
||||
const STD_CRATES: [Name; 3] = [known::std, known::core, known::alloc];
|
||||
let std_crates: [Symbol; 3] = [sym::std.clone(), sym::core.clone(), sym::alloc.clone()];
|
||||
|
||||
let choose = |new: (ModPath, _), old: (ModPath, _)| {
|
||||
let (new_path, _) = &new;
|
||||
let (old_path, _) = &old;
|
||||
let new_has_prelude = new_path.segments().iter().any(|seg| seg == &known::prelude);
|
||||
let old_has_prelude = old_path.segments().iter().any(|seg| seg == &known::prelude);
|
||||
let new_has_prelude = new_path.segments().iter().any(|seg| *seg == sym::prelude.clone());
|
||||
let old_has_prelude = old_path.segments().iter().any(|seg| *seg == sym::prelude.clone());
|
||||
match (new_has_prelude, old_has_prelude, cfg.prefer_prelude) {
|
||||
(true, false, true) | (false, true, false) => new,
|
||||
(true, false, false) | (false, true, true) => old,
|
||||
|
@ -441,18 +442,20 @@ fn select_best_path(
|
|||
};
|
||||
|
||||
match (old_path.0.segments().first(), new_path.0.segments().first()) {
|
||||
(Some(old), Some(new)) if STD_CRATES.contains(old) && STD_CRATES.contains(new) => {
|
||||
(Some(old), Some(new))
|
||||
if std_crates.contains(old.symbol()) && std_crates.contains(new.symbol()) =>
|
||||
{
|
||||
let rank = match cfg.prefer_no_std {
|
||||
false => |name: &Name| match name {
|
||||
name if name == &known::core => 0,
|
||||
name if name == &known::alloc => 1,
|
||||
name if name == &known::std => 2,
|
||||
name if *name == sym::core.clone() => 0,
|
||||
name if *name == sym::alloc.clone() => 1,
|
||||
name if *name == sym::std.clone() => 2,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
true => |name: &Name| match name {
|
||||
name if name == &known::core => 2,
|
||||
name if name == &known::alloc => 1,
|
||||
name if name == &known::std => 0,
|
||||
name if *name == sym::core.clone() => 2,
|
||||
name if *name == sym::alloc.clone() => 1,
|
||||
name if *name == sym::std.clone() => 0,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -3,10 +3,11 @@ use std::mem;
|
|||
|
||||
use hir_expand::name::Name;
|
||||
use rustc_parse_format as parse;
|
||||
use span::SyntaxContextId;
|
||||
use stdx::TupleExt;
|
||||
use syntax::{
|
||||
ast::{self, IsString},
|
||||
SmolStr, TextRange, TextSize,
|
||||
TextRange, TextSize,
|
||||
};
|
||||
|
||||
use crate::hir::ExprId;
|
||||
|
@ -174,6 +175,7 @@ pub(crate) fn parse(
|
|||
is_direct_literal: bool,
|
||||
mut synth: impl FnMut(Name) -> ExprId,
|
||||
mut record_usage: impl FnMut(Name, Option<TextRange>),
|
||||
call_ctx: SyntaxContextId,
|
||||
) -> FormatArgs {
|
||||
let Ok(text) = s.value() else {
|
||||
return FormatArgs {
|
||||
|
@ -248,7 +250,7 @@ pub(crate) fn parse(
|
|||
}
|
||||
}
|
||||
ArgRef::Name(name, span) => {
|
||||
let name = Name::new_text_dont_use(SmolStr::new(name));
|
||||
let name = Name::new(name, call_ctx);
|
||||
if let Some((index, _)) = args.by_name(&name) {
|
||||
record_usage(name, span);
|
||||
// Name found in `args`, so we resolve it to its index.
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
//! Describes items defined or visible (ie, imported) in a certain scope.
|
||||
//! This is shared between modules and blocks.
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
|
||||
use indexmap::map::Entry;
|
||||
use itertools::Itertools;
|
||||
use la_arena::Idx;
|
||||
use once_cell::sync::Lazy;
|
||||
|
@ -17,8 +16,8 @@ use crate::{
|
|||
db::DefDatabase,
|
||||
per_ns::PerNs,
|
||||
visibility::{Visibility, VisibilityExplicitness},
|
||||
AdtId, BuiltinType, ConstId, ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId,
|
||||
ModuleDefId, ModuleId, TraitId, UseId,
|
||||
AdtId, BuiltinType, ConstId, ExternCrateId, FxIndexMap, HasModule, ImplId, LocalModuleId,
|
||||
Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -67,9 +66,9 @@ pub struct ItemScope {
|
|||
/// Defs visible in this scope. This includes `declarations`, but also
|
||||
/// imports. The imports belong to this module and can be resolved by using them on
|
||||
/// the `use_imports_*` fields.
|
||||
types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
|
||||
values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
|
||||
macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
|
||||
types: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
|
||||
values: FxIndexMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
|
||||
macros: FxIndexMap<Name, (MacroId, Visibility, Option<ImportId>)>,
|
||||
unresolved: FxHashSet<Name>,
|
||||
|
||||
/// The defs declared in this scope. Each def has a single scope where it is
|
||||
|
@ -118,8 +117,8 @@ struct DeriveMacroInvocation {
|
|||
derive_call_ids: SmallVec<[Option<MacroCallId>; 1]>,
|
||||
}
|
||||
|
||||
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
|
||||
BuiltinType::ALL
|
||||
pub(crate) static BUILTIN_SCOPE: Lazy<FxIndexMap<Name, PerNs>> = Lazy::new(|| {
|
||||
BuiltinType::all_builtin_types()
|
||||
.iter()
|
||||
.map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))
|
||||
.collect()
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
|
||||
use hir_expand::{mod_path::path, name::AsName, span_map::SpanMapRef, HirFileId};
|
||||
use intern::sym;
|
||||
use la_arena::Arena;
|
||||
use rustc_hash::FxHashMap;
|
||||
use span::{AstIdMap, SyntaxContextId};
|
||||
|
@ -323,7 +324,8 @@ impl<'a> Ctx<'a> {
|
|||
let self_type = match self_param.ty() {
|
||||
Some(type_ref) => TypeRef::from_ast(&self.body_ctx, type_ref),
|
||||
None => {
|
||||
let self_type = TypeRef::Path(name![Self].into());
|
||||
let self_type =
|
||||
TypeRef::Path(Name::new_symbol_root(sym::Self_.clone()).into());
|
||||
match self_param.kind() {
|
||||
ast::SelfParamKind::Owned => self_type,
|
||||
ast::SelfParamKind::Ref => TypeRef::Reference(
|
||||
|
@ -669,7 +671,7 @@ impl<'a> Ctx<'a> {
|
|||
// Traits and trait aliases get the Self type as an implicit first type parameter.
|
||||
generics.type_or_consts.alloc(
|
||||
TypeParamData {
|
||||
name: Some(name![Self]),
|
||||
name: Some(Name::new_symbol_root(sym::Self_.clone())),
|
||||
default: None,
|
||||
provenance: TypeParamProvenance::TraitSelf,
|
||||
}
|
||||
|
@ -680,7 +682,7 @@ impl<'a> Ctx<'a> {
|
|||
generics.fill_bounds(
|
||||
&self.body_ctx,
|
||||
bounds,
|
||||
Either::Left(TypeRef::Path(name![Self].into())),
|
||||
Either::Left(TypeRef::Path(Name::new_symbol_root(sym::Self_.clone()).into())),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -745,7 +747,7 @@ fn desugar_future_path(orig: TypeRef) -> Path {
|
|||
let mut generic_args: Vec<_> =
|
||||
std::iter::repeat(None).take(path.segments().len() - 1).collect();
|
||||
let binding = AssociatedTypeBinding {
|
||||
name: name![Output],
|
||||
name: Name::new_symbol_root(sym::Output.clone()),
|
||||
args: None,
|
||||
type_ref: Some(orig),
|
||||
bounds: Box::default(),
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//! This attribute to tell the compiler about semi built-in std library
|
||||
//! features, such as Fn family of traits.
|
||||
use hir_expand::name::Name;
|
||||
use intern::{sym, Symbol};
|
||||
use rustc_hash::FxHashMap;
|
||||
use syntax::SmolStr;
|
||||
use triomphe::Arc;
|
||||
|
@ -191,8 +192,7 @@ impl LangItems {
|
|||
}
|
||||
|
||||
pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
|
||||
let attrs = db.attrs(item);
|
||||
attrs.by_key("lang").string_value().and_then(LangItem::from_str)
|
||||
db.attrs(item).lang_item()
|
||||
}
|
||||
|
||||
pub(crate) fn notable_traits_in_deps(
|
||||
|
@ -260,10 +260,9 @@ macro_rules! language_item_table {
|
|||
}
|
||||
|
||||
/// Opposite of [`LangItem::name`]
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
pub fn from_str(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
$( stringify!($name) => Some(LangItem::$variant), )*
|
||||
pub fn from_symbol(sym: &Symbol) -> Option<Self> {
|
||||
match sym {
|
||||
$(sym if *sym == $module::$name => Some(LangItem::$variant), )*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +273,7 @@ macro_rules! language_item_table {
|
|||
impl LangItem {
|
||||
/// Opposite of [`LangItem::name`]
|
||||
pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
|
||||
Self::from_str(name.as_str()?)
|
||||
Self::from_symbol(name.symbol())
|
||||
}
|
||||
|
||||
pub fn path(&self, db: &dyn DefDatabase, start_crate: CrateId) -> Option<Path> {
|
||||
|
@ -360,7 +359,7 @@ language_item_table! {
|
|||
DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
|
||||
Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
|
||||
|
||||
Fn, kw::fn, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
Fn, sym::fn_, fn_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
FnMut, sym::fn_mut, fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
FnOnce, sym::fn_once, fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
|
||||
|
||||
|
|
|
@ -862,7 +862,7 @@ impl GeneralConstId {
|
|||
.const_data(const_id)
|
||||
.name
|
||||
.as_ref()
|
||||
.and_then(|it| it.as_str())
|
||||
.map(|it| it.as_str())
|
||||
.unwrap_or("_")
|
||||
.to_owned(),
|
||||
GeneralConstId::ConstBlockId(id) => format!("{{anonymous const {id:?}}}"),
|
||||
|
|
|
@ -323,7 +323,7 @@ pub struct ModuleData {
|
|||
///
|
||||
/// [`None`] for block modules because they are always its `DefMap`'s root.
|
||||
pub parent: Option<LocalModuleId>,
|
||||
pub children: FxHashMap<Name, LocalModuleId>,
|
||||
pub children: FxIndexMap<Name, LocalModuleId>,
|
||||
pub scope: ItemScope,
|
||||
}
|
||||
|
||||
|
@ -593,10 +593,8 @@ impl DefMap {
|
|||
self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
|
||||
}
|
||||
|
||||
pub(crate) fn macro_use_prelude(
|
||||
&self,
|
||||
) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
|
||||
self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
|
||||
pub(crate) fn macro_use_prelude(&self) -> &FxHashMap<Name, (MacroId, Option<ExternCrateId>)> {
|
||||
&self.macro_use_prelude
|
||||
}
|
||||
|
||||
pub(crate) fn resolve_path(
|
||||
|
@ -668,7 +666,7 @@ impl ModuleData {
|
|||
origin,
|
||||
visibility,
|
||||
parent: None,
|
||||
children: FxHashMap::default(),
|
||||
children: Default::default(),
|
||||
scope: ItemScope::default(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,11 @@ use hir_expand::{
|
|||
builtin_attr_macro::find_builtin_attr,
|
||||
builtin_derive_macro::find_builtin_derive,
|
||||
builtin_fn_macro::find_builtin_macro,
|
||||
name::{name, AsName, Name},
|
||||
name::{AsName, Name},
|
||||
proc_macro::CustomProcMacroExpander,
|
||||
ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
|
||||
};
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use itertools::{izip, Itertools};
|
||||
use la_arena::Idx;
|
||||
use limit::Limit;
|
||||
|
@ -76,25 +76,28 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
|
|||
|
||||
let proc_macros = if krate.is_proc_macro {
|
||||
match db.proc_macros().get(&def_map.krate) {
|
||||
Some(Ok(proc_macros)) => Ok(proc_macros
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, it)| {
|
||||
let name = Name::new_text_dont_use(it.name.clone());
|
||||
(
|
||||
name,
|
||||
if !db.expand_proc_attr_macros() {
|
||||
CustomProcMacroExpander::dummy()
|
||||
} else if it.disabled {
|
||||
CustomProcMacroExpander::disabled()
|
||||
} else {
|
||||
CustomProcMacroExpander::new(hir_expand::proc_macro::ProcMacroId::new(
|
||||
idx as u32,
|
||||
))
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()),
|
||||
Some(Ok(proc_macros)) => Ok({
|
||||
let ctx = db.syntax_context(tree_id.file_id());
|
||||
proc_macros
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(idx, it)| {
|
||||
let name = Name::new(&it.name, ctx);
|
||||
(
|
||||
name,
|
||||
if !db.expand_proc_attr_macros() {
|
||||
CustomProcMacroExpander::dummy()
|
||||
} else if it.disabled {
|
||||
CustomProcMacroExpander::disabled()
|
||||
} else {
|
||||
CustomProcMacroExpander::new(
|
||||
hir_expand::proc_macro::ProcMacroId::new(idx as u32),
|
||||
)
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}),
|
||||
Some(Err(e)) => Err(e.clone().into_boxed_str()),
|
||||
None => Err("No proc-macros present for crate".to_owned().into_boxed_str()),
|
||||
}
|
||||
|
@ -291,24 +294,24 @@ impl DefCollector<'_> {
|
|||
let Some(attr_name) = attr.path.as_ident() else { continue };
|
||||
|
||||
match () {
|
||||
() if *attr_name == hir_expand::name![recursion_limit] => {
|
||||
() if *attr_name == sym::recursion_limit.clone() => {
|
||||
if let Some(limit) = attr.string_value() {
|
||||
if let Ok(limit) = limit.parse() {
|
||||
crate_data.recursion_limit = Some(limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
() if *attr_name == hir_expand::name![crate_type] => {
|
||||
() if *attr_name == sym::crate_type.clone() => {
|
||||
if let Some("proc-macro") = attr.string_value() {
|
||||
self.is_proc_macro = true;
|
||||
}
|
||||
}
|
||||
() if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true,
|
||||
() if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true,
|
||||
() if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => {
|
||||
() if *attr_name == sym::no_core.clone() => crate_data.no_core = true,
|
||||
() if *attr_name == sym::no_std.clone() => crate_data.no_std = true,
|
||||
() if *attr_name == sym::rustc_coherence_is_core.clone() => {
|
||||
crate_data.rustc_coherence_is_core = true;
|
||||
}
|
||||
() if *attr_name == hir_expand::name![feature] => {
|
||||
() if *attr_name == sym::feature.clone() => {
|
||||
let features = attr
|
||||
.parse_path_comma_token_tree(self.db.upcast())
|
||||
.into_iter()
|
||||
|
@ -319,13 +322,13 @@ impl DefCollector<'_> {
|
|||
});
|
||||
crate_data.unstable_features.extend(features);
|
||||
}
|
||||
() if *attr_name == hir_expand::name![register_attr] => {
|
||||
() if *attr_name == sym::register_attr.clone() => {
|
||||
if let Some(ident) = attr.single_ident_value() {
|
||||
crate_data.registered_attrs.push(ident.text.clone());
|
||||
cov_mark::hit!(register_attr);
|
||||
}
|
||||
}
|
||||
() if *attr_name == hir_expand::name![register_tool] => {
|
||||
() if *attr_name == sym::register_tool.clone() => {
|
||||
if let Some(ident) = attr.single_ident_value() {
|
||||
crate_data.registered_tools.push(ident.text.clone());
|
||||
cov_mark::hit!(register_tool);
|
||||
|
@ -535,27 +538,30 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
let krate = if self.def_map.data.no_std {
|
||||
name![core]
|
||||
} else if self.def_map.extern_prelude().any(|(name, _)| *name == name![std]) {
|
||||
name![std]
|
||||
Name::new_symbol_root(sym::core.clone())
|
||||
} else if self.def_map.extern_prelude().any(|(name, _)| *name == sym::std.clone()) {
|
||||
Name::new_symbol_root(sym::std.clone())
|
||||
} else {
|
||||
// If `std` does not exist for some reason, fall back to core. This mostly helps
|
||||
// keep r-a's own tests minimal.
|
||||
name![core]
|
||||
Name::new_symbol_root(sym::core.clone())
|
||||
};
|
||||
|
||||
let edition = match self.def_map.data.edition {
|
||||
Edition::Edition2015 => name![rust_2015],
|
||||
Edition::Edition2018 => name![rust_2018],
|
||||
Edition::Edition2021 => name![rust_2021],
|
||||
Edition::Edition2024 => name![rust_2024],
|
||||
Edition::Edition2015 => Name::new_symbol_root(sym::rust_2015.clone()),
|
||||
Edition::Edition2018 => Name::new_symbol_root(sym::rust_2018.clone()),
|
||||
Edition::Edition2021 => Name::new_symbol_root(sym::rust_2021.clone()),
|
||||
Edition::Edition2024 => Name::new_symbol_root(sym::rust_2024.clone()),
|
||||
};
|
||||
|
||||
let path_kind = match self.def_map.data.edition {
|
||||
Edition::Edition2015 => PathKind::Plain,
|
||||
_ => PathKind::Abs,
|
||||
};
|
||||
let path = ModPath::from_segments(path_kind, [krate, name![prelude], edition]);
|
||||
let path = ModPath::from_segments(
|
||||
path_kind,
|
||||
[krate, Name::new_symbol_root(sym::prelude.clone()), edition],
|
||||
);
|
||||
|
||||
let (per_ns, _) =
|
||||
self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None);
|
||||
|
@ -838,7 +844,7 @@ impl DefCollector<'_> {
|
|||
}
|
||||
|
||||
fn resolve_extern_crate(&self, name: &Name) -> Option<CrateRootModuleId> {
|
||||
if *name == name![self] {
|
||||
if *name == sym::self_.clone() {
|
||||
cov_mark::hit!(extern_crate_self_as);
|
||||
Some(self.def_map.crate_root())
|
||||
} else {
|
||||
|
@ -2136,9 +2142,9 @@ impl ModCollector<'_, '_> {
|
|||
let expander = if attrs.by_key("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() {
|
||||
Some(it) => {
|
||||
name = Name::new_text_dont_use(it.into());
|
||||
let name = match attrs.by_key("rustc_builtin_macro").string_value_with_span() {
|
||||
Some((it, span)) => {
|
||||
name = Name::new(it, span.ctx);
|
||||
&name
|
||||
}
|
||||
None => {
|
||||
|
|
|
@ -1348,6 +1348,7 @@ fn proc_attr(a: TokenStream, b: TokenStream) -> TokenStream { a }
|
|||
.keys()
|
||||
.map(|name| name.display(&db).to_string())
|
||||
.sorted()
|
||||
.sorted()
|
||||
.join("\n");
|
||||
|
||||
expect![[r#"
|
||||
|
|
|
@ -6,9 +6,9 @@ use crate::{lower::LowerCtx, type_ref::ConstRef};
|
|||
|
||||
use hir_expand::{
|
||||
mod_path::resolve_crate_root,
|
||||
name::{name, AsName},
|
||||
name::{AsName, Name},
|
||||
};
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use syntax::ast::{self, AstNode, HasGenericArgs, HasTypeBounds};
|
||||
|
||||
use crate::{
|
||||
|
@ -60,7 +60,7 @@ pub(super) fn lower_path(ctx: &LowerCtx<'_>, mut path: ast::Path) -> Option<Path
|
|||
segments.push(name);
|
||||
}
|
||||
ast::PathSegmentKind::SelfTypeKw => {
|
||||
segments.push(name![Self]);
|
||||
segments.push(Name::new_symbol_root(sym::Self_.clone()));
|
||||
}
|
||||
ast::PathSegmentKind::Type { type_ref, trait_ref } => {
|
||||
assert!(path.qualifier().is_none()); // this can only occur at the first segment
|
||||
|
@ -268,7 +268,7 @@ fn lower_generic_args_from_fn_path(
|
|||
let bindings = if let Some(ret_type) = ret_type {
|
||||
let type_ref = TypeRef::from_ast_opt(ctx, ret_type.ty());
|
||||
Box::new([AssociatedTypeBinding {
|
||||
name: name![Output],
|
||||
name: Name::new_symbol_root(sym::Output.clone()),
|
||||
args: None,
|
||||
type_ref: Some(type_ref),
|
||||
bounds: Box::default(),
|
||||
|
@ -277,7 +277,7 @@ fn lower_generic_args_from_fn_path(
|
|||
// -> ()
|
||||
let type_ref = TypeRef::Tuple(Vec::new());
|
||||
Box::new([AssociatedTypeBinding {
|
||||
name: name![Output],
|
||||
name: Name::new_symbol_root(sym::Output.clone()),
|
||||
args: None,
|
||||
type_ref: Some(type_ref),
|
||||
bounds: Box::default(),
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
use std::{fmt, iter, mem};
|
||||
|
||||
use base_db::CrateId;
|
||||
use hir_expand::{
|
||||
name::{name, Name},
|
||||
MacroDefId,
|
||||
};
|
||||
use intern::Interned;
|
||||
use hir_expand::{name::Name, MacroDefId};
|
||||
use intern::{sym, Interned};
|
||||
use itertools::Itertools as _;
|
||||
use rustc_hash::FxHashSet;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use triomphe::Arc;
|
||||
|
@ -197,12 +195,12 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
&Scope::ImplDefScope(impl_) => {
|
||||
if first_name == &name![Self] {
|
||||
if *first_name == sym::Self_.clone() {
|
||||
return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
|
||||
}
|
||||
}
|
||||
&Scope::AdtScope(adt) => {
|
||||
if first_name == &name![Self] {
|
||||
if *first_name == sym::Self_.clone() {
|
||||
return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
|
||||
}
|
||||
}
|
||||
|
@ -294,7 +292,7 @@ impl Resolver {
|
|||
}
|
||||
};
|
||||
let n_segments = path.segments().len();
|
||||
let tmp = name![self];
|
||||
let tmp = Name::new_symbol_root(sym::self_.clone());
|
||||
let first_name = if path.is_self() { &tmp } else { path.segments().first()? };
|
||||
let skip_to_mod = path.kind != PathKind::Plain && !path.is_self();
|
||||
if skip_to_mod {
|
||||
|
@ -325,7 +323,7 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
&Scope::ImplDefScope(impl_) => {
|
||||
if first_name == &name![Self] {
|
||||
if *first_name == sym::Self_.clone() {
|
||||
return Some(ResolveValueResult::ValueNs(
|
||||
ValueNs::ImplSelf(impl_),
|
||||
None,
|
||||
|
@ -352,7 +350,7 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
&Scope::ImplDefScope(impl_) => {
|
||||
if first_name == &name![Self] {
|
||||
if *first_name == sym::Self_.clone() {
|
||||
return Some(ResolveValueResult::Partial(
|
||||
TypeNs::SelfType(impl_),
|
||||
1,
|
||||
|
@ -361,7 +359,7 @@ impl Resolver {
|
|||
}
|
||||
}
|
||||
Scope::AdtScope(adt) => {
|
||||
if first_name == &name![Self] {
|
||||
if *first_name == sym::Self_.clone() {
|
||||
let ty = TypeNs::AdtSelfType(*adt);
|
||||
return Some(ResolveValueResult::Partial(ty, 1, None));
|
||||
}
|
||||
|
@ -425,7 +423,7 @@ impl Resolver {
|
|||
}
|
||||
|
||||
pub fn resolve_lifetime(&self, lifetime: &LifetimeRef) -> Option<LifetimeNs> {
|
||||
if lifetime.name == name::known::STATIC_LIFETIME {
|
||||
if lifetime.name == sym::tick_static.clone() {
|
||||
return Some(LifetimeNs::Static);
|
||||
}
|
||||
|
||||
|
@ -500,9 +498,11 @@ impl Resolver {
|
|||
res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)));
|
||||
})
|
||||
});
|
||||
def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| {
|
||||
res.add(name, ScopeDef::ModuleDef(def.into()));
|
||||
});
|
||||
def_map.macro_use_prelude().iter().sorted_by_key(|&(k, _)| k.clone()).for_each(
|
||||
|(name, &(def, _extern_crate))| {
|
||||
res.add(name, ScopeDef::ModuleDef(def.into()));
|
||||
},
|
||||
);
|
||||
def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
|
||||
res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
|
||||
});
|
||||
|
@ -781,10 +781,10 @@ impl Scope {
|
|||
}
|
||||
}
|
||||
Scope::ImplDefScope(i) => {
|
||||
acc.add(&name![Self], ScopeDef::ImplSelfType(*i));
|
||||
acc.add(&Name::new_symbol_root(sym::Self_.clone()), ScopeDef::ImplSelfType(*i));
|
||||
}
|
||||
Scope::AdtScope(i) => {
|
||||
acc.add(&name![Self], ScopeDef::AdtSelfType(*i));
|
||||
acc.add(&Name::new_symbol_root(sym::Self_.clone()), ScopeDef::AdtSelfType(*i));
|
||||
}
|
||||
Scope::ExprScope(scope) => {
|
||||
if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) {
|
||||
|
|
|
@ -4,7 +4,7 @@ use std::{borrow::Cow, fmt, ops};
|
|||
use base_db::CrateId;
|
||||
use cfg::CfgExpr;
|
||||
use either::Either;
|
||||
use intern::Interned;
|
||||
use intern::{sym, Interned};
|
||||
use mbe::{syntax_node_to_token_tree, DelimiterKind, DocCommentDesugarMode, Punct};
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use span::{Span, SyntaxContextId};
|
||||
|
@ -12,6 +12,7 @@ use syntax::unescape;
|
|||
use syntax::{ast, format_smolstr, match_ast, AstNode, AstToken, SmolStr, SyntaxNode};
|
||||
use triomphe::ThinArc;
|
||||
|
||||
use crate::name::Name;
|
||||
use crate::{
|
||||
db::ExpandDatabase,
|
||||
mod_path::ModPath,
|
||||
|
@ -58,7 +59,10 @@ impl RawAttrs {
|
|||
text: SmolStr::new(format_smolstr!("\"{}\"", Self::escape_chars(doc))),
|
||||
span,
|
||||
}))),
|
||||
path: Interned::new(ModPath::from(crate::name!(doc))),
|
||||
path: Interned::new(ModPath::from(Name::new_symbol(
|
||||
sym::doc.clone(),
|
||||
span.ctx,
|
||||
))),
|
||||
ctxt: span.ctx,
|
||||
}
|
||||
}),
|
||||
|
@ -115,7 +119,7 @@ impl RawAttrs {
|
|||
pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
|
||||
let has_cfg_attrs = self
|
||||
.iter()
|
||||
.any(|attr| attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]));
|
||||
.any(|attr| attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone()));
|
||||
if !has_cfg_attrs {
|
||||
return self;
|
||||
}
|
||||
|
@ -125,7 +129,7 @@ impl RawAttrs {
|
|||
self.iter()
|
||||
.flat_map(|attr| -> SmallVec<[_; 1]> {
|
||||
let is_cfg_attr =
|
||||
attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]);
|
||||
attr.path.as_ident().map_or(false, |name| *name == sym::cfg_attr.clone());
|
||||
if !is_cfg_attr {
|
||||
return smallvec![attr.clone()];
|
||||
}
|
||||
|
@ -316,6 +320,20 @@ impl Attr {
|
|||
}
|
||||
}
|
||||
|
||||
/// #[path = "string"]
|
||||
pub fn string_value_with_span(&self) -> Option<(&str, span::Span)> {
|
||||
match self.input.as_deref()? {
|
||||
AttrInput::Literal(it) => match it.text.strip_prefix('r') {
|
||||
Some(it) => it.trim_matches('#'),
|
||||
None => it.text.as_str(),
|
||||
}
|
||||
.strip_prefix('"')?
|
||||
.strip_suffix('"')
|
||||
.zip(Some(it.span)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn string_value_unescape(&self) -> Option<Cow<'_, str>> {
|
||||
match self.input.as_deref()? {
|
||||
AttrInput::Literal(it) => match it.text.strip_prefix('r') {
|
||||
|
@ -369,7 +387,7 @@ impl Attr {
|
|||
}
|
||||
|
||||
pub fn cfg(&self) -> Option<CfgExpr> {
|
||||
if *self.path.as_ident()? == crate::name![cfg] {
|
||||
if *self.path.as_ident()? == sym::cfg.clone() {
|
||||
self.token_tree_value().map(CfgExpr::parse)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//! Builtin attributes.
|
||||
use intern::sym;
|
||||
use span::{MacroCallId, Span};
|
||||
|
||||
use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind};
|
||||
|
@ -19,7 +20,7 @@ macro_rules! register_builtin {
|
|||
|
||||
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
match name {
|
||||
$( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )*
|
||||
$( id if id == &sym::$name => Some(BuiltinAttrExpander::$variant), )*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Builtin derives.
|
||||
|
||||
use intern::sym;
|
||||
use itertools::izip;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
@ -36,7 +37,7 @@ macro_rules! register_builtin {
|
|||
|
||||
fn find_by_name(name: &name::Name) -> Option<Self> {
|
||||
match name {
|
||||
$( id if id == &name::name![$trait] => Some(BuiltinDeriveExpander::$trait), )*
|
||||
$( id if id == &sym::$trait => Some(BuiltinDeriveExpander::$trait), )*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use base_db::{AnchoredPath, FileId};
|
||||
use cfg::CfgExpr;
|
||||
use either::Either;
|
||||
use intern::sym;
|
||||
use itertools::Itertools;
|
||||
use mbe::{parse_exprs_with_sep, parse_to_token_tree};
|
||||
use span::{Edition, Span, SpanAnchor, SyntaxContextId, ROOT_ERASED_FILE_AST_ID};
|
||||
|
@ -11,8 +12,7 @@ use syntax::ast::{self, AstToken};
|
|||
use crate::{
|
||||
db::ExpandDatabase,
|
||||
hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt},
|
||||
name::{self, known},
|
||||
quote,
|
||||
name, quote,
|
||||
quote::dollar_crate,
|
||||
tt::{self, DelimSpan},
|
||||
ExpandError, ExpandResult, HirFileIdExt, MacroCallId, MacroFileIdExt,
|
||||
|
@ -48,8 +48,8 @@ macro_rules! register_builtin {
|
|||
|
||||
fn find_by_name(ident: &name::Name) -> Option<Either<BuiltinFnLikeExpander, EagerExpander>> {
|
||||
match ident {
|
||||
$( id if id == &name::name![$name] => Some(Either::Left(BuiltinFnLikeExpander::$kind)), )*
|
||||
$( id if id == &name::name![$e_name] => Some(Either::Right(EagerExpander::$e_kind)), )*
|
||||
$( id if id == &sym::$name => Some(Either::Left(BuiltinFnLikeExpander::$kind)), )*
|
||||
$( id if id == &sym::$e_name => Some(Either::Right(EagerExpander::$e_kind)), )*
|
||||
_ => return None,
|
||||
}
|
||||
}
|
||||
|
@ -367,8 +367,11 @@ fn panic_expand(
|
|||
let dollar_crate = dollar_crate(span);
|
||||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
|
||||
let mac =
|
||||
if use_panic_2021(db, call_site_span) { known::panic_2021 } else { known::panic_2015 };
|
||||
let mac = if use_panic_2021(db, call_site_span) {
|
||||
sym::panic_2021.clone()
|
||||
} else {
|
||||
sym::panic_2015.clone()
|
||||
};
|
||||
|
||||
// Expand to a macro call `$crate::panic::panic_{edition}`
|
||||
let mut call = quote!(call_site_span =>#dollar_crate::panic::#mac!);
|
||||
|
@ -397,9 +400,9 @@ fn unreachable_expand(
|
|||
let call_site_span = span_with_call_site_ctxt(db, span, id);
|
||||
|
||||
let mac = if use_panic_2021(db, call_site_span) {
|
||||
known::unreachable_2021
|
||||
sym::unreachable_2021.clone()
|
||||
} else {
|
||||
known::unreachable_2015
|
||||
sym::unreachable_2015.clone()
|
||||
};
|
||||
|
||||
// Expand to a macro call `$crate::panic::panic_{edition}`
|
||||
|
@ -432,7 +435,7 @@ fn use_panic_2021(db: &dyn ExpandDatabase, span: Span) -> bool {
|
|||
// FIXME: Record allow_internal_unstable in the macro def (not been done yet because it
|
||||
// would consume quite a bit extra memory for all call locs...)
|
||||
// if let Some(features) = expn.def.allow_internal_unstable {
|
||||
// if features.iter().any(|&f| f == sym::edition_panic) {
|
||||
// if features.iter().any(|&f| f == sym::edition_panic.clone()) {
|
||||
// span = expn.call_site;
|
||||
// continue;
|
||||
// }
|
||||
|
|
|
@ -133,6 +133,15 @@ pub trait ExpandDatabase: SourceDatabase {
|
|||
&self,
|
||||
macro_call: MacroCallId,
|
||||
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
||||
#[salsa::transparent]
|
||||
fn syntax_context(&self, file: HirFileId) -> SyntaxContextId;
|
||||
}
|
||||
|
||||
fn syntax_context(db: &dyn ExpandDatabase, file: HirFileId) -> SyntaxContextId {
|
||||
match file.repr() {
|
||||
HirFileIdRepr::FileId(_) => SyntaxContextId::ROOT,
|
||||
HirFileIdRepr::MacroFile(m) => db.macro_arg(m.macro_call_id).2.ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/// This expands the given macro call, but with different arguments. This is
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use base_db::{CrateId, VersionReq};
|
||||
use intern::sym;
|
||||
use mbe::DocCommentDesugarMode;
|
||||
use span::{Edition, MacroCallId, Span, SyntaxContextId};
|
||||
use stdx::TupleExt;
|
||||
|
@ -111,8 +112,10 @@ impl DeclarativeMacroExpander {
|
|||
match &*attrs
|
||||
.iter()
|
||||
.find(|it| {
|
||||
it.path.as_ident().and_then(|it| it.as_str())
|
||||
== Some("rustc_macro_transparency")
|
||||
it.path
|
||||
.as_ident()
|
||||
.map(|it| *it == sym::rustc_macro_transparency.clone())
|
||||
.unwrap_or(false)
|
||||
})?
|
||||
.token_tree_value()?
|
||||
.token_trees
|
||||
|
|
|
@ -553,7 +553,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
),
|
||||
|
||||
BuiltinAttribute {
|
||||
// name: sym::rustc_diagnostic_item,
|
||||
// name: sym::rustc_diagnostic_item.clone(),
|
||||
name: "rustc_diagnostic_item",
|
||||
// FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
|
||||
// only_local: false,
|
||||
|
@ -562,7 +562,7 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
// duplicates: ErrorFollowing,
|
||||
// gate: Gated(
|
||||
// Stability::Unstable,
|
||||
// sym::rustc_attrs,
|
||||
// sym::rustc_attrs.clone(),
|
||||
// "diagnostic items compiler internal support for linting",
|
||||
// cfg_fn!(rustc_attrs),
|
||||
// ),
|
||||
|
|
|
@ -8,10 +8,11 @@ use std::{
|
|||
use crate::{
|
||||
db::ExpandDatabase,
|
||||
hygiene::{marks_rev, SyntaxContextExt, Transparency},
|
||||
name::{known, AsName, Name},
|
||||
name::{AsName, Name},
|
||||
tt,
|
||||
};
|
||||
use base_db::CrateId;
|
||||
use intern::sym;
|
||||
use smallvec::SmallVec;
|
||||
use span::SyntaxContextId;
|
||||
use syntax::{ast, AstNode};
|
||||
|
@ -106,10 +107,7 @@ impl ModPath {
|
|||
PathKind::Abs => 0,
|
||||
PathKind::DollarCrate(_) => "$crate".len(),
|
||||
};
|
||||
self.segments()
|
||||
.iter()
|
||||
.map(|segment| segment.as_str().map_or(0, str::len))
|
||||
.fold(base, core::ops::Add::add)
|
||||
self.segments().iter().map(|segment| segment.as_str().len()).fold(base, core::ops::Add::add)
|
||||
}
|
||||
|
||||
pub fn is_ident(&self) -> bool {
|
||||
|
@ -123,7 +121,7 @@ impl ModPath {
|
|||
#[allow(non_snake_case)]
|
||||
pub fn is_Self(&self) -> bool {
|
||||
self.kind == PathKind::Plain
|
||||
&& matches!(&*self.segments, [name] if *name == known::SELF_TYPE)
|
||||
&& matches!(&*self.segments, [name] if *name == sym::Self_.clone())
|
||||
}
|
||||
|
||||
/// If this path is a single identifier, like `foo`, return its name.
|
||||
|
@ -265,9 +263,10 @@ fn convert_path(
|
|||
res
|
||||
}
|
||||
}
|
||||
ast::PathSegmentKind::SelfTypeKw => {
|
||||
ModPath::from_segments(PathKind::Plain, Some(known::SELF_TYPE))
|
||||
}
|
||||
ast::PathSegmentKind::SelfTypeKw => ModPath::from_segments(
|
||||
PathKind::Plain,
|
||||
Some(Name::new_symbol(sym::Self_.clone(), SyntaxContextId::ROOT)),
|
||||
),
|
||||
ast::PathSegmentKind::CrateKw => ModPath::from_segments(PathKind::Crate, iter::empty()),
|
||||
ast::PathSegmentKind::SelfKw => handle_super_kw(0)?,
|
||||
ast::PathSegmentKind::SuperKw => handle_super_kw(1)?,
|
||||
|
@ -323,9 +322,9 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModP
|
|||
tt::Leaf::Ident(tt::Ident { text, .. }) if text == "self" => PathKind::SELF,
|
||||
tt::Leaf::Ident(tt::Ident { text, .. }) if text == "super" => {
|
||||
let mut deg = 1;
|
||||
while let Some(tt::Leaf::Ident(tt::Ident { text, .. })) = leaves.next() {
|
||||
while let Some(tt::Leaf::Ident(tt::Ident { text, span, .. })) = leaves.next() {
|
||||
if text != "super" {
|
||||
segments.push(Name::new_text_dont_use(text.clone()));
|
||||
segments.push(Name::new(text, span.ctx));
|
||||
break;
|
||||
}
|
||||
deg += 1;
|
||||
|
@ -334,13 +333,13 @@ fn convert_path_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModP
|
|||
}
|
||||
tt::Leaf::Ident(tt::Ident { text, .. }) if text == "crate" => PathKind::Crate,
|
||||
tt::Leaf::Ident(ident) => {
|
||||
segments.push(Name::new_text_dont_use(ident.text.clone()));
|
||||
segments.push(Name::new(&ident.text, ident.span.ctx));
|
||||
PathKind::Plain
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
segments.extend(leaves.filter_map(|leaf| match leaf {
|
||||
::tt::Leaf::Ident(ident) => Some(Name::new_text_dont_use(ident.text.clone())),
|
||||
::tt::Leaf::Ident(ident) => Some(Name::new(&ident.text, ident.span.ctx)),
|
||||
_ => None,
|
||||
}));
|
||||
Some(ModPath { kind, segments })
|
||||
|
@ -385,6 +384,8 @@ macro_rules! __known_path {
|
|||
(core::ops::RangeInclusive) => {};
|
||||
(core::future::Future) => {};
|
||||
(core::future::IntoFuture) => {};
|
||||
(core::fmt::Debug) => {};
|
||||
(std::fmt::format) => {};
|
||||
(core::ops::Try) => {};
|
||||
($path:path) => {
|
||||
compile_error!("Please register your known path in the path module")
|
||||
|
@ -396,7 +397,7 @@ macro_rules! __path {
|
|||
($start:ident $(:: $seg:ident)*) => ({
|
||||
$crate::__known_path!($start $(:: $seg)*);
|
||||
$crate::mod_path::ModPath::from_segments($crate::mod_path::PathKind::Abs, vec![
|
||||
$crate::mod_path::__name![$start], $($crate::mod_path::__name![$seg],)*
|
||||
$crate::name::Name::new_symbol_root(intern::sym::$start.clone()), $($crate::name::Name::new_symbol_root(intern::sym::$seg.clone()),)*
|
||||
])
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
use std::fmt;
|
||||
|
||||
use intern::{sym, Symbol};
|
||||
use span::SyntaxContextId;
|
||||
use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr};
|
||||
|
||||
/// `Name` is a wrapper around string, which is used in hir for both references
|
||||
|
@ -11,32 +13,58 @@ use syntax::{ast, format_smolstr, utils::is_raw_identifier, SmolStr};
|
|||
/// Note that `Name` holds and prints escaped name i.e. prefixed with "r#" when it
|
||||
/// is a raw identifier. Use [`unescaped()`][Name::unescaped] when you need the
|
||||
/// name without "r#".
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct Name(Repr);
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Name {
|
||||
symbol: Symbol,
|
||||
ctx: (),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Name")
|
||||
.field("symbol", &self.symbol.as_str())
|
||||
.field("ctx", &self.ctx)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Name {
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.symbol.as_str().cmp(other.symbol.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Name {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Symbol> for Name {
|
||||
fn eq(&self, sym: &Symbol) -> bool {
|
||||
self.symbol == *sym
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<Name> for Symbol {
|
||||
fn eq(&self, name: &Name) -> bool {
|
||||
*self == name.symbol
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper of `Name` to print the name without "r#" even when it is a raw identifier.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct UnescapedName<'a>(&'a Name);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
enum Repr {
|
||||
Text(SmolStr),
|
||||
TupleField(usize),
|
||||
}
|
||||
|
||||
impl UnescapedName<'_> {
|
||||
/// Returns the textual representation of this name as a [`SmolStr`]. Prefer using this over
|
||||
/// [`ToString::to_string`] if possible as this conversion is cheaper in the general case.
|
||||
pub fn to_smol_str(&self) -> SmolStr {
|
||||
match &self.0 .0 {
|
||||
Repr::Text(it) => {
|
||||
if let Some(stripped) = it.strip_prefix("r#") {
|
||||
SmolStr::new(stripped)
|
||||
} else {
|
||||
it.clone()
|
||||
}
|
||||
}
|
||||
Repr::TupleField(it) => SmolStr::new(it.to_string()),
|
||||
let it = self.0.symbol.as_str();
|
||||
if let Some(stripped) = it.strip_prefix("r#") {
|
||||
SmolStr::new(stripped)
|
||||
} else {
|
||||
it.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,27 +78,26 @@ impl Name {
|
|||
/// Note: this is private to make creating name from random string hard.
|
||||
/// Hopefully, this should allow us to integrate hygiene cleaner in the
|
||||
/// future, and to switch to interned representation of names.
|
||||
const fn new_text(text: SmolStr) -> Name {
|
||||
Name(Repr::Text(text))
|
||||
fn new_text(text: &str) -> Name {
|
||||
Name { symbol: Symbol::intern(text), ctx: () }
|
||||
}
|
||||
|
||||
// FIXME: See above, unfortunately some places really need this right now
|
||||
#[doc(hidden)]
|
||||
pub const fn new_text_dont_use(text: SmolStr) -> Name {
|
||||
Name(Repr::Text(text))
|
||||
pub fn new(text: &str, ctx: SyntaxContextId) -> Name {
|
||||
_ = ctx;
|
||||
Name { symbol: Symbol::intern(text), ctx: () }
|
||||
}
|
||||
|
||||
pub fn new_tuple_field(idx: usize) -> Name {
|
||||
Name(Repr::TupleField(idx))
|
||||
Name { symbol: Symbol::intern(&idx.to_string()), ctx: () }
|
||||
}
|
||||
|
||||
pub fn new_lifetime(lt: &ast::Lifetime) -> Name {
|
||||
Self::new_text(lt.text().into())
|
||||
Name { symbol: Symbol::intern(lt.text().as_str()), ctx: () }
|
||||
}
|
||||
|
||||
/// Shortcut to create a name from a string literal.
|
||||
const fn new_static(text: &'static str) -> Name {
|
||||
Name::new_text(SmolStr::new_static(text))
|
||||
fn new_ref(text: &str) -> Name {
|
||||
Name { symbol: Symbol::intern(text), ctx: () }
|
||||
}
|
||||
|
||||
/// Resolve a name from the text of token.
|
||||
|
@ -78,14 +105,14 @@ impl Name {
|
|||
match raw_text.strip_prefix("r#") {
|
||||
// When `raw_text` starts with "r#" but the name does not coincide with any
|
||||
// keyword, we never need the prefix so we strip it.
|
||||
Some(text) if !is_raw_identifier(text) => Name::new_text(SmolStr::new(text)),
|
||||
Some(text) if !is_raw_identifier(text) => Name::new_ref(text),
|
||||
// Keywords (in the current edition) *can* be used as a name in earlier editions of
|
||||
// Rust, e.g. "try" in Rust 2015. Even in such cases, we keep track of them in their
|
||||
// escaped form.
|
||||
None if is_raw_identifier(raw_text) => {
|
||||
Name::new_text(format_smolstr!("r#{}", raw_text))
|
||||
Name::new_text(&format_smolstr!("r#{}", raw_text))
|
||||
}
|
||||
_ => Name::new_text(raw_text.into()),
|
||||
_ => Name::new_text(raw_text),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,8 +125,8 @@ impl Name {
|
|||
/// Ideally, we want a `gensym` semantics for missing names -- each missing
|
||||
/// name is equal only to itself. It's not clear how to implement this in
|
||||
/// salsa though, so we punt on that bit for a moment.
|
||||
pub const fn missing() -> Name {
|
||||
Name::new_static("[missing name]")
|
||||
pub fn missing() -> Name {
|
||||
Name { symbol: sym::MISSING_NAME.clone(), ctx: () }
|
||||
}
|
||||
|
||||
/// Returns true if this is a fake name for things missing in the source code. See
|
||||
|
@ -115,41 +142,25 @@ impl Name {
|
|||
/// creating desugared locals and labels. The caller is responsible for picking an index
|
||||
/// that is stable across re-executions
|
||||
pub fn generate_new_name(idx: usize) -> Name {
|
||||
Name::new_text(format_smolstr!("<ra@gennew>{idx}"))
|
||||
Name::new_text(&format_smolstr!("<ra@gennew>{idx}"))
|
||||
}
|
||||
|
||||
/// Returns the tuple index this name represents if it is a tuple field.
|
||||
pub fn as_tuple_index(&self) -> Option<usize> {
|
||||
match self.0 {
|
||||
Repr::TupleField(idx) => Some(idx),
|
||||
_ => None,
|
||||
}
|
||||
self.symbol.as_str().parse().ok()
|
||||
}
|
||||
|
||||
/// Returns the text this name represents if it isn't a tuple field.
|
||||
pub fn as_text(&self) -> Option<SmolStr> {
|
||||
match &self.0 {
|
||||
Repr::Text(it) => Some(it.clone()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the text this name represents if it isn't a tuple field.
|
||||
pub fn as_str(&self) -> Option<&str> {
|
||||
match &self.0 {
|
||||
Repr::Text(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.symbol.as_str()
|
||||
}
|
||||
|
||||
// FIXME: Remove this
|
||||
/// Returns the textual representation of this name as a [`SmolStr`].
|
||||
/// Prefer using this over [`ToString::to_string`] if possible as this conversion is cheaper in
|
||||
/// the general case.
|
||||
pub fn to_smol_str(&self) -> SmolStr {
|
||||
match &self.0 {
|
||||
Repr::Text(it) => it.clone(),
|
||||
Repr::TupleField(it) => SmolStr::new(it.to_string()),
|
||||
}
|
||||
self.symbol.as_str().into()
|
||||
}
|
||||
|
||||
pub fn unescaped(&self) -> UnescapedName<'_> {
|
||||
|
@ -157,16 +168,27 @@ impl Name {
|
|||
}
|
||||
|
||||
pub fn is_escaped(&self) -> bool {
|
||||
match &self.0 {
|
||||
Repr::Text(it) => it.starts_with("r#"),
|
||||
Repr::TupleField(_) => false,
|
||||
}
|
||||
self.symbol.as_str().starts_with("r#")
|
||||
}
|
||||
|
||||
pub fn display<'a>(&'a self, db: &dyn crate::db::ExpandDatabase) -> impl fmt::Display + 'a {
|
||||
_ = db;
|
||||
Display { name: self }
|
||||
}
|
||||
|
||||
pub fn symbol(&self) -> &Symbol {
|
||||
&self.symbol
|
||||
}
|
||||
|
||||
pub const fn new_symbol(doc: Symbol, ctx: SyntaxContextId) -> Self {
|
||||
_ = ctx;
|
||||
Self { symbol: doc, ctx: () }
|
||||
}
|
||||
|
||||
// FIXME: This needs to go once we have hygiene
|
||||
pub const fn new_symbol_root(doc: Symbol) -> Self {
|
||||
Self { symbol: doc, ctx: () }
|
||||
}
|
||||
}
|
||||
|
||||
struct Display<'a> {
|
||||
|
@ -175,10 +197,7 @@ struct Display<'a> {
|
|||
|
||||
impl fmt::Display for Display<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.name.0 {
|
||||
Repr::Text(text) => fmt::Display::fmt(&text, f),
|
||||
Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
|
||||
}
|
||||
fmt::Display::fmt(self.name.symbol.as_str(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,13 +207,9 @@ struct UnescapedDisplay<'a> {
|
|||
|
||||
impl fmt::Display for UnescapedDisplay<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self.name.0 .0 {
|
||||
Repr::Text(text) => {
|
||||
let text = text.strip_prefix("r#").unwrap_or(text);
|
||||
fmt::Display::fmt(&text, f)
|
||||
}
|
||||
Repr::TupleField(idx) => fmt::Display::fmt(&idx, f),
|
||||
}
|
||||
let symbol = &self.name.0.symbol.as_str();
|
||||
let text = symbol.strip_prefix("r#").unwrap_or(symbol);
|
||||
fmt::Display::fmt(&text, f)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,251 +261,6 @@ impl AsName for ast::FieldKind {
|
|||
|
||||
impl AsName for base_db::Dependency {
|
||||
fn as_name(&self) -> Name {
|
||||
Name::new_text(SmolStr::new(&*self.name))
|
||||
Name::new_text(&self.name)
|
||||
}
|
||||
}
|
||||
|
||||
pub mod known {
|
||||
macro_rules! known_names {
|
||||
($($ident:ident),* $(,)?) => {
|
||||
$(
|
||||
#[allow(bad_style)]
|
||||
pub const $ident: super::Name =
|
||||
super::Name::new_static(stringify!($ident));
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
known_names!(
|
||||
// Primitives
|
||||
isize,
|
||||
i8,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i128,
|
||||
usize,
|
||||
u8,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u128,
|
||||
f16,
|
||||
f32,
|
||||
f64,
|
||||
f128,
|
||||
bool,
|
||||
char,
|
||||
str,
|
||||
// Special names
|
||||
macro_rules,
|
||||
doc,
|
||||
cfg,
|
||||
cfg_attr,
|
||||
register_attr,
|
||||
register_tool,
|
||||
// Components of known path (value or mod name)
|
||||
std,
|
||||
core,
|
||||
alloc,
|
||||
iter,
|
||||
ops,
|
||||
fmt,
|
||||
future,
|
||||
result,
|
||||
string,
|
||||
boxed,
|
||||
option,
|
||||
prelude,
|
||||
rust_2015,
|
||||
rust_2018,
|
||||
rust_2021,
|
||||
rust_2024,
|
||||
v1,
|
||||
new_display,
|
||||
new_debug,
|
||||
new_lower_exp,
|
||||
new_upper_exp,
|
||||
new_octal,
|
||||
new_pointer,
|
||||
new_binary,
|
||||
new_lower_hex,
|
||||
new_upper_hex,
|
||||
from_usize,
|
||||
panic_2015,
|
||||
panic_2021,
|
||||
unreachable_2015,
|
||||
unreachable_2021,
|
||||
// Components of known path (type name)
|
||||
Iterator,
|
||||
IntoIterator,
|
||||
Item,
|
||||
IntoIter,
|
||||
Try,
|
||||
Ok,
|
||||
Future,
|
||||
IntoFuture,
|
||||
Result,
|
||||
Option,
|
||||
Output,
|
||||
Target,
|
||||
Box,
|
||||
RangeFrom,
|
||||
RangeFull,
|
||||
RangeInclusive,
|
||||
RangeToInclusive,
|
||||
RangeTo,
|
||||
Range,
|
||||
String,
|
||||
Neg,
|
||||
Not,
|
||||
None,
|
||||
Index,
|
||||
Left,
|
||||
Right,
|
||||
Center,
|
||||
Unknown,
|
||||
Is,
|
||||
Param,
|
||||
Implied,
|
||||
// Components of known path (function name)
|
||||
filter_map,
|
||||
next,
|
||||
iter_mut,
|
||||
len,
|
||||
is_empty,
|
||||
as_str,
|
||||
new,
|
||||
new_v1_formatted,
|
||||
none,
|
||||
// Builtin macros
|
||||
asm,
|
||||
assert,
|
||||
column,
|
||||
compile_error,
|
||||
concat_idents,
|
||||
concat_bytes,
|
||||
concat,
|
||||
const_format_args,
|
||||
core_panic,
|
||||
env,
|
||||
file,
|
||||
format,
|
||||
format_args_nl,
|
||||
format_args,
|
||||
global_asm,
|
||||
include_bytes,
|
||||
include_str,
|
||||
include,
|
||||
line,
|
||||
llvm_asm,
|
||||
log_syntax,
|
||||
module_path,
|
||||
option_env,
|
||||
quote,
|
||||
std_panic,
|
||||
stringify,
|
||||
trace_macros,
|
||||
unreachable,
|
||||
// Builtin derives
|
||||
Copy,
|
||||
Clone,
|
||||
Default,
|
||||
Debug,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialOrd,
|
||||
Eq,
|
||||
PartialEq,
|
||||
// Builtin attributes
|
||||
bench,
|
||||
cfg_accessible,
|
||||
cfg_eval,
|
||||
crate_type,
|
||||
derive,
|
||||
derive_const,
|
||||
global_allocator,
|
||||
no_core,
|
||||
no_std,
|
||||
test,
|
||||
test_case,
|
||||
recursion_limit,
|
||||
feature,
|
||||
// known methods of lang items
|
||||
call_once,
|
||||
call_mut,
|
||||
call,
|
||||
eq,
|
||||
ne,
|
||||
ge,
|
||||
gt,
|
||||
le,
|
||||
lt,
|
||||
// known fields of lang items
|
||||
pieces,
|
||||
// lang items
|
||||
add_assign,
|
||||
add,
|
||||
bitand_assign,
|
||||
bitand,
|
||||
bitor_assign,
|
||||
bitor,
|
||||
bitxor_assign,
|
||||
bitxor,
|
||||
branch,
|
||||
deref_mut,
|
||||
deref,
|
||||
div_assign,
|
||||
div,
|
||||
drop,
|
||||
fn_mut,
|
||||
fn_once,
|
||||
future_trait,
|
||||
index,
|
||||
index_mut,
|
||||
into_future,
|
||||
mul_assign,
|
||||
mul,
|
||||
neg,
|
||||
not,
|
||||
owned_box,
|
||||
partial_ord,
|
||||
poll,
|
||||
r#fn,
|
||||
rem_assign,
|
||||
rem,
|
||||
shl_assign,
|
||||
shl,
|
||||
shr_assign,
|
||||
shr,
|
||||
sub_assign,
|
||||
sub,
|
||||
unsafe_cell,
|
||||
va_list
|
||||
);
|
||||
|
||||
// self/Self cannot be used as an identifier
|
||||
pub const SELF_PARAM: super::Name = super::Name::new_static("self");
|
||||
pub const SELF_TYPE: super::Name = super::Name::new_static("Self");
|
||||
|
||||
pub const STATIC_LIFETIME: super::Name = super::Name::new_static("'static");
|
||||
pub const DOLLAR_CRATE: super::Name = super::Name::new_static("$crate");
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! name {
|
||||
(self) => {
|
||||
$crate::name::known::SELF_PARAM
|
||||
};
|
||||
(Self) => {
|
||||
$crate::name::known::SELF_TYPE
|
||||
};
|
||||
('static) => {
|
||||
$crate::name::known::STATIC_LIFETIME
|
||||
};
|
||||
($ident:ident) => {
|
||||
$crate::name::known::$ident
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub use crate::name;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//! A simplified version of quote-crate like quasi quote macro
|
||||
#![allow(clippy::crate_in_macro_def)]
|
||||
|
||||
use intern::Symbol;
|
||||
use span::Span;
|
||||
use syntax::format_smolstr;
|
||||
|
||||
|
@ -219,6 +220,7 @@ impl_to_to_tokentrees! {
|
|||
span: &str => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}};
|
||||
span: String => self { crate::tt::Literal{text: format_smolstr!("\"{}\"", self.escape_default()), span}};
|
||||
span: Name => self { crate::tt::Ident{text: self.to_smol_str(), span}};
|
||||
span: Symbol => self { crate::tt::Ident{text: self.as_str().into(), span}};
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
use chalk_ir::cast::Cast;
|
||||
use hir_def::lang_item::LangItem;
|
||||
use hir_expand::name::name;
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use limit::Limit;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -151,7 +152,9 @@ pub(crate) fn deref_by_trait(
|
|||
|
||||
let deref_trait =
|
||||
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
|
||||
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
|
||||
let target = db
|
||||
.trait_data(deref_trait)
|
||||
.associated_type_by_name(&Name::new_symbol_root(sym::Target.clone()))?;
|
||||
|
||||
let projection = {
|
||||
let b = TyBuilder::subst_for_def(db, deref_trait, None);
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
use core::ops;
|
||||
use std::{iter, ops::ControlFlow, sync::Arc};
|
||||
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use tracing::debug;
|
||||
|
||||
use chalk_ir::{cast::Caster, fold::shift::Shift, CanonicalVarKinds};
|
||||
|
@ -16,7 +18,6 @@ use hir_def::{
|
|||
AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
|
||||
TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::name;
|
||||
|
||||
use crate::{
|
||||
db::{HirDatabase, InternedCoroutine},
|
||||
|
@ -288,15 +289,16 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
|
|||
chalk_ir::Binders::new(binders, bound)
|
||||
}
|
||||
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
|
||||
if let Some((future_trait, future_output)) = self
|
||||
.db
|
||||
.lang_item(self.krate, LangItem::Future)
|
||||
.and_then(|item| item.as_trait())
|
||||
.and_then(|trait_| {
|
||||
let alias =
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])?;
|
||||
Some((trait_, alias))
|
||||
})
|
||||
if let Some((future_trait, future_output)) =
|
||||
self.db
|
||||
.lang_item(self.krate, LangItem::Future)
|
||||
.and_then(|item| item.as_trait())
|
||||
.and_then(|trait_| {
|
||||
let alias = self.db.trait_data(trait_).associated_type_by_name(
|
||||
&Name::new_symbol_root(sym::Output.clone()),
|
||||
)?;
|
||||
Some((trait_, alias))
|
||||
})
|
||||
{
|
||||
// Making up Symbol’s value as variable is void: AsyncBlock<T>:
|
||||
//
|
||||
|
|
|
@ -247,7 +247,7 @@ impl<'a> DeclValidator<'a> {
|
|||
// Check the module name.
|
||||
let Some(module_name) = module_id.name(self.db.upcast()) else { return };
|
||||
let Some(module_name_replacement) =
|
||||
module_name.as_str().and_then(to_lower_snake_case).map(|new_name| Replacement {
|
||||
to_lower_snake_case(module_name.as_str()).map(|new_name| Replacement {
|
||||
current_name: module_name,
|
||||
suggested_text: new_name,
|
||||
expected_case: CaseType::LowerSnakeCase,
|
||||
|
|
|
@ -8,7 +8,7 @@ use either::Either;
|
|||
use hir_def::lang_item::LangItem;
|
||||
use hir_def::{resolver::HasResolver, AdtId, AssocItemId, DefWithBodyId, HasModule};
|
||||
use hir_def::{ItemContainerId, Lookup};
|
||||
use hir_expand::name;
|
||||
use intern::sym;
|
||||
use itertools::Itertools;
|
||||
use rustc_hash::FxHashSet;
|
||||
use rustc_pattern_analysis::constructor::Constructor;
|
||||
|
@ -423,7 +423,9 @@ impl FilterMapNextChecker {
|
|||
ItemContainerId::TraitId(iterator_trait_id) => {
|
||||
let iterator_trait_items = &db.trait_data(iterator_trait_id).items;
|
||||
iterator_trait_items.iter().find_map(|(name, it)| match it {
|
||||
&AssocItemId::FunctionId(id) if *name == name![filter_map] => Some(id),
|
||||
&AssocItemId::FunctionId(id) if *name == sym::filter_map.clone() => {
|
||||
Some(id)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ use hir_def::{
|
|||
ModuleId, TraitId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::{Internable, Interned};
|
||||
use intern::{sym, Internable, Interned};
|
||||
use itertools::Itertools;
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_apfloat::{
|
||||
|
@ -1171,7 +1171,9 @@ impl HirDisplay for Ty {
|
|||
.lang_item(body.module(db.upcast()).krate(), LangItem::Future)
|
||||
.and_then(LangItemTarget::as_trait);
|
||||
let output = future_trait.and_then(|t| {
|
||||
db.trait_data(t).associated_type_by_name(&hir_expand::name!(Output))
|
||||
db.trait_data(t).associated_type_by_name(&Name::new_symbol_root(
|
||||
sym::Output.clone(),
|
||||
))
|
||||
});
|
||||
write!(f, "impl ")?;
|
||||
if let Some(t) = future_trait {
|
||||
|
|
|
@ -46,8 +46,9 @@ use hir_def::{
|
|||
AdtId, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, Lookup, TraitId,
|
||||
TupleFieldId, TupleId, TypeAliasId, VariantId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use hir_expand::name::Name;
|
||||
use indexmap::IndexSet;
|
||||
use intern::sym;
|
||||
use la_arena::{ArenaMap, Entry};
|
||||
use once_cell::unsync::OnceCell;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
@ -1424,7 +1425,9 @@ impl<'a> InferenceContext<'a> {
|
|||
}
|
||||
|
||||
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
|
||||
self.db.trait_data(trait_).associated_type_by_name(&name![Output])
|
||||
self.db
|
||||
.trait_data(trait_)
|
||||
.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))
|
||||
}
|
||||
|
||||
fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
|
||||
|
|
|
@ -15,7 +15,8 @@ use hir_def::{
|
|||
resolver::{resolver_for_expr, ResolveValueResult, ValueNs},
|
||||
DefWithBodyId, FieldId, HasModule, TupleFieldId, TupleId, VariantId,
|
||||
};
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use stdx::never;
|
||||
|
@ -268,9 +269,7 @@ impl CapturedItem {
|
|||
}
|
||||
let variant_data = f.parent.variant_data(db.upcast());
|
||||
let field = match &*variant_data {
|
||||
VariantData::Record(fields) => {
|
||||
fields[f.local_id].name.as_str().unwrap_or("[missing field]").to_owned()
|
||||
}
|
||||
VariantData::Record(fields) => fields[f.local_id].name.as_str().to_owned(),
|
||||
VariantData::Tuple(fields) => fields
|
||||
.iter()
|
||||
.position(|it| it.0 == f.local_id)
|
||||
|
@ -621,8 +620,10 @@ impl InferenceContext<'_> {
|
|||
if let Some(deref_trait) =
|
||||
self.resolve_lang_item(LangItem::DerefMut).and_then(|it| it.as_trait())
|
||||
{
|
||||
if let Some(deref_fn) =
|
||||
self.db.trait_data(deref_trait).method_by_name(&name![deref_mut])
|
||||
if let Some(deref_fn) = self
|
||||
.db
|
||||
.trait_data(deref_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut.clone()))
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@ use hir_def::{
|
|||
path::{GenericArgs, Path},
|
||||
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use stdx::always;
|
||||
use syntax::ast::RangeOp;
|
||||
|
||||
|
@ -646,8 +647,10 @@ impl InferenceContext<'_> {
|
|||
match op {
|
||||
UnaryOp::Deref => {
|
||||
if let Some(deref_trait) = self.resolve_lang_trait(LangItem::Deref) {
|
||||
if let Some(deref_fn) =
|
||||
self.db.trait_data(deref_trait).method_by_name(&name![deref])
|
||||
if let Some(deref_fn) = self
|
||||
.db
|
||||
.trait_data(deref_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref.clone()))
|
||||
{
|
||||
// FIXME: this is wrong in multiple ways, subst is empty, and we emit it even for builtin deref (note that
|
||||
// the mutability is not wrong, and will be fixed in `self.infer_mut`).
|
||||
|
@ -785,8 +788,10 @@ impl InferenceContext<'_> {
|
|||
// mutability will be fixed up in `InferenceContext::infer_mut`;
|
||||
adj.push(Adjustment::borrow(Mutability::Not, self_ty.clone()));
|
||||
self.write_expr_adj(*base, adj);
|
||||
if let Some(func) =
|
||||
self.db.trait_data(index_trait).method_by_name(&name!(index))
|
||||
if let Some(func) = self
|
||||
.db
|
||||
.trait_data(index_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::index.clone()))
|
||||
{
|
||||
let substs = TyBuilder::subst_for_def(self.db, index_trait, None)
|
||||
.push(self_ty.clone())
|
||||
|
|
|
@ -6,7 +6,8 @@ use hir_def::{
|
|||
hir::{Array, BinaryOp, BindingAnnotation, Expr, ExprId, PatId, Statement, UnaryOp},
|
||||
lang_item::LangItem,
|
||||
};
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
|
||||
use crate::{lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, OverloadedDeref};
|
||||
|
||||
|
@ -108,8 +109,10 @@ impl InferenceContext<'_> {
|
|||
.lang_item(self.table.trait_env.krate, LangItem::IndexMut)
|
||||
.and_then(|l| l.as_trait())
|
||||
{
|
||||
if let Some(index_fn) =
|
||||
self.db.trait_data(index_trait).method_by_name(&name![index_mut])
|
||||
if let Some(index_fn) = self
|
||||
.db
|
||||
.trait_data(index_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::index_mut.clone()))
|
||||
{
|
||||
*f = index_fn;
|
||||
let base_adjustments = self
|
||||
|
@ -139,8 +142,10 @@ impl InferenceContext<'_> {
|
|||
.lang_item(self.table.trait_env.krate, LangItem::DerefMut)
|
||||
.and_then(|l| l.as_trait())
|
||||
{
|
||||
if let Some(deref_fn) =
|
||||
self.db.trait_data(deref_trait).method_by_name(&name![deref_mut])
|
||||
if let Some(deref_fn) = self
|
||||
.db
|
||||
.trait_data(deref_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut.clone()))
|
||||
{
|
||||
*f = deref_fn;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use hir_def::{
|
|||
AdtId, AssocItemId, GenericDefId, ItemContainerId, Lookup,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use stdx::never;
|
||||
|
||||
use crate::{
|
||||
|
@ -227,7 +228,7 @@ impl InferenceContext<'_> {
|
|||
Path::LangItem(..) => (
|
||||
PathSegment {
|
||||
name: {
|
||||
_d = hir_expand::name::known::Unknown;
|
||||
_d = Name::new_symbol_root(sym::Unknown.clone());
|
||||
&_d
|
||||
},
|
||||
args_and_bindings: None,
|
||||
|
|
|
@ -9,7 +9,8 @@ use chalk_ir::{
|
|||
use chalk_solve::infer::ParameterEnaVariableExt;
|
||||
use either::Either;
|
||||
use ena::unify::UnifyKey;
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::SmallVec;
|
||||
use triomphe::Arc;
|
||||
|
@ -781,7 +782,8 @@ impl<'a> InferenceTable<'a> {
|
|||
let krate = self.trait_env.krate;
|
||||
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
||||
let trait_data = self.db.trait_data(fn_once_trait);
|
||||
let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
|
||||
let output_assoc_type =
|
||||
trait_data.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
|
||||
|
||||
let mut arg_tys = Vec::with_capacity(num_args);
|
||||
let arg_ty = TyBuilder::tuple(num_args)
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use hir_def::{data::adt::StructFlags, lang_item::LangItem, AdtId};
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
|
||||
use crate::db::HirDatabase;
|
||||
|
||||
|
@ -16,48 +17,57 @@ pub fn is_unsafe_cell(db: &dyn HirDatabase, adt: AdtId) -> bool {
|
|||
}
|
||||
|
||||
pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Name, LangItem)> {
|
||||
use hir_expand::name;
|
||||
use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering};
|
||||
Some(match op {
|
||||
BinaryOp::LogicOp(_) => return None,
|
||||
BinaryOp::ArithOp(aop) => match aop {
|
||||
ArithOp::Add => (name![add], LangItem::Add),
|
||||
ArithOp::Mul => (name![mul], LangItem::Mul),
|
||||
ArithOp::Sub => (name![sub], LangItem::Sub),
|
||||
ArithOp::Div => (name![div], LangItem::Div),
|
||||
ArithOp::Rem => (name![rem], LangItem::Rem),
|
||||
ArithOp::Shl => (name![shl], LangItem::Shl),
|
||||
ArithOp::Shr => (name![shr], LangItem::Shr),
|
||||
ArithOp::BitXor => (name![bitxor], LangItem::BitXor),
|
||||
ArithOp::BitOr => (name![bitor], LangItem::BitOr),
|
||||
ArithOp::BitAnd => (name![bitand], LangItem::BitAnd),
|
||||
ArithOp::Add => (Name::new_symbol_root(sym::add.clone()), LangItem::Add),
|
||||
ArithOp::Mul => (Name::new_symbol_root(sym::mul.clone()), LangItem::Mul),
|
||||
ArithOp::Sub => (Name::new_symbol_root(sym::sub.clone()), LangItem::Sub),
|
||||
ArithOp::Div => (Name::new_symbol_root(sym::div.clone()), LangItem::Div),
|
||||
ArithOp::Rem => (Name::new_symbol_root(sym::rem.clone()), LangItem::Rem),
|
||||
ArithOp::Shl => (Name::new_symbol_root(sym::shl.clone()), LangItem::Shl),
|
||||
ArithOp::Shr => (Name::new_symbol_root(sym::shr.clone()), LangItem::Shr),
|
||||
ArithOp::BitXor => (Name::new_symbol_root(sym::bitxor.clone()), LangItem::BitXor),
|
||||
ArithOp::BitOr => (Name::new_symbol_root(sym::bitor.clone()), LangItem::BitOr),
|
||||
ArithOp::BitAnd => (Name::new_symbol_root(sym::bitand.clone()), LangItem::BitAnd),
|
||||
},
|
||||
BinaryOp::Assignment { op: Some(aop) } => match aop {
|
||||
ArithOp::Add => (name![add_assign], LangItem::AddAssign),
|
||||
ArithOp::Mul => (name![mul_assign], LangItem::MulAssign),
|
||||
ArithOp::Sub => (name![sub_assign], LangItem::SubAssign),
|
||||
ArithOp::Div => (name![div_assign], LangItem::DivAssign),
|
||||
ArithOp::Rem => (name![rem_assign], LangItem::RemAssign),
|
||||
ArithOp::Shl => (name![shl_assign], LangItem::ShlAssign),
|
||||
ArithOp::Shr => (name![shr_assign], LangItem::ShrAssign),
|
||||
ArithOp::BitXor => (name![bitxor_assign], LangItem::BitXorAssign),
|
||||
ArithOp::BitOr => (name![bitor_assign], LangItem::BitOrAssign),
|
||||
ArithOp::BitAnd => (name![bitand_assign], LangItem::BitAndAssign),
|
||||
ArithOp::Add => (Name::new_symbol_root(sym::add_assign.clone()), LangItem::AddAssign),
|
||||
ArithOp::Mul => (Name::new_symbol_root(sym::mul_assign.clone()), LangItem::MulAssign),
|
||||
ArithOp::Sub => (Name::new_symbol_root(sym::sub_assign.clone()), LangItem::SubAssign),
|
||||
ArithOp::Div => (Name::new_symbol_root(sym::div_assign.clone()), LangItem::DivAssign),
|
||||
ArithOp::Rem => (Name::new_symbol_root(sym::rem_assign.clone()), LangItem::RemAssign),
|
||||
ArithOp::Shl => (Name::new_symbol_root(sym::shl_assign.clone()), LangItem::ShlAssign),
|
||||
ArithOp::Shr => (Name::new_symbol_root(sym::shr_assign.clone()), LangItem::ShrAssign),
|
||||
ArithOp::BitXor => {
|
||||
(Name::new_symbol_root(sym::bitxor_assign.clone()), LangItem::BitXorAssign)
|
||||
}
|
||||
ArithOp::BitOr => {
|
||||
(Name::new_symbol_root(sym::bitor_assign.clone()), LangItem::BitOrAssign)
|
||||
}
|
||||
ArithOp::BitAnd => {
|
||||
(Name::new_symbol_root(sym::bitand_assign.clone()), LangItem::BitAndAssign)
|
||||
}
|
||||
},
|
||||
BinaryOp::CmpOp(cop) => match cop {
|
||||
CmpOp::Eq { negated: false } => (name![eq], LangItem::PartialEq),
|
||||
CmpOp::Eq { negated: true } => (name![ne], LangItem::PartialEq),
|
||||
CmpOp::Eq { negated: false } => {
|
||||
(Name::new_symbol_root(sym::eq.clone()), LangItem::PartialEq)
|
||||
}
|
||||
CmpOp::Eq { negated: true } => {
|
||||
(Name::new_symbol_root(sym::ne.clone()), LangItem::PartialEq)
|
||||
}
|
||||
CmpOp::Ord { ordering: Ordering::Less, strict: false } => {
|
||||
(name![le], LangItem::PartialOrd)
|
||||
(Name::new_symbol_root(sym::le.clone()), LangItem::PartialOrd)
|
||||
}
|
||||
CmpOp::Ord { ordering: Ordering::Less, strict: true } => {
|
||||
(name![lt], LangItem::PartialOrd)
|
||||
(Name::new_symbol_root(sym::lt.clone()), LangItem::PartialOrd)
|
||||
}
|
||||
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => {
|
||||
(name![ge], LangItem::PartialOrd)
|
||||
(Name::new_symbol_root(sym::ge.clone()), LangItem::PartialOrd)
|
||||
}
|
||||
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => {
|
||||
(name![gt], LangItem::PartialOrd)
|
||||
(Name::new_symbol_root(sym::gt.clone()), LangItem::PartialOrd)
|
||||
}
|
||||
},
|
||||
BinaryOp::Assignment { op: None } => return None,
|
||||
|
|
|
@ -61,7 +61,8 @@ use chalk_ir::{
|
|||
};
|
||||
use either::Either;
|
||||
use hir_def::{hir::ExprId, type_ref::Rawness, CallableDefId, GeneralConstId, TypeOrConstParamId};
|
||||
use hir_expand::name;
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use la_arena::{Arena, Idx};
|
||||
use mir::{MirEvalError, VTableMap};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
@ -894,7 +895,9 @@ pub fn callable_sig_from_fn_trait(
|
|||
) -> Option<(FnTrait, CallableSig)> {
|
||||
let krate = trait_env.krate;
|
||||
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
|
||||
let output_assoc_type = db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
|
||||
let output_assoc_type = db
|
||||
.trait_data(fn_once_trait)
|
||||
.associated_type_by_name(&Name::new_symbol_root(sym::Output.clone()))?;
|
||||
|
||||
let mut table = InferenceTable::new(db, trait_env.clone());
|
||||
let b = TyBuilder::trait_ref(db, fn_once_trait);
|
||||
|
|
|
@ -14,8 +14,8 @@ use hir_def::{
|
|||
AdtId, ConstId, DefWithBodyId, EnumVariantId, FunctionId, HasModule, ItemContainerId, Lookup,
|
||||
StaticId, VariantId,
|
||||
};
|
||||
use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile};
|
||||
use intern::Interned;
|
||||
use hir_expand::{mod_path::path, name::Name, HirFileIdExt, InFile};
|
||||
use intern::{sym, Interned};
|
||||
use la_arena::ArenaMap;
|
||||
use rustc_abi::TargetDataLayout;
|
||||
use rustc_apfloat::{
|
||||
|
@ -35,7 +35,7 @@ use crate::{
|
|||
layout::{Layout, LayoutError, RustcEnumVariantIdx},
|
||||
mapping::from_chalk,
|
||||
method_resolution::{is_dyn_method, lookup_impl_const},
|
||||
name, static_lifetime,
|
||||
static_lifetime,
|
||||
traits::FnTrait,
|
||||
utils::{detect_variant_from_bytes, ClosureSubst},
|
||||
CallableDefId, ClosureId, ComplexMemoryMap, Const, ConstScalar, FnDefId, Interner, MemoryMap,
|
||||
|
@ -631,15 +631,21 @@ impl Evaluator<'_> {
|
|||
cached_fn_trait_func: db
|
||||
.lang_item(crate_id, LangItem::Fn)
|
||||
.and_then(|x| x.as_trait())
|
||||
.and_then(|x| db.trait_data(x).method_by_name(&name![call])),
|
||||
.and_then(|x| {
|
||||
db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call.clone()))
|
||||
}),
|
||||
cached_fn_mut_trait_func: db
|
||||
.lang_item(crate_id, LangItem::FnMut)
|
||||
.and_then(|x| x.as_trait())
|
||||
.and_then(|x| db.trait_data(x).method_by_name(&name![call_mut])),
|
||||
.and_then(|x| {
|
||||
db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_mut.clone()))
|
||||
}),
|
||||
cached_fn_once_trait_func: db
|
||||
.lang_item(crate_id, LangItem::FnOnce)
|
||||
.and_then(|x| x.as_trait())
|
||||
.and_then(|x| db.trait_data(x).method_by_name(&name![call_once])),
|
||||
.and_then(|x| {
|
||||
db.trait_data(x).method_by_name(&Name::new_symbol_root(sym::call_once.clone()))
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -2633,10 +2639,7 @@ impl Evaluator<'_> {
|
|||
let static_data = self.db.static_data(st);
|
||||
let result = if !static_data.is_extern {
|
||||
let konst = self.db.const_eval_static(st).map_err(|e| {
|
||||
MirEvalError::ConstEvalError(
|
||||
static_data.name.as_str().unwrap_or("_").to_owned(),
|
||||
Box::new(e),
|
||||
)
|
||||
MirEvalError::ConstEvalError(static_data.name.as_str().to_owned(), Box::new(e))
|
||||
})?;
|
||||
self.allocate_const_in_heap(locals, &konst)?
|
||||
} else {
|
||||
|
@ -2693,7 +2696,7 @@ impl Evaluator<'_> {
|
|||
) -> Result<()> {
|
||||
let Some(drop_fn) = (|| {
|
||||
let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?;
|
||||
self.db.trait_data(drop_trait).method_by_name(&name![drop])
|
||||
self.db.trait_data(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop.clone()))
|
||||
})() else {
|
||||
// in some tests we don't have drop trait in minicore, and
|
||||
// we can ignore drop in them.
|
||||
|
@ -2797,14 +2800,13 @@ pub fn render_const_using_debug_impl(
|
|||
let resolver = owner.resolver(db.upcast());
|
||||
let Some(TypeNs::TraitId(debug_trait)) = resolver.resolve_path_in_type_ns_fully(
|
||||
db.upcast(),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
|
||||
hir_expand::mod_path::PathKind::Abs,
|
||||
[name![core], name![fmt], name![Debug]],
|
||||
)),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(path![core::fmt::Debug]),
|
||||
) else {
|
||||
not_supported!("core::fmt::Debug not found");
|
||||
};
|
||||
let Some(debug_fmt_fn) = db.trait_data(debug_trait).method_by_name(&name![fmt]) else {
|
||||
let Some(debug_fmt_fn) =
|
||||
db.trait_data(debug_trait).method_by_name(&Name::new_symbol_root(sym::fmt.clone()))
|
||||
else {
|
||||
not_supported!("core::fmt::Debug::fmt not found");
|
||||
};
|
||||
// a1 = &[""]
|
||||
|
@ -2829,10 +2831,7 @@ pub fn render_const_using_debug_impl(
|
|||
evaluator.write_memory(a3.offset(5 * evaluator.ptr_size()), &[1])?;
|
||||
let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully(
|
||||
db.upcast(),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(ModPath::from_segments(
|
||||
hir_expand::mod_path::PathKind::Abs,
|
||||
[name![std], name![fmt], name![format]],
|
||||
)),
|
||||
&hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]),
|
||||
) else {
|
||||
not_supported!("std::fmt::format not found");
|
||||
};
|
||||
|
|
|
@ -8,12 +8,14 @@ use hir_def::{
|
|||
builtin_type::{BuiltinInt, BuiltinUint},
|
||||
resolver::HasResolver,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
|
||||
use crate::{
|
||||
error_lifetime,
|
||||
mir::eval::{
|
||||
name, pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule,
|
||||
HirDisplay, Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned,
|
||||
pad16, Address, AdtId, Arc, BuiltinType, Evaluator, FunctionId, HasModule, HirDisplay,
|
||||
Interned, InternedClosure, Interner, Interval, IntervalAndTy, IntervalOrOwned,
|
||||
ItemContainerId, LangItem, Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability,
|
||||
Result, Substitution, Ty, TyBuilder, TyExt,
|
||||
},
|
||||
|
@ -64,7 +66,7 @@ impl Evaluator<'_> {
|
|||
};
|
||||
if is_intrinsic {
|
||||
self.exec_intrinsic(
|
||||
function_data.name.as_text().unwrap_or_default().as_str(),
|
||||
function_data.name.as_str(),
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
|
@ -86,7 +88,7 @@ impl Evaluator<'_> {
|
|||
};
|
||||
if is_platform_intrinsic {
|
||||
self.exec_platform_intrinsic(
|
||||
function_data.name.as_text().unwrap_or_default().as_str(),
|
||||
function_data.name.as_str(),
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
|
@ -104,7 +106,7 @@ impl Evaluator<'_> {
|
|||
};
|
||||
if is_extern_c {
|
||||
self.exec_extern_c(
|
||||
function_data.name.as_text().unwrap_or_default().as_str(),
|
||||
function_data.name.as_str(),
|
||||
args,
|
||||
generic_args,
|
||||
destination,
|
||||
|
@ -117,7 +119,7 @@ impl Evaluator<'_> {
|
|||
.attrs
|
||||
.iter()
|
||||
.filter_map(|it| it.path().as_ident())
|
||||
.filter_map(|it| it.as_str())
|
||||
.map(|it| it.as_str())
|
||||
.find(|it| {
|
||||
[
|
||||
"rustc_allocator",
|
||||
|
@ -317,7 +319,7 @@ impl Evaluator<'_> {
|
|||
return Some(LangItem::BeginPanic);
|
||||
}
|
||||
|
||||
let candidate = attrs.by_key("lang").string_value().and_then(LangItem::from_str)?;
|
||||
let candidate = attrs.lang_item()?;
|
||||
// We want to execute these functions with special logic
|
||||
// `PanicFmt` is not detected here as it's redirected later.
|
||||
if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
|
||||
|
@ -1274,10 +1276,11 @@ impl Evaluator<'_> {
|
|||
args.push(IntervalAndTy::new(addr, field, self, locals)?);
|
||||
}
|
||||
if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) {
|
||||
if let Some(def) = target
|
||||
.as_trait()
|
||||
.and_then(|it| self.db.trait_data(it).method_by_name(&name![call_once]))
|
||||
{
|
||||
if let Some(def) = target.as_trait().and_then(|it| {
|
||||
self.db
|
||||
.trait_data(it)
|
||||
.method_by_name(&Name::new_symbol_root(sym::call_once.clone()))
|
||||
}) {
|
||||
self.exec_fn_trait(
|
||||
def,
|
||||
&args,
|
||||
|
|
|
@ -1113,9 +1113,9 @@ impl<'ctx> MirLowerCtx<'ctx> {
|
|||
.iter()
|
||||
.map(|it| {
|
||||
let o = match it.1.name.as_str() {
|
||||
Some("start") => lp.take(),
|
||||
Some("end") => rp.take(),
|
||||
Some("exhausted") => {
|
||||
"start" => lp.take(),
|
||||
"end" => rp.take(),
|
||||
"exhausted" => {
|
||||
Some(Operand::from_bytes(Box::new([0]), TyBuilder::bool()))
|
||||
}
|
||||
_ => None,
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::mir::MutBorrowKind;
|
|||
|
||||
use super::*;
|
||||
use hir_def::FunctionId;
|
||||
use hir_expand::name;
|
||||
use intern::sym;
|
||||
|
||||
macro_rules! not_supported {
|
||||
($it: expr) => {
|
||||
|
@ -189,10 +189,10 @@ impl MirLowerCtx<'_> {
|
|||
if let Some(deref_trait) =
|
||||
self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
|
||||
{
|
||||
if let Some(deref_fn) = self
|
||||
.db
|
||||
.trait_data(deref_trait)
|
||||
.method_by_name(&name![deref_mut])
|
||||
if let Some(deref_fn) =
|
||||
self.db.trait_data(deref_trait).method_by_name(
|
||||
&Name::new_symbol_root(sym::deref_mut.clone()),
|
||||
)
|
||||
{
|
||||
break 'b deref_fn == f;
|
||||
}
|
||||
|
@ -324,12 +324,17 @@ impl MirLowerCtx<'_> {
|
|||
mutability: bool,
|
||||
) -> Result<Option<(Place, BasicBlockId)>> {
|
||||
let (chalk_mut, trait_lang_item, trait_method_name, borrow_kind) = if !mutability {
|
||||
(Mutability::Not, LangItem::Deref, name![deref], BorrowKind::Shared)
|
||||
(
|
||||
Mutability::Not,
|
||||
LangItem::Deref,
|
||||
Name::new_symbol_root(sym::deref.clone()),
|
||||
BorrowKind::Shared,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Mutability::Mut,
|
||||
LangItem::DerefMut,
|
||||
name![deref_mut],
|
||||
Name::new_symbol_root(sym::deref_mut.clone()),
|
||||
BorrowKind::Mut { kind: MutBorrowKind::Default },
|
||||
)
|
||||
};
|
||||
|
|
|
@ -12,7 +12,8 @@ use hir_def::{
|
|||
lang_item::{LangItem, LangItemTarget},
|
||||
BlockId, TraitId,
|
||||
};
|
||||
use hir_expand::name::{name, Name};
|
||||
use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
use stdx::panic_context;
|
||||
use triomphe::Arc;
|
||||
|
||||
|
@ -256,9 +257,9 @@ impl FnTrait {
|
|||
|
||||
pub fn method_name(self) -> Name {
|
||||
match self {
|
||||
FnTrait::FnOnce => name!(call_once),
|
||||
FnTrait::FnMut => name!(call_mut),
|
||||
FnTrait::Fn => name!(call),
|
||||
FnTrait::FnOnce => Name::new_symbol_root(sym::call_once.clone()),
|
||||
FnTrait::FnMut => Name::new_symbol_root(sym::call_mut.clone()),
|
||||
FnTrait::Fn => Name::new_symbol_root(sym::call.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use hir_def::{
|
|||
};
|
||||
use hir_expand::{mod_path::PathKind, name::Name};
|
||||
use hir_ty::{db::HirDatabase, method_resolution};
|
||||
use span::SyntaxContextId;
|
||||
|
||||
use crate::{
|
||||
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl,
|
||||
|
@ -328,7 +329,7 @@ fn doc_modpath_from_str(link: &str) -> Option<ModPath> {
|
|||
let parts = first_segment.into_iter().chain(parts).map(|segment| match segment.parse() {
|
||||
Ok(idx) => Name::new_tuple_field(idx),
|
||||
Err(_) => {
|
||||
Name::new_text_dont_use(segment.split_once('<').map_or(segment, |it| it.0).into())
|
||||
Name::new(segment.split_once('<').map_or(segment, |it| it.0), SyntaxContextId::ROOT)
|
||||
}
|
||||
});
|
||||
Some(ModPath::from_segments(kind, parts))
|
||||
|
|
|
@ -58,7 +58,7 @@ use hir_def::{
|
|||
TypeOrConstParamId, TypeParamId, UnionId,
|
||||
};
|
||||
use hir_expand::{
|
||||
attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
|
||||
attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
|
||||
};
|
||||
use hir_ty::{
|
||||
all_super_traits, autoderef, check_orphan_rules,
|
||||
|
@ -131,7 +131,7 @@ pub use {
|
|||
change::ChangeWithProcMacros,
|
||||
hygiene::{marks_rev, SyntaxContextExt},
|
||||
inert_attr_macro::AttributeTemplate,
|
||||
name::{known, Name},
|
||||
name::Name,
|
||||
proc_macro::ProcMacros,
|
||||
tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId,
|
||||
MacroFileIdExt,
|
||||
|
@ -145,6 +145,7 @@ pub use {
|
|||
},
|
||||
// FIXME: Properly encapsulate mir
|
||||
hir_ty::{mir, Interner as ChalkTyInterner},
|
||||
intern::{sym, Symbol},
|
||||
};
|
||||
|
||||
// These are negative re-exports: pub using these names is forbidden, they
|
||||
|
@ -1826,7 +1827,7 @@ impl DefWithBody {
|
|||
continue;
|
||||
}
|
||||
let mut need_mut = &mol[local];
|
||||
if body[binding_id].name.as_str() == Some("self")
|
||||
if body[binding_id].name == sym::self_.clone()
|
||||
&& need_mut == &mir::MutabilityReason::Unused
|
||||
{
|
||||
need_mut = &mir::MutabilityReason::Not;
|
||||
|
@ -1836,7 +1837,7 @@ impl DefWithBody {
|
|||
|
||||
match (need_mut, is_mut) {
|
||||
(mir::MutabilityReason::Unused, _) => {
|
||||
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
|
||||
let should_ignore = body[binding_id].name.as_str().starts_with('_');
|
||||
if !should_ignore {
|
||||
acc.push(UnusedVariable { local }.into())
|
||||
}
|
||||
|
@ -1866,7 +1867,7 @@ impl DefWithBody {
|
|||
}
|
||||
(mir::MutabilityReason::Not, true) => {
|
||||
if !infer.mutated_bindings_in_closure.contains(&binding_id) {
|
||||
let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
|
||||
let should_ignore = body[binding_id].name.as_str().starts_with('_');
|
||||
if !should_ignore {
|
||||
acc.push(UnusedMut { local }.into())
|
||||
}
|
||||
|
@ -2588,7 +2589,7 @@ pub struct StaticLifetime;
|
|||
|
||||
impl StaticLifetime {
|
||||
pub fn name(self) -> Name {
|
||||
known::STATIC_LIFETIME
|
||||
Name::new_symbol_root(sym::tick_static.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3248,7 +3249,7 @@ impl Local {
|
|||
}
|
||||
|
||||
pub fn is_self(self, db: &dyn HirDatabase) -> bool {
|
||||
self.name(db) == name![self]
|
||||
self.name(db) == sym::self_.clone()
|
||||
}
|
||||
|
||||
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
|
||||
|
|
|
@ -25,11 +25,8 @@ use hir_def::{
|
|||
};
|
||||
use hir_expand::{
|
||||
mod_path::path,
|
||||
name::{AsName, Name},
|
||||
HirFileId, InFile, InMacroFile, MacroFileId, MacroFileIdExt,
|
||||
{
|
||||
name,
|
||||
name::{AsName, Name},
|
||||
},
|
||||
};
|
||||
use hir_ty::{
|
||||
diagnostics::{
|
||||
|
@ -40,6 +37,7 @@ use hir_ty::{
|
|||
method_resolution, Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind,
|
||||
TyLoweringContext,
|
||||
};
|
||||
use intern::sym;
|
||||
use itertools::Itertools;
|
||||
use smallvec::SmallVec;
|
||||
use syntax::{
|
||||
|
@ -368,7 +366,7 @@ impl SourceAnalyzer {
|
|||
let items = into_future_trait.items(db);
|
||||
let into_future_type = items.into_iter().find_map(|item| match item {
|
||||
AssocItem::TypeAlias(alias)
|
||||
if alias.name(db) == hir_expand::name![IntoFuture] =>
|
||||
if alias.name(db) == Name::new_symbol_root(sym::IntoFuture.clone()) =>
|
||||
{
|
||||
Some(alias)
|
||||
}
|
||||
|
@ -397,15 +395,21 @@ impl SourceAnalyzer {
|
|||
// This can be either `Deref::deref` or `DerefMut::deref_mut`.
|
||||
// Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,
|
||||
// use that result to find out which one it is.
|
||||
let (deref_trait, deref) =
|
||||
self.lang_trait_fn(db, LangItem::Deref, &name![deref])?;
|
||||
let (deref_trait, deref) = self.lang_trait_fn(
|
||||
db,
|
||||
LangItem::Deref,
|
||||
&Name::new_symbol_root(sym::deref.clone()),
|
||||
)?;
|
||||
self.infer
|
||||
.as_ref()
|
||||
.and_then(|infer| {
|
||||
let expr = self.expr_id(db, &prefix_expr.clone().into())?;
|
||||
let (func, _) = infer.method_resolution(expr)?;
|
||||
let (deref_mut_trait, deref_mut) =
|
||||
self.lang_trait_fn(db, LangItem::DerefMut, &name![deref_mut])?;
|
||||
let (deref_mut_trait, deref_mut) = self.lang_trait_fn(
|
||||
db,
|
||||
LangItem::DerefMut,
|
||||
&Name::new_symbol_root(sym::deref_mut.clone()),
|
||||
)?;
|
||||
if func == deref_mut {
|
||||
Some((deref_mut_trait, deref_mut))
|
||||
} else {
|
||||
|
@ -414,8 +418,12 @@ impl SourceAnalyzer {
|
|||
})
|
||||
.unwrap_or((deref_trait, deref))
|
||||
}
|
||||
ast::UnaryOp::Not => self.lang_trait_fn(db, LangItem::Not, &name![not])?,
|
||||
ast::UnaryOp::Neg => self.lang_trait_fn(db, LangItem::Neg, &name![neg])?,
|
||||
ast::UnaryOp::Not => {
|
||||
self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not.clone()))?
|
||||
}
|
||||
ast::UnaryOp::Neg => {
|
||||
self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg.clone()))?
|
||||
}
|
||||
};
|
||||
|
||||
let ty = self.ty_of_expr(db, &prefix_expr.expr()?)?;
|
||||
|
@ -435,15 +443,19 @@ impl SourceAnalyzer {
|
|||
let base_ty = self.ty_of_expr(db, &index_expr.base()?)?;
|
||||
let index_ty = self.ty_of_expr(db, &index_expr.index()?)?;
|
||||
|
||||
let (index_trait, index_fn) = self.lang_trait_fn(db, LangItem::Index, &name![index])?;
|
||||
let (index_trait, index_fn) =
|
||||
self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index.clone()))?;
|
||||
let (op_trait, op_fn) = self
|
||||
.infer
|
||||
.as_ref()
|
||||
.and_then(|infer| {
|
||||
let expr = self.expr_id(db, &index_expr.clone().into())?;
|
||||
let (func, _) = infer.method_resolution(expr)?;
|
||||
let (index_mut_trait, index_mut_fn) =
|
||||
self.lang_trait_fn(db, LangItem::IndexMut, &name![index_mut])?;
|
||||
let (index_mut_trait, index_mut_fn) = self.lang_trait_fn(
|
||||
db,
|
||||
LangItem::IndexMut,
|
||||
&Name::new_symbol_root(sym::index_mut.clone()),
|
||||
)?;
|
||||
if func == index_mut_fn {
|
||||
Some((index_mut_trait, index_mut_fn))
|
||||
} else {
|
||||
|
|
|
@ -239,7 +239,7 @@ impl<'a> SymbolCollector<'a> {
|
|||
|
||||
fn collect_from_trait(&mut self, trait_id: TraitId) {
|
||||
let trait_data = self.db.trait_data(trait_id);
|
||||
self.with_container_name(trait_data.name.as_text(), |s| {
|
||||
self.with_container_name(Some(trait_data.name.as_str().into()), |s| {
|
||||
for &(_, assoc_item_id) in &trait_data.items {
|
||||
s.push_assoc_item(assoc_item_id);
|
||||
}
|
||||
|
|
|
@ -1637,8 +1637,8 @@ mod bar {
|
|||
|
||||
#[test]
|
||||
fn local_inline_import_has_alias() {
|
||||
// FIXME
|
||||
check_assist_not_applicable(
|
||||
// FIXME wrong import
|
||||
check_assist(
|
||||
auto_import,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
|
@ -1647,14 +1647,24 @@ use S as IoResult;
|
|||
mod foo {
|
||||
pub fn bar() -> S$0<()> {}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
use S as IoResult;
|
||||
|
||||
mod foo {
|
||||
use crate::S;
|
||||
|
||||
pub fn bar() -> S<()> {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alias_local() {
|
||||
// FIXME
|
||||
check_assist_not_applicable(
|
||||
// FIXME wrong import
|
||||
check_assist(
|
||||
auto_import,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
|
@ -1663,6 +1673,16 @@ use S as IoResult;
|
|||
mod foo {
|
||||
pub fn bar() -> IoResult$0<()> {}
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
struct S<T>(T);
|
||||
use S as IoResult;
|
||||
|
||||
mod foo {
|
||||
use crate::S;
|
||||
|
||||
pub fn bar() -> IoResult<()> {}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -470,7 +470,7 @@ fn add_enum_def(
|
|||
.module()
|
||||
.scope(ctx.db(), Some(*target_module))
|
||||
.iter()
|
||||
.any(|(name, _)| name.as_str() == Some("Bool"))
|
||||
.any(|(name, _)| name.as_str() == "Bool")
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{known, AsAssocItem, Semantics};
|
||||
use hir::{sym, AsAssocItem, Semantics};
|
||||
use ide_db::{
|
||||
famous_defs::FamousDefs,
|
||||
syntax_helpers::node_ext::{
|
||||
|
@ -223,7 +223,7 @@ fn option_variants(
|
|||
let fam = FamousDefs(sema, sema.scope(expr)?.krate());
|
||||
let option_variants = fam.core_option_Option()?.variants(sema.db);
|
||||
match &*option_variants {
|
||||
&[variant0, variant1] => Some(if variant0.name(sema.db) == known::None {
|
||||
&[variant0, variant1] => Some(if variant0.name(sema.db) == sym::None.clone() {
|
||||
(variant0, variant1)
|
||||
} else {
|
||||
(variant1, variant0)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::known;
|
||||
use hir::{sym, Name};
|
||||
use ide_db::famous_defs::FamousDefs;
|
||||
use stdx::format_to;
|
||||
use syntax::{
|
||||
|
@ -149,7 +149,11 @@ fn is_ref_and_impls_iter_method(
|
|||
ast::Expr::RefExpr(r) => r,
|
||||
_ => return None,
|
||||
};
|
||||
let wanted_method = if ref_expr.mut_token().is_some() { known::iter_mut } else { known::iter };
|
||||
let wanted_method = Name::new_symbol_root(if ref_expr.mut_token().is_some() {
|
||||
sym::iter_mut.clone()
|
||||
} else {
|
||||
sym::iter.clone()
|
||||
});
|
||||
let expr_behind_ref = ref_expr.expr()?;
|
||||
let ty = sema.type_of_expr(&expr_behind_ref)?.adjusted();
|
||||
let scope = sema.scope(iterable.syntax())?;
|
||||
|
|
|
@ -169,8 +169,8 @@ fn get_names_in_scope(
|
|||
|
||||
let mut names = FxHashSet::default();
|
||||
scope.process_all_names(&mut |name, scope| {
|
||||
if let (Some(name), hir::ScopeDef::Local(_)) = (name.as_text(), scope) {
|
||||
names.insert(name);
|
||||
if let hir::ScopeDef::Local(_) = scope {
|
||||
names.insert(name.as_str().into());
|
||||
}
|
||||
});
|
||||
Some(names)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use hir::{known, HasSource, Name};
|
||||
use hir::{sym, HasSource, Name};
|
||||
use syntax::{
|
||||
ast::{self, HasName},
|
||||
AstNode,
|
||||
|
@ -54,13 +54,13 @@ pub(crate) fn generate_is_empty_from_len(acc: &mut Assists, ctx: &AssistContext<
|
|||
}
|
||||
|
||||
let impl_ = fn_node.syntax().ancestors().find_map(ast::Impl::cast)?;
|
||||
let len_fn = get_impl_method(ctx, &impl_, &known::len)?;
|
||||
let len_fn = get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::len.clone()))?;
|
||||
if !len_fn.ret_type(ctx.sema.db).is_usize() {
|
||||
cov_mark::hit!(len_fn_different_return_type);
|
||||
return None;
|
||||
}
|
||||
|
||||
if get_impl_method(ctx, &impl_, &known::is_empty).is_some() {
|
||||
if get_impl_method(ctx, &impl_, &Name::new_symbol_root(sym::is_empty.clone())).is_some() {
|
||||
cov_mark::hit!(is_empty_already_implemented);
|
||||
return None;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::BTreeSet;
|
|||
|
||||
use ast::make;
|
||||
use either::Either;
|
||||
use hir::{db::HirDatabase, PathResolution, Semantics, TypeInfo};
|
||||
use hir::{db::HirDatabase, sym, PathResolution, Semantics, TypeInfo};
|
||||
use ide_db::{
|
||||
base_db::{FileId, FileRange},
|
||||
defs::Definition,
|
||||
|
@ -430,10 +430,7 @@ fn inline(
|
|||
|
||||
let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
|
||||
|
||||
let is_self = param
|
||||
.name(sema.db)
|
||||
.and_then(|name| name.as_text())
|
||||
.is_some_and(|name| name == "self");
|
||||
let is_self = param.name(sema.db).is_some_and(|name| name == sym::self_.clone());
|
||||
|
||||
if is_self {
|
||||
let mut this_pat = make::ident_pat(false, false, make::name("this"));
|
||||
|
|
|
@ -47,7 +47,7 @@ pub(crate) fn replace_with_lazy_method(acc: &mut Assists, ctx: &AssistContext<'_
|
|||
None,
|
||||
None,
|
||||
|func| {
|
||||
let valid = func.name(ctx.sema.db).as_str() == Some(&*method_name_lazy)
|
||||
let valid = func.name(ctx.sema.db).as_str() == &*method_name_lazy
|
||||
&& func.num_params(ctx.sema.db) == n_params
|
||||
&& {
|
||||
let params = func.params_without_self(ctx.sema.db);
|
||||
|
@ -133,7 +133,7 @@ pub(crate) fn replace_with_eager_method(acc: &mut Assists, ctx: &AssistContext<'
|
|||
None,
|
||||
None,
|
||||
|func| {
|
||||
let valid = func.name(ctx.sema.db).as_str() == Some(method_name_eager)
|
||||
let valid = func.name(ctx.sema.db).as_str() == method_name_eager
|
||||
&& func.num_params(ctx.sema.db) == n_params;
|
||||
valid.then_some(func)
|
||||
},
|
||||
|
|
|
@ -88,8 +88,8 @@ pub fn has_test_related_attribute(attrs: &hir::AttrsWithOwner) -> bool {
|
|||
let path = attr.path();
|
||||
(|| {
|
||||
Some(
|
||||
path.segments().first()?.as_text()?.starts_with("test")
|
||||
|| path.segments().last()?.as_text()?.ends_with("test"),
|
||||
path.segments().first()?.as_str().starts_with("test")
|
||||
|| path.segments().last()?.as_str().ends_with("test"),
|
||||
)
|
||||
})()
|
||||
.unwrap_or_default()
|
||||
|
|
|
@ -24,7 +24,7 @@ pub(crate) mod vis;
|
|||
|
||||
use std::iter;
|
||||
|
||||
use hir::{known, HasAttrs, ImportPathConfig, ScopeDef, Variant};
|
||||
use hir::{sym, HasAttrs, ImportPathConfig, Name, ScopeDef, Variant};
|
||||
use ide_db::{imports::import_assets::LocatedImport, RootDatabase, SymbolKind};
|
||||
use syntax::{ast, SmolStr};
|
||||
|
||||
|
@ -618,7 +618,8 @@ fn enum_variants_with_paths(
|
|||
let mut process_variant = |variant: Variant| {
|
||||
let self_path = hir::ModPath::from_segments(
|
||||
hir::PathKind::Plain,
|
||||
iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
|
||||
iter::once(Name::new_symbol_root(sym::Self_.clone()))
|
||||
.chain(iter::once(variant.name(ctx.db))),
|
||||
);
|
||||
|
||||
cb(acc, ctx, variant, self_path);
|
||||
|
|
|
@ -18,7 +18,7 @@ pub(super) fn complete_macro_use(
|
|||
for mod_def in krate.root_module().declarations(ctx.db) {
|
||||
if let ModuleDef::Macro(mac) = mod_def {
|
||||
let mac_name = mac.name(ctx.db);
|
||||
let Some(mac_name) = mac_name.as_str() else { continue };
|
||||
let mac_name = mac_name.as_str();
|
||||
|
||||
let existing_import = existing_imports
|
||||
.iter()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//! Completes references after dot (fields and method calls).
|
||||
|
||||
use hir::{sym, Name};
|
||||
use ide_db::FxHashSet;
|
||||
use syntax::SmolStr;
|
||||
|
||||
|
@ -90,12 +91,14 @@ pub(crate) fn complete_undotted_self(
|
|||
in_breakable: expr_ctx.in_breakable,
|
||||
},
|
||||
},
|
||||
Some(hir::known::SELF_PARAM),
|
||||
Some(Name::new_symbol_root(sym::self_.clone())),
|
||||
field,
|
||||
&ty,
|
||||
)
|
||||
},
|
||||
|acc, field, ty| acc.add_tuple_field(ctx, Some(hir::known::SELF_PARAM), field, &ty),
|
||||
|acc, field, ty| {
|
||||
acc.add_tuple_field(ctx, Some(Name::new_symbol_root(sym::self_.clone())), field, &ty)
|
||||
},
|
||||
true,
|
||||
false,
|
||||
);
|
||||
|
@ -112,7 +115,7 @@ pub(crate) fn complete_undotted_self(
|
|||
},
|
||||
},
|
||||
func,
|
||||
Some(hir::known::SELF_PARAM),
|
||||
Some(Name::new_symbol_root(sym::self_.clone())),
|
||||
None,
|
||||
)
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Completion of names from the current scope in expression position.
|
||||
|
||||
use hir::{ImportPathConfig, ScopeDef};
|
||||
use hir::{sym, ImportPathConfig, Name, ScopeDef};
|
||||
use syntax::ast;
|
||||
|
||||
use crate::{
|
||||
|
@ -190,7 +190,7 @@ pub(crate) fn complete_expr_path(
|
|||
path_ctx,
|
||||
strukt,
|
||||
None,
|
||||
Some(hir::known::SELF_TYPE),
|
||||
Some(Name::new_symbol_root(sym::Self_.clone())),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +210,12 @@ pub(crate) fn complete_expr_path(
|
|||
|
||||
acc.add_union_literal(ctx, un, path, None);
|
||||
if complete_self {
|
||||
acc.add_union_literal(ctx, un, None, Some(hir::known::SELF_TYPE));
|
||||
acc.add_union_literal(
|
||||
ctx,
|
||||
un,
|
||||
None,
|
||||
Some(Name::new_symbol_root(sym::Self_.clone())),
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::Adt::Enum(e) => {
|
||||
|
|
|
@ -31,7 +31,7 @@ pub(crate) fn format_string(
|
|||
};
|
||||
|
||||
let source_range = TextRange::new(brace_offset, cursor);
|
||||
ctx.locals.iter().for_each(|(name, _)| {
|
||||
ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()).for_each(|(name, _)| {
|
||||
CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
|
||||
.add_to(acc, ctx.db);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//! there is no value in lifting these out into the outline module test since they will either not
|
||||
//! show up for normal completions, or they won't show completions other than lifetimes depending
|
||||
//! on the fixture input.
|
||||
use hir::{known, ScopeDef};
|
||||
use hir::{sym, Name, ScopeDef};
|
||||
use syntax::{ast, TokenText};
|
||||
|
||||
use crate::{
|
||||
|
@ -47,7 +47,7 @@ pub(crate) fn complete_lifetime(
|
|||
}
|
||||
});
|
||||
if param_lifetime.is_none() {
|
||||
acc.add_lifetime(ctx, known::STATIC_LIFETIME);
|
||||
acc.add_lifetime(ctx, Name::new_symbol_root(sym::tick_static.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,9 +55,8 @@ pub(crate) fn complete_use_path(
|
|||
if !ctx.check_stability(def.attrs(ctx.db).as_deref()) {
|
||||
continue;
|
||||
}
|
||||
let is_name_already_imported = name
|
||||
.as_text()
|
||||
.map_or(false, |text| already_imported_names.contains(text.as_str()));
|
||||
let is_name_already_imported =
|
||||
already_imported_names.contains(name.as_str());
|
||||
|
||||
let add_resolution = match def {
|
||||
ScopeDef::Unknown if unknown_is_current(&name) => {
|
||||
|
|
|
@ -823,13 +823,13 @@ fn classify_name_ref(
|
|||
for item in trait_.items_with_supertraits(sema.db) {
|
||||
match item {
|
||||
hir::AssocItem::TypeAlias(assoc_ty) => {
|
||||
if assoc_ty.name(sema.db).as_str()? == arg_name {
|
||||
if assoc_ty.name(sema.db).as_str() == arg_name {
|
||||
override_location = Some(TypeLocation::AssocTypeEq);
|
||||
return None;
|
||||
}
|
||||
},
|
||||
hir::AssocItem::Const(const_) => {
|
||||
if const_.name(sema.db)?.as_str()? == arg_name {
|
||||
if const_.name(sema.db)?.as_str() == arg_name {
|
||||
override_location = Some(TypeLocation::AssocConstEq);
|
||||
return None;
|
||||
}
|
||||
|
@ -867,7 +867,7 @@ fn classify_name_ref(
|
|||
let trait_items = trait_.items_with_supertraits(sema.db);
|
||||
let assoc_ty = trait_items.iter().find_map(|item| match item {
|
||||
hir::AssocItem::TypeAlias(assoc_ty) => {
|
||||
(assoc_ty.name(sema.db).as_str()? == arg_name)
|
||||
(assoc_ty.name(sema.db).as_str() == arg_name)
|
||||
.then_some(assoc_ty)
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
@ -280,8 +280,7 @@ pub(crate) fn render_expr(
|
|||
let mut snippet_formatter = |ty: &hir::Type| {
|
||||
let arg_name = ty
|
||||
.as_adt()
|
||||
.and_then(|adt| adt.name(ctx.db).as_text())
|
||||
.map(|s| stdx::to_lower_snake_case(s.as_str()))
|
||||
.map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
|
||||
.unwrap_or_else(|| String::from("_"));
|
||||
let res = format!("${{{i}:{arg_name}}}");
|
||||
i += 1;
|
||||
|
@ -290,8 +289,7 @@ pub(crate) fn render_expr(
|
|||
|
||||
let mut label_formatter = |ty: &hir::Type| {
|
||||
ty.as_adt()
|
||||
.and_then(|adt| adt.name(ctx.db).as_text())
|
||||
.map(|s| stdx::to_lower_snake_case(s.as_str()))
|
||||
.map(|adt| stdx::to_lower_snake_case(adt.name(ctx.db).as_str()))
|
||||
.unwrap_or_else(|| String::from("..."))
|
||||
};
|
||||
|
||||
|
|
|
@ -188,7 +188,7 @@ fn compute_return_type_match(
|
|||
CompletionRelevanceReturnType::Constructor
|
||||
} else if ret_type
|
||||
.as_adt()
|
||||
.and_then(|adt| adt.name(db).as_str().map(|name| name.ends_with("Builder")))
|
||||
.map(|adt| adt.name(db).as_str().ends_with("Builder"))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
// fn([..]) -> [..]Builder
|
||||
|
@ -227,11 +227,7 @@ pub(super) fn add_call_parens<'b>(
|
|||
None => {
|
||||
let name = match param.ty().as_adt() {
|
||||
None => "_".to_owned(),
|
||||
Some(adt) => adt
|
||||
.name(ctx.db)
|
||||
.as_text()
|
||||
.map(|s| to_lower_snake_case(s.as_str()))
|
||||
.unwrap_or_else(|| "_".to_owned()),
|
||||
Some(adt) => to_lower_snake_case(adt.name(ctx.db).as_str()),
|
||||
};
|
||||
f(&format_args!("${{{}:{name}}}", index + offset))
|
||||
}
|
||||
|
@ -263,8 +259,8 @@ pub(super) fn add_call_parens<'b>(
|
|||
|
||||
fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str {
|
||||
if let Some(derefed_ty) = ty.remove_ref() {
|
||||
for (name, local) in ctx.locals.iter() {
|
||||
if name.as_text().as_deref() == Some(arg) {
|
||||
for (name, local) in ctx.locals.iter().sorted_by_key(|&(k, _)| k.clone()) {
|
||||
if name.as_str() == arg {
|
||||
return if local.ty(ctx.db) == derefed_ty {
|
||||
if ty.is_mutable_reference() {
|
||||
"&mut "
|
||||
|
|
|
@ -767,8 +767,8 @@ fn main() {
|
|||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
|
||||
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
|
||||
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
|
||||
me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
|
||||
"#]],
|
||||
);
|
||||
|
|
|
@ -144,7 +144,7 @@ impl Definition {
|
|||
Definition::Local(it) => it.name(db),
|
||||
Definition::GenericParam(it) => it.name(db),
|
||||
Definition::Label(it) => it.name(db),
|
||||
Definition::BuiltinLifetime(StaticLifetime) => hir::known::STATIC_LIFETIME,
|
||||
Definition::BuiltinLifetime(it) => it.name(),
|
||||
Definition::BuiltinAttr(_) => return None, // FIXME
|
||||
Definition::ToolModule(_) => return None, // FIXME
|
||||
Definition::DeriveHelper(it) => it.name(db),
|
||||
|
|
|
@ -15,7 +15,7 @@ use syntax::{
|
|||
use crate::{
|
||||
helpers::item_name,
|
||||
items_locator::{self, AssocSearchMode, DEFAULT_QUERY_SEARCH_LIMIT},
|
||||
RootDatabase,
|
||||
FxIndexSet, RootDatabase,
|
||||
};
|
||||
|
||||
/// A candidate for import, derived during various IDE activities:
|
||||
|
@ -262,7 +262,7 @@ impl ImportAssets {
|
|||
|
||||
let scope = match sema.scope(&self.candidate_node) {
|
||||
Some(it) => it,
|
||||
None => return <FxHashSet<_>>::default().into_iter(),
|
||||
None => return <FxIndexSet<_>>::default().into_iter(),
|
||||
};
|
||||
|
||||
let krate = self.module_with_candidate.krate();
|
||||
|
@ -319,7 +319,7 @@ fn path_applicable_imports(
|
|||
path_candidate: &PathImportCandidate,
|
||||
mod_path: impl Fn(ItemInNs) -> Option<ModPath> + Copy,
|
||||
scope_filter: impl Fn(ItemInNs) -> bool + Copy,
|
||||
) -> FxHashSet<LocatedImport> {
|
||||
) -> FxIndexSet<LocatedImport> {
|
||||
let _p = tracing::info_span!("ImportAssets::path_applicable_imports").entered();
|
||||
|
||||
match &path_candidate.qualifier {
|
||||
|
@ -389,16 +389,16 @@ fn import_for_item(
|
|||
let mut import_path_candidate_segments = import_path_candidate.segments().iter().rev();
|
||||
let predicate = |it: EitherOrBoth<&SmolStr, &Name>| match it {
|
||||
// segments match, check next one
|
||||
EitherOrBoth::Both(a, b) if b.as_str() == Some(&**a) => None,
|
||||
EitherOrBoth::Both(a, b) if b.as_str() == &**a => None,
|
||||
// segments mismatch / qualifier is longer than the path, bail out
|
||||
EitherOrBoth::Both(..) | EitherOrBoth::Left(_) => Some(false),
|
||||
// all segments match and we have exhausted the qualifier, proceed
|
||||
EitherOrBoth::Right(_) => Some(true),
|
||||
};
|
||||
if item_as_assoc.is_none() {
|
||||
let item_name = item_name(db, original_item)?.as_text()?;
|
||||
let item_name = item_name(db, original_item)?;
|
||||
let last_segment = import_path_candidate_segments.next()?;
|
||||
if last_segment.as_str() != Some(&*item_name) {
|
||||
if *last_segment != item_name {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -500,7 +500,7 @@ fn trait_applicable_items(
|
|||
trait_assoc_item: bool,
|
||||
mod_path: impl Fn(ItemInNs) -> Option<ModPath>,
|
||||
scope_filter: impl Fn(hir::Trait) -> bool,
|
||||
) -> FxHashSet<LocatedImport> {
|
||||
) -> FxIndexSet<LocatedImport> {
|
||||
let _p = tracing::info_span!("ImportAssets::trait_applicable_items").entered();
|
||||
|
||||
let db = sema.db;
|
||||
|
@ -566,7 +566,7 @@ fn trait_applicable_items(
|
|||
definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate()
|
||||
});
|
||||
|
||||
let mut located_imports = FxHashSet::default();
|
||||
let mut located_imports = FxIndexSet::default();
|
||||
let mut trait_import_paths = FxHashMap::default();
|
||||
|
||||
if trait_assoc_item {
|
||||
|
|
|
@ -472,7 +472,7 @@ fn find_trait_for_assoc_item(
|
|||
});
|
||||
|
||||
for name in names {
|
||||
if assoc_item_name.as_str() == name.as_text()?.as_str() {
|
||||
if assoc_item_name.as_str() == name.as_str() {
|
||||
// It is fine to return the first match because in case of
|
||||
// multiple possibilities, the exact trait must be disambiguated
|
||||
// in the definition of trait being implemented, so this search
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use either::Either;
|
||||
use hir::{
|
||||
db::{ExpandDatabase, HirDatabase},
|
||||
known, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type,
|
||||
sym, AssocItem, HirDisplay, HirFileIdExt, ImportPathConfig, InFile, Type,
|
||||
};
|
||||
use ide_db::{
|
||||
assists::Assist, famous_defs::FamousDefs, imports::import_assets::item_for_path_search,
|
||||
|
@ -210,7 +210,7 @@ fn get_default_constructor(
|
|||
let has_new_func = ty
|
||||
.iterate_assoc_items(ctx.sema.db, krate, |assoc_item| {
|
||||
if let AssocItem::Function(func) = assoc_item {
|
||||
if func.name(ctx.sema.db) == known::new
|
||||
if func.name(ctx.sema.db) == sym::new.clone()
|
||||
&& func.assoc_fn_params(ctx.sema.db).is_empty()
|
||||
{
|
||||
return Some(());
|
||||
|
|
|
@ -76,7 +76,7 @@ fn field_fix(ctx: &DiagnosticsContext<'_>, d: &hir::UnresolvedField) -> Option<A
|
|||
let expr = d.expr.value.to_node(&root);
|
||||
|
||||
let error_range = ctx.sema.original_range_opt(expr.syntax())?;
|
||||
let field_name = d.name.as_str()?;
|
||||
let field_name = d.name.as_str();
|
||||
// Convert the receiver to an ADT
|
||||
let adt = d.receiver.strip_references().as_adt()?;
|
||||
let target_module = adt.module(ctx.sema.db);
|
||||
|
|
|
@ -150,7 +150,7 @@ fn try_lookup_macro_def_in_macro_use(
|
|||
|
||||
for mod_def in krate.root_module().declarations(sema.db) {
|
||||
if let ModuleDef::Macro(mac) = mod_def {
|
||||
if mac.name(sema.db).as_str() == Some(token.text()) {
|
||||
if mac.name(sema.db).as_str() == token.text() {
|
||||
if let Some(nav) = mac.try_to_nav(sema.db) {
|
||||
return Some(nav.call_site);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use either::Either;
|
||||
use hir::{
|
||||
known, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
|
||||
sym, ClosureStyle, HasVisibility, HirDisplay, HirDisplayError, HirWrite, ModuleDef,
|
||||
ModuleDefId, Semantics,
|
||||
};
|
||||
use ide_db::{base_db::FileRange, famous_defs::FamousDefs, RootDatabase};
|
||||
|
@ -633,7 +633,7 @@ fn hint_iterator(
|
|||
|
||||
if ty.impls_trait(db, iter_trait, &[]) {
|
||||
let assoc_type_item = iter_trait.items(db).into_iter().find_map(|item| match item {
|
||||
hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias),
|
||||
hir::AssocItem::TypeAlias(alias) if alias.name(db) == sym::Item.clone() => Some(alias),
|
||||
_ => None,
|
||||
})?;
|
||||
if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
|
||||
|
|
|
@ -46,7 +46,7 @@ pub(crate) fn hints(
|
|||
}
|
||||
|
||||
let name = param.name(sema.db);
|
||||
let param_name = name.as_str()?;
|
||||
let param_name = name.as_str();
|
||||
|
||||
let should_hide = {
|
||||
let argument = get_string_representation(&arg)?;
|
||||
|
|
|
@ -6,6 +6,7 @@ use ide_db::{
|
|||
defs::{Definition, IdentClass, NameClass, NameRefClass},
|
||||
FxHashMap, RootDatabase, SymbolKind,
|
||||
};
|
||||
use stdx::hash_once;
|
||||
use syntax::{
|
||||
ast, match_ast, AstNode, AstToken, NodeOrToken,
|
||||
SyntaxKind::{self, *},
|
||||
|
@ -358,17 +359,7 @@ fn highlight_name(
|
|||
}
|
||||
|
||||
fn calc_binding_hash(name: &hir::Name, shadow_count: u32) -> u64 {
|
||||
fn hash<T: std::hash::Hash + std::fmt::Debug>(x: T) -> u64 {
|
||||
use ide_db::FxHasher;
|
||||
|
||||
use std::hash::Hasher;
|
||||
|
||||
let mut hasher = FxHasher::default();
|
||||
x.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
}
|
||||
|
||||
hash((name, shadow_count))
|
||||
hash_once::<ide_db::FxHasher>((name.as_str(), shadow_count))
|
||||
}
|
||||
|
||||
pub(super) fn highlight_def(
|
||||
|
|
|
@ -66,8 +66,11 @@ fn discover_tests_in_module(
|
|||
|
||||
let mut r = vec![];
|
||||
for c in module.children(db) {
|
||||
let module_name =
|
||||
c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned();
|
||||
let module_name = c
|
||||
.name(db)
|
||||
.as_ref()
|
||||
.map(|n| n.as_str().to_owned())
|
||||
.unwrap_or_else(|| "[mod without name]".to_owned());
|
||||
let module_id = format!("{prefix_id}::{module_name}");
|
||||
let module_children = discover_tests_in_module(db, c, module_id.clone(), only_in_this_file);
|
||||
if !module_children.is_empty() {
|
||||
|
@ -94,7 +97,7 @@ fn discover_tests_in_module(
|
|||
continue;
|
||||
}
|
||||
let nav = f.try_to_nav(db).map(|r| r.call_site);
|
||||
let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned();
|
||||
let fn_name = f.name(db).as_str().to_owned();
|
||||
r.push(TestItem {
|
||||
id: format!("{prefix_id}::{fn_name}"),
|
||||
kind: TestItemKind::Function,
|
||||
|
@ -153,7 +156,7 @@ fn find_module_id_and_test_parents(
|
|||
let parent = Some(id.clone());
|
||||
id += "::";
|
||||
let module_name = &module.name(sema.db);
|
||||
let module_name = module_name.as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]");
|
||||
let module_name = module_name.as_ref().map(|n| n.as_str()).unwrap_or("[mod without name]");
|
||||
id += module_name;
|
||||
let nav = NavigationTarget::from_module_to_decl(sema.db, module).call_site;
|
||||
r.push(TestItem {
|
||||
|
|
|
@ -64,11 +64,7 @@ enum FieldOrTupleIdx {
|
|||
impl FieldOrTupleIdx {
|
||||
fn name(&self, db: &RootDatabase) -> String {
|
||||
match *self {
|
||||
FieldOrTupleIdx::Field(f) => f
|
||||
.name(db)
|
||||
.as_str()
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| format!(".{}", f.name(db).as_tuple_index().unwrap())),
|
||||
FieldOrTupleIdx::Field(f) => f.name(db).as_str().to_owned(),
|
||||
FieldOrTupleIdx::TupleIdx(i) => format!(".{i}"),
|
||||
}
|
||||
}
|
||||
|
@ -189,14 +185,7 @@ pub(crate) fn view_memory_layout(
|
|||
| Definition::SelfType(_) => "[ROOT]".to_owned(),
|
||||
|
||||
// def is an item
|
||||
def => def
|
||||
.name(db)
|
||||
.map(|n| {
|
||||
n.as_str()
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| format!(".{}", n.as_tuple_index().unwrap()))
|
||||
})
|
||||
.unwrap_or("[ROOT]".to_owned()),
|
||||
def => def.name(db).map(|n| n.as_str().to_owned()).unwrap_or("[ROOT]".to_owned()),
|
||||
};
|
||||
|
||||
let typename = ty.display(db).to_string();
|
||||
|
|
|
@ -18,6 +18,7 @@ dashmap.workspace = true
|
|||
hashbrown.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
triomphe.workspace = true
|
||||
sptr = "0.3.2"
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
workspace = true
|
||||
|
|
|
@ -20,6 +20,9 @@ type Guard<T> = dashmap::RwLockWriteGuard<
|
|||
HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>,
|
||||
>;
|
||||
|
||||
mod symbol;
|
||||
pub use self::symbol::{symbols as sym, Symbol};
|
||||
|
||||
pub struct Interned<T: Internable + ?Sized> {
|
||||
arc: Arc<T>,
|
||||
}
|
||||
|
|
328
crates/intern/src/symbol.rs
Normal file
328
crates/intern/src/symbol.rs
Normal file
|
@ -0,0 +1,328 @@
|
|||
//! Attempt at flexible symbol interning, allowing to intern and free strings at runtime while also
|
||||
//! supporting compile time declaration of symbols that will never be freed.
|
||||
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
fmt,
|
||||
hash::{BuildHasherDefault, Hash, Hasher},
|
||||
mem::{self, ManuallyDrop},
|
||||
ptr::NonNull,
|
||||
sync::OnceLock,
|
||||
};
|
||||
|
||||
use dashmap::{DashMap, SharedValue};
|
||||
use hashbrown::{hash_map::RawEntryMut, HashMap};
|
||||
use rustc_hash::FxHasher;
|
||||
use sptr::Strict;
|
||||
use triomphe::Arc;
|
||||
|
||||
pub mod symbols;
|
||||
|
||||
// some asserts for layout compatibility
|
||||
const _: () = assert!(std::mem::size_of::<Box<str>>() == std::mem::size_of::<&str>());
|
||||
const _: () = assert!(std::mem::align_of::<Box<str>>() == std::mem::align_of::<&str>());
|
||||
|
||||
const _: () = assert!(std::mem::size_of::<Arc<Box<str>>>() == std::mem::size_of::<&&str>());
|
||||
const _: () = assert!(std::mem::align_of::<Arc<Box<str>>>() == std::mem::align_of::<&&str>());
|
||||
|
||||
const _: () =
|
||||
assert!(std::mem::size_of::<*const *const str>() == std::mem::size_of::<TaggedArcPtr>());
|
||||
const _: () =
|
||||
assert!(std::mem::align_of::<*const *const str>() == std::mem::align_of::<TaggedArcPtr>());
|
||||
|
||||
const _: () = assert!(std::mem::size_of::<Arc<Box<str>>>() == std::mem::size_of::<TaggedArcPtr>());
|
||||
const _: () =
|
||||
assert!(std::mem::align_of::<Arc<Box<str>>>() == std::mem::align_of::<TaggedArcPtr>());
|
||||
|
||||
/// A pointer that points to a pointer to a `str`, it may be backed as a `&'static &'static str` or
|
||||
/// `Arc<Box<str>>` but its size is that of a thin pointer. The active variant is encoded as a tag
|
||||
/// in the LSB of the alignment niche.
|
||||
// Note, Ideally this would encode a `ThinArc<str>` and `ThinRef<str>`/`ThinConstPtr<str>` instead of the double indirection.
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||
struct TaggedArcPtr {
|
||||
packed: NonNull<*const str>,
|
||||
}
|
||||
|
||||
unsafe impl Send for TaggedArcPtr {}
|
||||
unsafe impl Sync for TaggedArcPtr {}
|
||||
|
||||
impl TaggedArcPtr {
|
||||
const BOOL_BITS: usize = true as usize;
|
||||
|
||||
const fn non_arc(r: &'static &'static str) -> Self {
|
||||
assert!(
|
||||
mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS
|
||||
);
|
||||
// SAFETY: The pointer is non-null as it is derived from a reference
|
||||
// Ideally we would call out to `pack_arc` but for a `false` tag, unfortunately the
|
||||
// packing stuff requires reading out the pointer to an integer which is not supported
|
||||
// in const contexts, so here we make use of the fact that for the non-arc version the
|
||||
// tag is false (0) and thus does not need touching the actual pointer value.ext)
|
||||
|
||||
let packed =
|
||||
unsafe { NonNull::new_unchecked((r as *const &str).cast::<*const str>().cast_mut()) };
|
||||
Self { packed }
|
||||
}
|
||||
|
||||
fn arc(arc: Arc<Box<str>>) -> Self {
|
||||
assert!(
|
||||
mem::align_of::<&'static &'static str>().trailing_zeros() as usize > Self::BOOL_BITS
|
||||
);
|
||||
Self {
|
||||
packed: Self::pack_arc(
|
||||
// Safety: `Arc::into_raw` always returns a non null pointer
|
||||
unsafe { NonNull::new_unchecked(Arc::into_raw(arc).cast_mut().cast()) },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the tag.
|
||||
#[inline]
|
||||
pub(crate) fn try_as_arc_owned(self) -> Option<ManuallyDrop<Arc<Box<str>>>> {
|
||||
// Unpack the tag from the alignment niche
|
||||
let tag = Strict::addr(self.packed.as_ptr()) & Self::BOOL_BITS;
|
||||
if tag != 0 {
|
||||
// Safety: We checked that the tag is non-zero -> true, so we are pointing to the data offset of an `Arc`
|
||||
Some(ManuallyDrop::new(unsafe {
|
||||
Arc::from_raw(self.pointer().as_ptr().cast::<Box<str>>())
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn pack_arc(ptr: NonNull<*const str>) -> NonNull<*const str> {
|
||||
let packed_tag = true as usize;
|
||||
|
||||
// can't use this strict provenance stuff here due to trait methods not being const
|
||||
// unsafe {
|
||||
// // Safety: The pointer is derived from a non-null
|
||||
// NonNull::new_unchecked(Strict::map_addr(ptr.as_ptr(), |addr| {
|
||||
// // Safety:
|
||||
// // - The pointer is `NonNull` => it's address is `NonZero<usize>`
|
||||
// // - `P::BITS` least significant bits are always zero (`Pointer` contract)
|
||||
// // - `T::BITS <= P::BITS` (from `Self::ASSERTION`)
|
||||
// //
|
||||
// // Thus `addr >> T::BITS` is guaranteed to be non-zero.
|
||||
// //
|
||||
// // `{non_zero} | packed_tag` can't make the value zero.
|
||||
|
||||
// (addr >> Self::BOOL_BITS) | packed_tag
|
||||
// }))
|
||||
// }
|
||||
// so what follows is roughly what the above looks like but inlined
|
||||
|
||||
let self_addr = ptr.as_ptr() as *const *const str as usize;
|
||||
let addr = self_addr | packed_tag;
|
||||
let dest_addr = addr as isize;
|
||||
let offset = dest_addr.wrapping_sub(self_addr as isize);
|
||||
|
||||
// SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes
|
||||
unsafe { NonNull::new_unchecked(ptr.as_ptr().cast::<u8>().wrapping_offset(offset).cast()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn pointer(self) -> NonNull<*const str> {
|
||||
// SAFETY: The resulting pointer is guaranteed to be NonNull as we only modify the niche bytes
|
||||
unsafe {
|
||||
NonNull::new_unchecked(Strict::map_addr(self.packed.as_ptr(), |addr| {
|
||||
addr & !Self::BOOL_BITS
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(crate) fn as_str(&self) -> &str {
|
||||
// SAFETY: We always point to a pointer to a str no matter what variant is active
|
||||
unsafe { *self.pointer().as_ptr().cast::<&str>() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Debug)]
|
||||
pub struct Symbol {
|
||||
repr: TaggedArcPtr,
|
||||
}
|
||||
|
||||
const _: () = assert!(std::mem::size_of::<Symbol>() == std::mem::size_of::<NonNull<()>>());
|
||||
const _: () = assert!(std::mem::align_of::<Symbol>() == std::mem::align_of::<NonNull<()>>());
|
||||
|
||||
static MAP: OnceLock<DashMap<SymbolProxy, (), BuildHasherDefault<FxHasher>>> = OnceLock::new();
|
||||
|
||||
impl Symbol {
|
||||
pub fn intern(s: &str) -> Self {
|
||||
let (mut shard, hash) = Self::select_shard(s);
|
||||
// Atomically,
|
||||
// - check if `obj` is already in the map
|
||||
// - if so, copy out its entry, conditionally bumping the backing Arc and return it
|
||||
// - if not, put it into a box and then into an Arc, insert it, bump the ref-count and return the copy
|
||||
// This needs to be atomic (locking the shard) to avoid races with other thread, which could
|
||||
// insert the same object between us looking it up and inserting it.
|
||||
match shard.raw_entry_mut().from_key_hashed_nocheck(hash, s) {
|
||||
RawEntryMut::Occupied(occ) => Self { repr: increase_arc_refcount(occ.key().0) },
|
||||
RawEntryMut::Vacant(vac) => Self {
|
||||
repr: increase_arc_refcount(
|
||||
vac.insert_hashed_nocheck(
|
||||
hash,
|
||||
SymbolProxy(TaggedArcPtr::arc(Arc::new(Box::<str>::from(s)))),
|
||||
SharedValue::new(()),
|
||||
)
|
||||
.0
|
||||
.0,
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
self.repr.as_str()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn select_shard(
|
||||
s: &str,
|
||||
) -> (
|
||||
dashmap::RwLockWriteGuard<
|
||||
'static,
|
||||
HashMap<SymbolProxy, SharedValue<()>, BuildHasherDefault<FxHasher>>,
|
||||
>,
|
||||
u64,
|
||||
) {
|
||||
let storage = MAP.get_or_init(symbols::prefill);
|
||||
let hash = {
|
||||
let mut hasher = std::hash::BuildHasher::build_hasher(storage.hasher());
|
||||
s.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
let shard_idx = storage.determine_shard(hash as usize);
|
||||
let shard = &storage.shards()[shard_idx];
|
||||
(shard.write(), hash)
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn drop_slow(arc: &Arc<Box<str>>) {
|
||||
let (mut shard, hash) = Self::select_shard(arc);
|
||||
|
||||
match Arc::count(arc) {
|
||||
0 => unreachable!(),
|
||||
1 => unreachable!(),
|
||||
2 => (),
|
||||
_ => {
|
||||
// Another thread has interned another copy
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ManuallyDrop::into_inner(
|
||||
match shard.raw_entry_mut().from_key_hashed_nocheck::<str>(hash, arc.as_ref()) {
|
||||
RawEntryMut::Occupied(occ) => occ.remove_entry(),
|
||||
RawEntryMut::Vacant(_) => unreachable!(),
|
||||
}
|
||||
.0
|
||||
.0
|
||||
.try_as_arc_owned()
|
||||
.unwrap(),
|
||||
);
|
||||
debug_assert_eq!(Arc::count(arc), 1);
|
||||
|
||||
// Shrink the backing storage if the shard is less than 50% occupied.
|
||||
if shard.len() * 2 < shard.capacity() {
|
||||
shard.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Symbol {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
let Some(arc) = self.repr.try_as_arc_owned() else {
|
||||
return;
|
||||
};
|
||||
// When the last `Ref` is dropped, remove the object from the global map.
|
||||
if Arc::count(&arc) == 2 {
|
||||
// Only `self` and the global map point to the object.
|
||||
|
||||
Self::drop_slow(&arc);
|
||||
}
|
||||
// decrement the ref count
|
||||
ManuallyDrop::into_inner(arc);
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for Symbol {
|
||||
fn clone(&self) -> Self {
|
||||
Self { repr: increase_arc_refcount(self.repr) }
|
||||
}
|
||||
}
|
||||
|
||||
fn increase_arc_refcount(repr: TaggedArcPtr) -> TaggedArcPtr {
|
||||
let Some(arc) = repr.try_as_arc_owned() else {
|
||||
return repr;
|
||||
};
|
||||
// increase the ref count
|
||||
mem::forget(Arc::clone(&arc));
|
||||
repr
|
||||
}
|
||||
|
||||
impl fmt::Display for Symbol {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
// only exists so we can use `from_key_hashed_nocheck` with a &str
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct SymbolProxy(TaggedArcPtr);
|
||||
|
||||
impl Hash for SymbolProxy {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.0.as_str().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Borrow<str> for SymbolProxy {
|
||||
fn borrow(&self) -> &str {
|
||||
self.0.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn smoke_test() {
|
||||
Symbol::intern("isize");
|
||||
let base_len = MAP.get().unwrap().len();
|
||||
let hello = Symbol::intern("hello");
|
||||
let world = Symbol::intern("world");
|
||||
let more_worlds = world.clone();
|
||||
let bang = Symbol::intern("!");
|
||||
let q = Symbol::intern("?");
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len + 4);
|
||||
let bang2 = Symbol::intern("!");
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len + 4);
|
||||
drop(bang2);
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len + 4);
|
||||
drop(q);
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len + 3);
|
||||
let default = Symbol::intern("default");
|
||||
let many_worlds = world.clone();
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len + 3);
|
||||
assert_eq!(
|
||||
"hello default world!",
|
||||
format!("{} {} {}{}", hello.as_str(), default.as_str(), world.as_str(), bang.as_str())
|
||||
);
|
||||
drop(default);
|
||||
assert_eq!(
|
||||
"hello world!",
|
||||
format!("{} {}{}", hello.as_str(), world.as_str(), bang.as_str())
|
||||
);
|
||||
drop(many_worlds);
|
||||
drop(more_worlds);
|
||||
drop(hello);
|
||||
drop(world);
|
||||
drop(bang);
|
||||
assert_eq!(MAP.get().unwrap().len(), base_len);
|
||||
}
|
||||
}
|
360
crates/intern/src/symbol/symbols.rs
Normal file
360
crates/intern/src/symbol/symbols.rs
Normal file
|
@ -0,0 +1,360 @@
|
|||
//! Module defining all known symbols required by the rest of rust-analyzer.
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use std::hash::{BuildHasherDefault, Hash as _, Hasher as _};
|
||||
|
||||
use dashmap::{DashMap, SharedValue};
|
||||
use rustc_hash::FxHasher;
|
||||
|
||||
use crate::{
|
||||
symbol::{SymbolProxy, TaggedArcPtr},
|
||||
Symbol,
|
||||
};
|
||||
|
||||
macro_rules! define_symbols {
|
||||
(@WITH_NAME: $($alias:ident = $value:literal),* $(,)? @PLAIN: $($name:ident),* $(,)?) => {
|
||||
// Ideally we would be emitting `const` here, but then we no longer have stable addresses
|
||||
// which is what we are relying on for equality! In the future if consts can refer to
|
||||
// statics we should swap these for `const`s and have the the string literal being pointed
|
||||
// to be statics to refer to such that their address is stable.
|
||||
$(
|
||||
pub static $name: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&stringify!($name)) };
|
||||
)*
|
||||
$(
|
||||
pub static $alias: Symbol = Symbol { repr: TaggedArcPtr::non_arc(&$value) };
|
||||
)*
|
||||
|
||||
|
||||
pub(super) fn prefill() -> DashMap<SymbolProxy, (), BuildHasherDefault<FxHasher>> {
|
||||
let mut dashmap_ = <DashMap<SymbolProxy, (), BuildHasherDefault<FxHasher>>>::with_hasher(BuildHasherDefault::default());
|
||||
|
||||
let hash_thing_ = |hasher_: &BuildHasherDefault<FxHasher>, it_: &SymbolProxy| {
|
||||
let mut hasher_ = std::hash::BuildHasher::build_hasher(hasher_);
|
||||
it_.hash(&mut hasher_);
|
||||
hasher_.finish()
|
||||
};
|
||||
{
|
||||
$(
|
||||
|
||||
let proxy_ = SymbolProxy($name.repr);
|
||||
let hash_ = hash_thing_(dashmap_.hasher(), &proxy_);
|
||||
let shard_idx_ = dashmap_.determine_shard(hash_ as usize);
|
||||
dashmap_.shards_mut()[shard_idx_].get_mut().raw_entry_mut().from_hash(hash_, |k| k == &proxy_).insert(proxy_, SharedValue::new(()));
|
||||
)*
|
||||
$(
|
||||
|
||||
let proxy_ = SymbolProxy($alias.repr);
|
||||
let hash_ = hash_thing_(dashmap_.hasher(), &proxy_);
|
||||
let shard_idx_ = dashmap_.determine_shard(hash_ as usize);
|
||||
dashmap_.shards_mut()[shard_idx_].get_mut().raw_entry_mut().from_hash(hash_, |k| k == &proxy_).insert(proxy_, SharedValue::new(()));
|
||||
)*
|
||||
}
|
||||
dashmap_
|
||||
}
|
||||
};
|
||||
}
|
||||
define_symbols! {
|
||||
@WITH_NAME:
|
||||
|
||||
self_ = "self",
|
||||
Self_ = "Self",
|
||||
tick_static = "'static",
|
||||
dollar_crate = "$crate",
|
||||
MISSING_NAME = "[missing name]",
|
||||
INTEGER_0 = "0",
|
||||
INTEGER_1 = "1",
|
||||
INTEGER_2 = "2",
|
||||
INTEGER_3 = "3",
|
||||
INTEGER_4 = "4",
|
||||
INTEGER_5 = "5",
|
||||
INTEGER_6 = "6",
|
||||
INTEGER_7 = "7",
|
||||
INTEGER_8 = "8",
|
||||
INTEGER_9 = "9",
|
||||
INTEGER_10 = "10",
|
||||
INTEGER_11 = "11",
|
||||
INTEGER_12 = "12",
|
||||
INTEGER_13 = "13",
|
||||
INTEGER_14 = "14",
|
||||
INTEGER_15 = "15",
|
||||
fn_ = "fn",
|
||||
|
||||
@PLAIN:
|
||||
add_assign,
|
||||
add,
|
||||
align_offset,
|
||||
alloc_layout,
|
||||
alloc,
|
||||
as_str,
|
||||
asm,
|
||||
assert,
|
||||
begin_panic,
|
||||
bench,
|
||||
bitand_assign,
|
||||
bitand,
|
||||
bitor_assign,
|
||||
bitor,
|
||||
bitxor_assign,
|
||||
bitxor,
|
||||
bool,
|
||||
box_free,
|
||||
Box,
|
||||
boxed,
|
||||
branch,
|
||||
Break,
|
||||
c_void,
|
||||
call_mut,
|
||||
call_once,
|
||||
call,
|
||||
Center,
|
||||
cfg_accessible,
|
||||
cfg_attr,
|
||||
cfg_eval,
|
||||
cfg,
|
||||
char,
|
||||
clone,
|
||||
Clone,
|
||||
coerce_unsized,
|
||||
column,
|
||||
compile_error,
|
||||
concat_bytes,
|
||||
concat_idents,
|
||||
concat,
|
||||
const_format_args,
|
||||
const_panic_fmt,
|
||||
const_param_ty,
|
||||
Context,
|
||||
Continue,
|
||||
copy,
|
||||
Copy,
|
||||
core_panic,
|
||||
core,
|
||||
coroutine_state,
|
||||
coroutine,
|
||||
crate_type,
|
||||
CStr,
|
||||
Debug,
|
||||
default,
|
||||
Default,
|
||||
deref_mut,
|
||||
deref_target,
|
||||
deref,
|
||||
derive_const,
|
||||
derive,
|
||||
discriminant_kind,
|
||||
discriminant_type,
|
||||
dispatch_from_dyn,destruct,
|
||||
div_assign,
|
||||
div,
|
||||
doc,
|
||||
drop_in_place,
|
||||
drop,
|
||||
dyn_metadata,
|
||||
eh_catch_typeinfo,
|
||||
eh_personality,
|
||||
env,
|
||||
eq,
|
||||
Eq,
|
||||
Err,
|
||||
exchange_malloc,
|
||||
f128,
|
||||
f16,
|
||||
f32,
|
||||
f64,
|
||||
feature,
|
||||
file,
|
||||
filter_map,
|
||||
fmt,
|
||||
fn_mut,
|
||||
fn_once_output,
|
||||
fn_once,
|
||||
fn_ptr_addr,
|
||||
fn_ptr_trait,
|
||||
format_alignment,
|
||||
format_args_nl,
|
||||
format_args,
|
||||
format_argument,
|
||||
format_arguments,
|
||||
format_count,
|
||||
format_placeholder,
|
||||
format_unsafe_arg,
|
||||
format,
|
||||
freeze,
|
||||
from_output,
|
||||
from_residual,
|
||||
from_usize,
|
||||
from_yeet,
|
||||
future_trait,
|
||||
future,
|
||||
Future,
|
||||
ge,
|
||||
get_context,
|
||||
global_allocator,
|
||||
global_asm,
|
||||
gt,
|
||||
Hash,
|
||||
i128,
|
||||
i16,
|
||||
i32,
|
||||
i64,
|
||||
i8,
|
||||
Implied,
|
||||
include_bytes,
|
||||
include_str,
|
||||
include,
|
||||
index_mut,
|
||||
index,
|
||||
Index,
|
||||
into_future,
|
||||
into_iter,
|
||||
IntoFuture,
|
||||
IntoIter,
|
||||
IntoIterator,
|
||||
is_empty,
|
||||
Is,
|
||||
isize,
|
||||
Item,
|
||||
iter_mut,
|
||||
iter,
|
||||
Iterator,
|
||||
le,
|
||||
Left,
|
||||
len,
|
||||
line,
|
||||
llvm_asm,
|
||||
log_syntax,
|
||||
lt,
|
||||
macro_rules,
|
||||
manually_drop,
|
||||
maybe_uninit,
|
||||
metadata_type,
|
||||
module_path,
|
||||
mul_assign,
|
||||
mul,
|
||||
ne,
|
||||
neg,
|
||||
Neg,
|
||||
new_binary,
|
||||
new_debug,
|
||||
new_display,
|
||||
new_lower_exp,
|
||||
new_lower_hex,
|
||||
new_octal,
|
||||
new_pointer,
|
||||
new_unchecked,
|
||||
new_upper_exp,
|
||||
new_upper_hex,
|
||||
new_v1_formatted,
|
||||
new,
|
||||
next,
|
||||
no_core,
|
||||
no_std,
|
||||
none,
|
||||
None,
|
||||
not,
|
||||
Not,
|
||||
Ok,
|
||||
opaque,
|
||||
ops,
|
||||
option_env,
|
||||
option,
|
||||
Option,
|
||||
Ord,
|
||||
Output,
|
||||
owned_box,
|
||||
panic_2015,
|
||||
panic_2021,
|
||||
panic_bounds_check,
|
||||
panic_cannot_unwind,
|
||||
panic_display,
|
||||
panic_fmt,
|
||||
panic_impl,
|
||||
panic_info,
|
||||
panic_location,
|
||||
panic_misaligned_pointer_dereference,
|
||||
panic_nounwind,
|
||||
panic,
|
||||
Param,
|
||||
partial_ord,
|
||||
PartialEq,
|
||||
PartialOrd,
|
||||
Pending,
|
||||
phantom_data,
|
||||
pieces,
|
||||
pin,
|
||||
pointee_trait,
|
||||
pointer_like,
|
||||
poll,
|
||||
Poll,
|
||||
prelude,
|
||||
quote,
|
||||
range_inclusive_new,
|
||||
Range,
|
||||
RangeFrom,
|
||||
RangeFull,
|
||||
RangeInclusive,
|
||||
RangeTo,
|
||||
RangeToInclusive,
|
||||
Ready,
|
||||
receiver,
|
||||
recursion_limit,
|
||||
register_attr,
|
||||
register_tool,
|
||||
rem_assign,
|
||||
rem,
|
||||
result,
|
||||
Result,
|
||||
ResumeTy,
|
||||
Right,
|
||||
rust_2015,
|
||||
rust_2018,
|
||||
rust_2021,
|
||||
rust_2024,
|
||||
rustc_coherence_is_core,
|
||||
rustc_macro_transparency,
|
||||
semitransparent,
|
||||
shl_assign,
|
||||
shl,
|
||||
shr_assign,
|
||||
shr,
|
||||
sized,
|
||||
slice_len_fn,
|
||||
Some,
|
||||
start,
|
||||
std_panic,
|
||||
std,
|
||||
str,
|
||||
string,
|
||||
String,
|
||||
stringify,
|
||||
structural_peq,
|
||||
structural_teq,
|
||||
sub_assign,
|
||||
sub,
|
||||
sync,
|
||||
Target,
|
||||
termination,
|
||||
test_case,
|
||||
test,
|
||||
trace_macros,
|
||||
transmute_opts,
|
||||
transmute_trait,
|
||||
transparent,
|
||||
Try,
|
||||
tuple_trait,
|
||||
u128,
|
||||
u16,
|
||||
u32,
|
||||
u64,
|
||||
u8,
|
||||
Unknown,
|
||||
unpin,
|
||||
unreachable_2015,
|
||||
unreachable_2021,
|
||||
unreachable,
|
||||
unsafe_cell,
|
||||
unsize,
|
||||
usize,
|
||||
v1,
|
||||
va_list
|
||||
}
|
Loading…
Reference in a new issue