mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #20475 from ShoyuVanilla/analysis-std-panic
fix: Make lang items query properly filter out overwritten/excluded sysroots
This commit is contained in:
commit
484db3a517
@ -30,6 +30,8 @@ use triomphe::Arc;
|
|||||||
pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet};
|
pub use vfs::{AnchoredPath, AnchoredPathBuf, FileId, VfsPath, file_set::FileSet};
|
||||||
|
|
||||||
pub type FxIndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>;
|
pub type FxIndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>;
|
||||||
|
pub type FxIndexMap<K, V> =
|
||||||
|
indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! impl_intern_key {
|
macro_rules! impl_intern_key {
|
||||||
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
StaticId, StructId, TraitId, TypeAliasId, UnionId,
|
StaticId, StructId, TraitId, TypeAliasId, UnionId,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
expr_store::path::Path,
|
expr_store::path::Path,
|
||||||
nameres::{assoc::TraitItems, crate_def_map},
|
nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
@ -170,7 +170,19 @@ pub fn lang_item(
|
|||||||
{
|
{
|
||||||
return Some(target);
|
return Some(target);
|
||||||
}
|
}
|
||||||
start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
|
|
||||||
|
// Our `CrateGraph` eagerly inserts sysroot dependencies like `core` or `std` into dependencies
|
||||||
|
// even if the target crate has `#![no_std]`, `#![no_core]` or shadowed sysroot dependencies
|
||||||
|
// like `dependencies.std.path = ".."`. So we use `extern_prelude()` instead of
|
||||||
|
// `CrateData.dependencies` here, which has already come through such sysroot complexities
|
||||||
|
// while nameres.
|
||||||
|
//
|
||||||
|
// See https://github.com/rust-lang/rust-analyzer/pull/20475 for details.
|
||||||
|
crate_local_def_map(db, start_crate).local(db).extern_prelude().find_map(|(_, (krate, _))| {
|
||||||
|
// Some crates declares themselves as extern crate like `extern crate self as core`.
|
||||||
|
// Ignore these to prevent cycles.
|
||||||
|
if krate.krate == start_crate { None } else { lang_item(db, krate.krate, item) }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
#[derive(Default, Debug, Clone, PartialEq, Eq)]
|
||||||
|
@ -545,6 +545,10 @@ impl DefMap {
|
|||||||
self.data.no_std || self.data.no_core
|
self.data.no_std || self.data.no_core
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_no_core(&self) -> bool {
|
||||||
|
self.data.no_core
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
|
pub fn fn_as_proc_macro(&self, id: FunctionId) -> Option<ProcMacroId> {
|
||||||
self.data.fn_proc_macro_mapping.get(&id).copied()
|
self.data.fn_proc_macro_mapping.get(&id).copied()
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,11 @@ use triomphe::Arc;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
AdtId, AssocItemId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
|
AdtId, AssocItemId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, ExternBlockLoc,
|
||||||
ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
|
ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, FxIndexMap, ImplLoc, Intern,
|
||||||
LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId,
|
ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
|
||||||
MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
|
MacroRulesId, MacroRulesLoc, MacroRulesLocFlags, ModuleDefId, ModuleId, ProcMacroId,
|
||||||
StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
|
ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId,
|
||||||
|
UseLoc,
|
||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
|
item_scope::{GlobId, ImportId, ImportOrExternCrate, PerNsGlobImports},
|
||||||
@ -69,7 +70,7 @@ pub(super) fn collect_defs(
|
|||||||
|
|
||||||
// populate external prelude and dependency list
|
// populate external prelude and dependency list
|
||||||
let mut deps =
|
let mut deps =
|
||||||
FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
|
FxIndexMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
|
||||||
for dep in &krate.dependencies {
|
for dep in &krate.dependencies {
|
||||||
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
|
tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
|
||||||
|
|
||||||
@ -220,7 +221,7 @@ struct DefCollector<'db> {
|
|||||||
/// Set only in case of blocks.
|
/// Set only in case of blocks.
|
||||||
crate_local_def_map: Option<&'db LocalDefMap>,
|
crate_local_def_map: Option<&'db LocalDefMap>,
|
||||||
// The dependencies of the current crate, including optional deps like `test`.
|
// The dependencies of the current crate, including optional deps like `test`.
|
||||||
deps: FxHashMap<Name, BuiltDependency>,
|
deps: FxIndexMap<Name, BuiltDependency>,
|
||||||
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
|
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, GlobId)>>,
|
||||||
unresolved_imports: Vec<ImportDirective>,
|
unresolved_imports: Vec<ImportDirective>,
|
||||||
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
|
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
|
||||||
@ -332,7 +333,9 @@ impl<'db> DefCollector<'db> {
|
|||||||
let skip = dep.is_sysroot()
|
let skip = dep.is_sysroot()
|
||||||
&& match dep.crate_id.data(self.db).origin {
|
&& match dep.crate_id.data(self.db).origin {
|
||||||
CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
|
CrateOrigin::Lang(LangCrateOrigin::Core) => crate_data.no_core,
|
||||||
CrateOrigin::Lang(LangCrateOrigin::Std) => crate_data.no_std,
|
CrateOrigin::Lang(LangCrateOrigin::Std) => {
|
||||||
|
crate_data.no_core || crate_data.no_std
|
||||||
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
if skip {
|
if skip {
|
||||||
@ -2550,7 +2553,7 @@ mod tests {
|
|||||||
def_map,
|
def_map,
|
||||||
local_def_map: LocalDefMap::default(),
|
local_def_map: LocalDefMap::default(),
|
||||||
crate_local_def_map: None,
|
crate_local_def_map: None,
|
||||||
deps: FxHashMap::default(),
|
deps: FxIndexMap::default(),
|
||||||
glob_imports: FxHashMap::default(),
|
glob_imports: FxHashMap::default(),
|
||||||
unresolved_imports: Vec::new(),
|
unresolved_imports: Vec::new(),
|
||||||
indeterminate_imports: Vec::new(),
|
indeterminate_imports: Vec::new(),
|
||||||
|
@ -2388,3 +2388,54 @@ pub trait Destruct {}
|
|||||||
"#,
|
"#,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_duplicated_lang_item_metadata() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
//- minicore: pointee
|
||||||
|
//- /main.rs crate:main deps:std,core
|
||||||
|
use std::AtomicPtr;
|
||||||
|
use std::null_mut;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x: AtomicPtr<()> = AtomicPtr::new(null_mut());
|
||||||
|
//^ AtomicPtr<()>
|
||||||
|
}
|
||||||
|
|
||||||
|
//- /lib.rs crate:r#std deps:core
|
||||||
|
#![no_std]
|
||||||
|
pub use core::*;
|
||||||
|
|
||||||
|
//- /lib.rs crate:r#core
|
||||||
|
#![no_core]
|
||||||
|
|
||||||
|
#[lang = "pointee_trait"]
|
||||||
|
pub trait Pointee {
|
||||||
|
#[lang = "metadata_type"]
|
||||||
|
type Metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AtomicPtr<T>(T);
|
||||||
|
|
||||||
|
impl<T> AtomicPtr<T> {
|
||||||
|
pub fn new(p: *mut T) -> AtomicPtr<T> {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[lang = "pointee_sized"]
|
||||||
|
pub trait PointeeSized {}
|
||||||
|
#[lang = "meta_sized"]
|
||||||
|
pub trait MetaSized: PointeeSized {}
|
||||||
|
#[lang = "sized"]
|
||||||
|
pub trait Sized: MetaSized {}
|
||||||
|
|
||||||
|
pub trait Thin = Pointee<Metadata = ()> + PointeeSized;
|
||||||
|
|
||||||
|
pub fn null_mut<T: PointeeSized + Thin>() -> *mut T {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -66,13 +66,9 @@ pub use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
|
|||||||
pub use ::line_index;
|
pub use ::line_index;
|
||||||
|
|
||||||
/// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
|
/// `base_db` is normally also needed in places where `ide_db` is used, so this re-export is for convenience.
|
||||||
pub use base_db;
|
pub use base_db::{self, FxIndexMap, FxIndexSet};
|
||||||
pub use span::{self, FileId};
|
pub use span::{self, FileId};
|
||||||
|
|
||||||
pub type FxIndexSet<T> = indexmap::IndexSet<T, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
|
||||||
pub type FxIndexMap<K, V> =
|
|
||||||
indexmap::IndexMap<K, V, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>;
|
|
||||||
|
|
||||||
pub type FilePosition = FilePositionWrapper<FileId>;
|
pub type FilePosition = FilePositionWrapper<FileId>;
|
||||||
pub type FileRange = FileRangeWrapper<FileId>;
|
pub type FileRange = FileRangeWrapper<FileId>;
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ use std::{any::TypeId, mem, str::FromStr, sync};
|
|||||||
|
|
||||||
use base_db::{
|
use base_db::{
|
||||||
Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
|
Crate, CrateDisplayName, CrateGraphBuilder, CrateName, CrateOrigin, CrateWorkspaceData,
|
||||||
DependencyBuilder, Env, FileChange, FileSet, LangCrateOrigin, SourceDatabase, SourceRoot,
|
DependencyBuilder, Env, FileChange, FileSet, FxIndexMap, LangCrateOrigin, SourceDatabase,
|
||||||
Version, VfsPath, salsa,
|
SourceRoot, Version, VfsPath, salsa,
|
||||||
};
|
};
|
||||||
use cfg::CfgOptions;
|
use cfg::CfgOptions;
|
||||||
use hir_expand::{
|
use hir_expand::{
|
||||||
@ -20,7 +20,6 @@ use hir_expand::{
|
|||||||
};
|
};
|
||||||
use intern::{Symbol, sym};
|
use intern::{Symbol, sym};
|
||||||
use paths::AbsPathBuf;
|
use paths::AbsPathBuf;
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use span::{Edition, FileId, Span};
|
use span::{Edition, FileId, Span};
|
||||||
use stdx::itertools::Itertools;
|
use stdx::itertools::Itertools;
|
||||||
use test_utils::{
|
use test_utils::{
|
||||||
@ -147,7 +146,7 @@ impl ChangeFixture {
|
|||||||
|
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
let mut crate_graph = CrateGraphBuilder::default();
|
let mut crate_graph = CrateGraphBuilder::default();
|
||||||
let mut crates = FxHashMap::default();
|
let mut crates = FxIndexMap::default();
|
||||||
let mut crate_deps = Vec::new();
|
let mut crate_deps = Vec::new();
|
||||||
let mut default_crate_root: Option<FileId> = None;
|
let mut default_crate_root: Option<FileId> = None;
|
||||||
let mut default_edition = Edition::CURRENT;
|
let mut default_edition = Edition::CURRENT;
|
||||||
@ -249,37 +248,7 @@ impl ChangeFixture {
|
|||||||
file_id = FileId::from_raw(file_id.index() + 1);
|
file_id = FileId::from_raw(file_id.index() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if crates.is_empty() {
|
let mini_core = mini_core.map(|mini_core| {
|
||||||
let crate_root = default_crate_root
|
|
||||||
.expect("missing default crate root, specify a main.rs or lib.rs");
|
|
||||||
crate_graph.add_crate_root(
|
|
||||||
crate_root,
|
|
||||||
default_edition,
|
|
||||||
Some(CrateName::new("ra_test_fixture").unwrap().into()),
|
|
||||||
None,
|
|
||||||
default_cfg.clone(),
|
|
||||||
Some(default_cfg),
|
|
||||||
default_env,
|
|
||||||
CrateOrigin::Local { repo: None, name: None },
|
|
||||||
false,
|
|
||||||
proc_macro_cwd.clone(),
|
|
||||||
crate_ws_data.clone(),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
for (from, to, prelude) in crate_deps {
|
|
||||||
let from_id = crates[&from];
|
|
||||||
let to_id = crates[&to];
|
|
||||||
let sysroot = crate_graph[to_id].basic.origin.is_lang();
|
|
||||||
crate_graph
|
|
||||||
.add_dep(
|
|
||||||
from_id,
|
|
||||||
DependencyBuilder::with_prelude(to.clone(), to_id, prelude, sysroot),
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(mini_core) = mini_core {
|
|
||||||
let core_file = file_id;
|
let core_file = file_id;
|
||||||
file_id = FileId::from_raw(file_id.index() + 1);
|
file_id = FileId::from_raw(file_id.index() + 1);
|
||||||
|
|
||||||
@ -289,8 +258,6 @@ impl ChangeFixture {
|
|||||||
|
|
||||||
source_change.change_file(core_file, Some(mini_core.source_code()));
|
source_change.change_file(core_file, Some(mini_core.source_code()));
|
||||||
|
|
||||||
let all_crates = crate_graph.iter().collect::<Vec<_>>();
|
|
||||||
|
|
||||||
let core_crate = crate_graph.add_crate_root(
|
let core_crate = crate_graph.add_crate_root(
|
||||||
core_file,
|
core_file,
|
||||||
Edition::CURRENT,
|
Edition::CURRENT,
|
||||||
@ -308,16 +275,58 @@ impl ChangeFixture {
|
|||||||
crate_ws_data.clone(),
|
crate_ws_data.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
for krate in all_crates {
|
(
|
||||||
|
move || {
|
||||||
|
DependencyBuilder::with_prelude(
|
||||||
|
CrateName::new("core").unwrap(),
|
||||||
|
core_crate,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
core_crate,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
if crates.is_empty() {
|
||||||
|
let crate_root = default_crate_root
|
||||||
|
.expect("missing default crate root, specify a main.rs or lib.rs");
|
||||||
|
let root = crate_graph.add_crate_root(
|
||||||
|
crate_root,
|
||||||
|
default_edition,
|
||||||
|
Some(CrateName::new("ra_test_fixture").unwrap().into()),
|
||||||
|
None,
|
||||||
|
default_cfg.clone(),
|
||||||
|
Some(default_cfg),
|
||||||
|
default_env,
|
||||||
|
CrateOrigin::Local { repo: None, name: None },
|
||||||
|
false,
|
||||||
|
proc_macro_cwd.clone(),
|
||||||
|
crate_ws_data.clone(),
|
||||||
|
);
|
||||||
|
if let Some((mini_core, _)) = mini_core {
|
||||||
|
crate_graph.add_dep(root, mini_core()).unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Insert minicore first to match with `project-model::workspace`
|
||||||
|
if let Some((mini_core, core_crate)) = mini_core {
|
||||||
|
let all_crates = crate_graph.iter().collect::<Vec<_>>();
|
||||||
|
for krate in all_crates {
|
||||||
|
if krate == core_crate {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
crate_graph.add_dep(krate, mini_core()).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (from, to, prelude) in crate_deps {
|
||||||
|
let from_id = crates[&from];
|
||||||
|
let to_id = crates[&to];
|
||||||
|
let sysroot = crate_graph[to_id].basic.origin.is_lang();
|
||||||
crate_graph
|
crate_graph
|
||||||
.add_dep(
|
.add_dep(
|
||||||
krate,
|
from_id,
|
||||||
DependencyBuilder::with_prelude(
|
DependencyBuilder::with_prelude(to.clone(), to_id, prelude, sysroot),
|
||||||
CrateName::new("core").unwrap(),
|
|
||||||
core_crate,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
@ -627,11 +636,23 @@ impl FileMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
enum ForceNoneLangOrigin {
|
||||||
|
Yes,
|
||||||
|
No,
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_crate(
|
fn parse_crate(
|
||||||
crate_str: String,
|
crate_str: String,
|
||||||
current_source_root_kind: SourceRootKind,
|
current_source_root_kind: SourceRootKind,
|
||||||
explicit_non_workspace_member: bool,
|
explicit_non_workspace_member: bool,
|
||||||
) -> (String, CrateOrigin, Option<String>) {
|
) -> (String, CrateOrigin, Option<String>) {
|
||||||
|
let (crate_str, force_non_lang_origin) = if let Some(s) = crate_str.strip_prefix("r#") {
|
||||||
|
(s.to_owned(), ForceNoneLangOrigin::Yes)
|
||||||
|
} else {
|
||||||
|
(crate_str, ForceNoneLangOrigin::No)
|
||||||
|
};
|
||||||
|
|
||||||
// syntax:
|
// syntax:
|
||||||
// "my_awesome_crate"
|
// "my_awesome_crate"
|
||||||
// "my_awesome_crate@0.0.1,http://example.com"
|
// "my_awesome_crate@0.0.1,http://example.com"
|
||||||
@ -646,16 +667,25 @@ fn parse_crate(
|
|||||||
let non_workspace_member = explicit_non_workspace_member
|
let non_workspace_member = explicit_non_workspace_member
|
||||||
|| matches!(current_source_root_kind, SourceRootKind::Library);
|
|| matches!(current_source_root_kind, SourceRootKind::Library);
|
||||||
|
|
||||||
let origin = match LangCrateOrigin::from(&*name) {
|
let origin = if force_non_lang_origin == ForceNoneLangOrigin::Yes {
|
||||||
LangCrateOrigin::Other => {
|
let name = Symbol::intern(&name);
|
||||||
let name = Symbol::intern(&name);
|
if non_workspace_member {
|
||||||
if non_workspace_member {
|
CrateOrigin::Library { repo, name }
|
||||||
CrateOrigin::Library { repo, name }
|
} else {
|
||||||
} else {
|
CrateOrigin::Local { repo, name: Some(name) }
|
||||||
CrateOrigin::Local { repo, name: Some(name) }
|
}
|
||||||
}
|
} else {
|
||||||
|
match LangCrateOrigin::from(&*name) {
|
||||||
|
LangCrateOrigin::Other => {
|
||||||
|
let name = Symbol::intern(&name);
|
||||||
|
if non_workspace_member {
|
||||||
|
CrateOrigin::Library { repo, name }
|
||||||
|
} else {
|
||||||
|
CrateOrigin::Local { repo, name: Some(name) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
origin => CrateOrigin::Lang(origin),
|
||||||
}
|
}
|
||||||
origin => CrateOrigin::Lang(origin),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(name, origin, version)
|
(name, origin, version)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user