mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 22:54:58 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
544b4cfe4d
commit
dbf04a5ee2
106 changed files with 2219 additions and 609 deletions
|
@ -40,6 +40,7 @@ pub struct StructData {
|
|||
pub repr: Option<ReprOptions>,
|
||||
pub visibility: RawVisibility,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
pub fundamental: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
@ -173,10 +174,10 @@ impl StructData {
|
|||
let item_tree = loc.id.item_tree(db);
|
||||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
let rustc_has_incoherent_inherent_impls = item_tree
|
||||
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||
.by_key("rustc_has_incoherent_inherent_impls")
|
||||
.exists();
|
||||
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
||||
let fundamental = attrs.by_key("fundamental").exists();
|
||||
|
||||
let strukt = &item_tree[loc.id.value];
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
|
@ -196,6 +197,7 @@ impl StructData {
|
|||
repr,
|
||||
visibility: item_tree[strukt.visibility].clone(),
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
fundamental,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
|
@ -215,10 +217,10 @@ impl StructData {
|
|||
let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
|
||||
let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();
|
||||
|
||||
let rustc_has_incoherent_inherent_impls = item_tree
|
||||
.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
|
||||
.by_key("rustc_has_incoherent_inherent_impls")
|
||||
.exists();
|
||||
let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
||||
let fundamental = attrs.by_key("fundamental").exists();
|
||||
|
||||
let union = &item_tree[loc.id.value];
|
||||
let (variant_data, diagnostics) = lower_fields(
|
||||
|
@ -238,6 +240,7 @@ impl StructData {
|
|||
repr,
|
||||
visibility: item_tree[union.visibility].clone(),
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
fundamental,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
|
|
|
@ -24,7 +24,9 @@ use syntax::{ast, AstPtr, SyntaxNode, SyntaxNodePtr};
|
|||
use crate::{
|
||||
attr::Attrs,
|
||||
db::DefDatabase,
|
||||
expr::{dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId},
|
||||
expr::{
|
||||
dummy_expr_id, Binding, BindingId, Expr, ExprId, Label, LabelId, Pat, PatId, RecordFieldPat,
|
||||
},
|
||||
item_scope::BuiltinShadowMode,
|
||||
macro_id_to_def_id,
|
||||
nameres::DefMap,
|
||||
|
@ -432,6 +434,44 @@ impl Body {
|
|||
pats.shrink_to_fit();
|
||||
bindings.shrink_to_fit();
|
||||
}
|
||||
|
||||
pub fn walk_bindings_in_pat(&self, pat_id: PatId, mut f: impl FnMut(BindingId)) {
|
||||
self.walk_pats(pat_id, &mut |pat| {
|
||||
if let Pat::Bind { id, .. } = pat {
|
||||
f(*id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn walk_pats(&self, pat_id: PatId, f: &mut impl FnMut(&Pat)) {
|
||||
let pat = &self[pat_id];
|
||||
f(pat);
|
||||
match pat {
|
||||
Pat::Range { .. }
|
||||
| Pat::Lit(..)
|
||||
| Pat::Path(..)
|
||||
| Pat::ConstBlock(..)
|
||||
| Pat::Wild
|
||||
| Pat::Missing => {}
|
||||
&Pat::Bind { subpat, .. } => {
|
||||
if let Some(subpat) = subpat {
|
||||
self.walk_pats(subpat, f);
|
||||
}
|
||||
}
|
||||
Pat::Or(args) | Pat::Tuple { args, .. } | Pat::TupleStruct { args, .. } => {
|
||||
args.iter().copied().for_each(|p| self.walk_pats(p, f));
|
||||
}
|
||||
Pat::Ref { pat, .. } => self.walk_pats(*pat, f),
|
||||
Pat::Slice { prefix, slice, suffix } => {
|
||||
let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
|
||||
total_iter.copied().for_each(|p| self.walk_pats(p, f));
|
||||
}
|
||||
Pat::Record { args, .. } => {
|
||||
args.iter().for_each(|RecordFieldPat { pat, .. }| self.walk_pats(*pat, f));
|
||||
}
|
||||
Pat::Box { inner } => self.walk_pats(*inner, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Body {
|
||||
|
|
|
@ -499,6 +499,8 @@ impl ExprCollector<'_> {
|
|||
Movability::Movable
|
||||
};
|
||||
ClosureKind::Generator(movability)
|
||||
} else if e.async_token().is_some() {
|
||||
ClosureKind::Async
|
||||
} else {
|
||||
ClosureKind::Closure
|
||||
};
|
||||
|
|
|
@ -360,8 +360,14 @@ impl<'a> Printer<'a> {
|
|||
w!(self, "]");
|
||||
}
|
||||
Expr::Closure { args, arg_types, ret_type, body, closure_kind } => {
|
||||
if let ClosureKind::Generator(Movability::Static) = closure_kind {
|
||||
w!(self, "static ");
|
||||
match closure_kind {
|
||||
ClosureKind::Generator(Movability::Static) => {
|
||||
w!(self, "static ");
|
||||
}
|
||||
ClosureKind::Async => {
|
||||
w!(self, "async ");
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
w!(self, "|");
|
||||
for (i, (pat, ty)) in args.iter().zip(arg_types.iter()).enumerate() {
|
||||
|
|
|
@ -35,6 +35,7 @@ pub struct FunctionData {
|
|||
pub visibility: RawVisibility,
|
||||
pub abi: Option<Interned<str>>,
|
||||
pub legacy_const_generics_indices: Box<[u32]>,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
flags: FnFlags,
|
||||
}
|
||||
|
||||
|
@ -84,13 +85,14 @@ impl FunctionData {
|
|||
}
|
||||
}
|
||||
|
||||
let legacy_const_generics_indices = item_tree
|
||||
.attrs(db, krate, ModItem::from(loc.id.value).into())
|
||||
let attrs = item_tree.attrs(db, krate, ModItem::from(loc.id.value).into());
|
||||
let legacy_const_generics_indices = attrs
|
||||
.by_key("rustc_legacy_const_generics")
|
||||
.tt_values()
|
||||
.next()
|
||||
.map(parse_rustc_legacy_const_generics)
|
||||
.unwrap_or_default();
|
||||
let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
|
||||
|
||||
Arc::new(FunctionData {
|
||||
name: func.name.clone(),
|
||||
|
@ -108,6 +110,7 @@ impl FunctionData {
|
|||
abi: func.abi.clone(),
|
||||
legacy_const_generics_indices,
|
||||
flags,
|
||||
rustc_allow_incoherent_impl,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -171,6 +174,7 @@ pub struct TypeAliasData {
|
|||
pub visibility: RawVisibility,
|
||||
pub is_extern: bool,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
/// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
|
||||
pub bounds: Vec<Interned<TypeBound>>,
|
||||
}
|
||||
|
@ -189,10 +193,14 @@ impl TypeAliasData {
|
|||
item_tree[typ.visibility].clone()
|
||||
};
|
||||
|
||||
let rustc_has_incoherent_inherent_impls = item_tree
|
||||
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
|
||||
.by_key("rustc_has_incoherent_inherent_impls")
|
||||
.exists();
|
||||
let attrs = item_tree.attrs(
|
||||
db,
|
||||
loc.container.module(db).krate(),
|
||||
ModItem::from(loc.id.value).into(),
|
||||
);
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
||||
let rustc_allow_incoherent_impl = attrs.by_key("rustc_allow_incoherent_impl").exists();
|
||||
|
||||
Arc::new(TypeAliasData {
|
||||
name: typ.name.clone(),
|
||||
|
@ -200,6 +208,7 @@ impl TypeAliasData {
|
|||
visibility,
|
||||
is_extern: matches!(loc.container, ItemContainerId::ExternBlockId(_)),
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
rustc_allow_incoherent_impl,
|
||||
bounds: typ.bounds.to_vec(),
|
||||
})
|
||||
}
|
||||
|
@ -212,11 +221,12 @@ pub struct TraitData {
|
|||
pub is_auto: bool,
|
||||
pub is_unsafe: bool,
|
||||
pub rustc_has_incoherent_inherent_impls: bool,
|
||||
pub skip_array_during_method_dispatch: bool,
|
||||
pub fundamental: bool,
|
||||
pub visibility: RawVisibility,
|
||||
/// Whether the trait has `#[rust_skip_array_during_method_dispatch]`. `hir_ty` will ignore
|
||||
/// method calls to this trait's methods when the receiver is an array and the crate edition is
|
||||
/// 2015 or 2018.
|
||||
pub skip_array_during_method_dispatch: bool,
|
||||
// box it as the vec is usually empty anyways
|
||||
pub attribute_calls: Option<Box<Vec<(AstId<ast::Item>, MacroCallId)>>>,
|
||||
}
|
||||
|
@ -245,6 +255,7 @@ impl TraitData {
|
|||
attrs.by_key("rustc_skip_array_during_method_dispatch").exists();
|
||||
let rustc_has_incoherent_inherent_impls =
|
||||
attrs.by_key("rustc_has_incoherent_inherent_impls").exists();
|
||||
let fundamental = attrs.by_key("fundamental").exists();
|
||||
let mut collector =
|
||||
AssocItemCollector::new(db, module_id, tree_id.file_id(), ItemContainerId::TraitId(tr));
|
||||
collector.collect(&item_tree, tree_id.tree_id(), &tr_def.items);
|
||||
|
@ -260,6 +271,7 @@ impl TraitData {
|
|||
visibility,
|
||||
skip_array_during_method_dispatch,
|
||||
rustc_has_incoherent_inherent_impls,
|
||||
fundamental,
|
||||
}),
|
||||
diagnostics.into(),
|
||||
)
|
||||
|
@ -450,6 +462,7 @@ pub struct ConstData {
|
|||
pub name: Option<Name>,
|
||||
pub type_ref: Interned<TypeRef>,
|
||||
pub visibility: RawVisibility,
|
||||
pub rustc_allow_incoherent_impl: bool,
|
||||
}
|
||||
|
||||
impl ConstData {
|
||||
|
@ -463,10 +476,16 @@ impl ConstData {
|
|||
item_tree[konst.visibility].clone()
|
||||
};
|
||||
|
||||
let rustc_allow_incoherent_impl = item_tree
|
||||
.attrs(db, loc.container.module(db).krate(), ModItem::from(loc.id.value).into())
|
||||
.by_key("rustc_allow_incoherent_impl")
|
||||
.exists();
|
||||
|
||||
Arc::new(ConstData {
|
||||
name: konst.name.clone(),
|
||||
type_ref: konst.type_ref.clone(),
|
||||
visibility,
|
||||
rustc_allow_incoherent_impl,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||
|
||||
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
|
||||
use either::Either;
|
||||
use hir_expand::{db::AstDatabase, HirFileId};
|
||||
use hir_expand::{db::ExpandDatabase, HirFileId};
|
||||
use intern::Interned;
|
||||
use la_arena::ArenaMap;
|
||||
use syntax::{ast, AstPtr};
|
||||
|
@ -64,7 +64,7 @@ pub trait InternDatabase: SourceDatabase {
|
|||
}
|
||||
|
||||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
|
||||
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
|
||||
#[salsa::input]
|
||||
fn enable_proc_attr_macros(&self) -> bool;
|
||||
|
||||
|
|
|
@ -245,6 +245,7 @@ pub enum Expr {
|
|||
pub enum ClosureKind {
|
||||
Closure,
|
||||
Generator(Movability),
|
||||
Async,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
|
|
@ -20,7 +20,7 @@ use ::mbe::TokenMap;
|
|||
use base_db::{fixture::WithFixture, ProcMacro, SourceDatabase};
|
||||
use expect_test::Expect;
|
||||
use hir_expand::{
|
||||
db::{AstDatabase, TokenExpander},
|
||||
db::{ExpandDatabase, TokenExpander},
|
||||
AstId, InFile, MacroDefId, MacroDefKind, MacroFile,
|
||||
};
|
||||
use stdx::format_to;
|
||||
|
|
|
@ -120,6 +120,8 @@ pub struct DefMap {
|
|||
registered_tools: Vec<SmolStr>,
|
||||
/// Unstable features of Rust enabled with `#![feature(A, B)]`.
|
||||
unstable_features: FxHashSet<SmolStr>,
|
||||
/// #[rustc_coherence_is_core]
|
||||
rustc_coherence_is_core: bool,
|
||||
|
||||
edition: Edition,
|
||||
recursion_limit: Option<u32>,
|
||||
|
@ -215,7 +217,7 @@ pub struct ModuleData {
|
|||
pub origin: ModuleOrigin,
|
||||
/// Declared visibility of this module.
|
||||
pub visibility: Visibility,
|
||||
|
||||
/// Always [`None`] for block modules
|
||||
pub parent: Option<LocalModuleId>,
|
||||
pub children: FxHashMap<Name, LocalModuleId>,
|
||||
pub scope: ItemScope,
|
||||
|
@ -292,6 +294,7 @@ impl DefMap {
|
|||
registered_tools: Vec::new(),
|
||||
unstable_features: FxHashSet::default(),
|
||||
diagnostics: Vec::new(),
|
||||
rustc_coherence_is_core: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -325,6 +328,10 @@ impl DefMap {
|
|||
self.unstable_features.contains(feature)
|
||||
}
|
||||
|
||||
pub fn is_rustc_coherence_is_core(&self) -> bool {
|
||||
self.rustc_coherence_is_core
|
||||
}
|
||||
|
||||
pub fn root(&self) -> LocalModuleId {
|
||||
self.root
|
||||
}
|
||||
|
@ -337,7 +344,7 @@ impl DefMap {
|
|||
self.proc_macro_loading_error.as_deref()
|
||||
}
|
||||
|
||||
pub(crate) fn krate(&self) -> CrateId {
|
||||
pub fn krate(&self) -> CrateId {
|
||||
self.krate
|
||||
}
|
||||
|
||||
|
@ -425,7 +432,7 @@ impl DefMap {
|
|||
Some(self.block?.parent)
|
||||
}
|
||||
|
||||
/// Returns the module containing `local_mod`, either the parent `mod`, or the module containing
|
||||
/// Returns the module containing `local_mod`, either the parent `mod`, or the module (or block) containing
|
||||
/// the block, if `self` corresponds to a block expression.
|
||||
pub fn containing_module(&self, local_mod: LocalModuleId) -> Option<ModuleId> {
|
||||
match self[local_mod].parent {
|
||||
|
@ -498,6 +505,7 @@ impl DefMap {
|
|||
krate: _,
|
||||
prelude: _,
|
||||
root: _,
|
||||
rustc_coherence_is_core: _,
|
||||
} = self;
|
||||
|
||||
extern_prelude.shrink_to_fit();
|
||||
|
|
|
@ -87,10 +87,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: T
|
|||
// FIXME: a hacky way to create a Name from string.
|
||||
let name =
|
||||
tt::Ident { text: it.name.clone(), span: tt::TokenId::unspecified() };
|
||||
(
|
||||
name.as_name(),
|
||||
ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
|
||||
)
|
||||
(name.as_name(), ProcMacroExpander::new(base_db::ProcMacroId(idx as u32)))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
@ -299,6 +296,11 @@ impl DefCollector<'_> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
|
||||
self.def_map.rustc_coherence_is_core = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if *attr_name == hir_expand::name![feature] {
|
||||
let features =
|
||||
attr.parse_path_comma_token_tree().into_iter().flatten().filter_map(
|
||||
|
@ -581,7 +583,7 @@ impl DefCollector<'_> {
|
|||
let kind = def.kind.to_basedb_kind();
|
||||
let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
|
||||
Some(&(_, expander)) => (expander, kind),
|
||||
None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
|
||||
None => (ProcMacroExpander::dummy(), kind),
|
||||
};
|
||||
|
||||
let proc_macro_id =
|
||||
|
|
|
@ -9,7 +9,7 @@ use base_db::{
|
|||
salsa, AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition,
|
||||
SourceDatabase, Upcast,
|
||||
};
|
||||
use hir_expand::{db::AstDatabase, InFile};
|
||||
use hir_expand::{db::ExpandDatabase, InFile};
|
||||
use stdx::hash::NoHashHashSet;
|
||||
use syntax::{algo, ast, AstNode};
|
||||
|
||||
|
@ -23,7 +23,7 @@ use crate::{
|
|||
#[salsa::database(
|
||||
base_db::SourceDatabaseExtStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir_expand::db::AstDatabaseStorage,
|
||||
hir_expand::db::ExpandDatabaseStorage,
|
||||
crate::db::InternDatabaseStorage,
|
||||
crate::db::DefDatabaseStorage
|
||||
)]
|
||||
|
@ -40,8 +40,8 @@ impl Default for TestDB {
|
|||
}
|
||||
}
|
||||
|
||||
impl Upcast<dyn AstDatabase> for TestDB {
|
||||
fn upcast(&self) -> &(dyn AstDatabase + 'static) {
|
||||
impl Upcast<dyn ExpandDatabase> for TestDB {
|
||||
fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
|
||||
&*self
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,21 +131,23 @@ impl Visibility {
|
|||
// visibility as the containing module (even though no items are directly nameable from
|
||||
// there, getting this right is important for method resolution).
|
||||
// In that case, we adjust the visibility of `to_module` to point to the containing module.
|
||||
|
||||
// Additional complication: `to_module` might be in `from_module`'s `DefMap`, which we're
|
||||
// currently computing, so we must not call the `def_map` query for it.
|
||||
let arc;
|
||||
let to_module_def_map =
|
||||
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
|
||||
cov_mark::hit!(is_visible_from_same_block_def_map);
|
||||
def_map
|
||||
} else {
|
||||
arc = to_module.def_map(db);
|
||||
&arc
|
||||
};
|
||||
let is_block_root =
|
||||
to_module.block.is_some() && to_module_def_map[to_module.local_id].parent.is_none();
|
||||
if is_block_root {
|
||||
to_module = to_module_def_map.containing_module(to_module.local_id).unwrap();
|
||||
let mut arc;
|
||||
loop {
|
||||
let to_module_def_map =
|
||||
if to_module.krate == def_map.krate() && to_module.block == def_map.block_id() {
|
||||
cov_mark::hit!(is_visible_from_same_block_def_map);
|
||||
def_map
|
||||
} else {
|
||||
arc = to_module.def_map(db);
|
||||
&arc
|
||||
};
|
||||
match to_module_def_map.parent() {
|
||||
Some(parent) => to_module = parent,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
// from_module needs to be a descendant of to_module
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue