mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Auto merge of #131832 - lnicola:sync-from-ra, r=lnicola
Subtree update of `rust-analyzer` r? `@ghost`
This commit is contained in:
commit
3a85d3fa78
@ -1187,6 +1187,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.33.0"
|
||||
@ -1439,9 +1448,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "protobuf"
|
||||
version = "3.2.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b55bad9126f378a853655831eb7363b7b01b81d19f8cb1218861086ca4a1a61e"
|
||||
checksum = "a3a7c64d9bf75b1b8d981124c14c179074e8caa7dfe7b6a12e6222ddcd0c8f72"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"protobuf-support",
|
||||
@ -1450,9 +1459,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "protobuf-support"
|
||||
version = "3.2.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5d4d7b8601c814cfb36bcebb79f0e61e45e1e93640cf778837833bbed05c372"
|
||||
checksum = "b088fd20b938a875ea00843b6faf48579462630015c3788d397ad6a786663252"
|
||||
dependencies = [
|
||||
"thiserror",
|
||||
]
|
||||
@ -1488,9 +1497,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_abi"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a8cb51bb4534ac3e9c74f1d9bd90e607e60f94f734b1cf1a66f753ad2af6ed7"
|
||||
checksum = "c6999d098000b98415939f13158dac78cb3eeeb7b0c073847f3e4b623866e27c"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"ra-ap-rustc_index",
|
||||
@ -1499,9 +1508,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b640fba2b7ef4f875459e2e76daeb846ef341d1d376fa758962ac0eba79bce6"
|
||||
checksum = "ae9fb312d942817dab10790881f555928c1f6a11a85186e8e573ad4a86c7d3be"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"ra-ap-rustc_index_macros",
|
||||
@ -1510,9 +1519,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_index_macros"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "faef502419ba5ac9d3079b1a835c6e5b4e605388254bbe55eb5683936f541be9"
|
||||
checksum = "766e3990eb1066a06deefc561b5a01b32ca5c9211feea31cbf4ed50611519872"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1521,9 +1530,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_lexer"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5da7f9d533b8d5be6704558da741ff20b982ad4647b1e9e08632853e4fecf9d5"
|
||||
checksum = "f4afa98eb7889c137d5a3f1cd189089e16da04d1e4837d358a67aa3dab10ffbe"
|
||||
dependencies = [
|
||||
"unicode-properties",
|
||||
"unicode-xid",
|
||||
@ -1531,9 +1540,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_parse_format"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94389cf81c651b1bda9ac45d3de6a2d851bb6fd4cb893875daa44e419c94205f"
|
||||
checksum = "d9234c96ffb0565286790407fb7eb7f55ebf69267de4db382fdec0a17f14b0e2"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"ra-ap-rustc_lexer",
|
||||
@ -1541,9 +1550,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ra-ap-rustc_pattern_analysis"
|
||||
version = "0.68.0"
|
||||
version = "0.71.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3679d8dd0114ed6000918309f843782738e51c99d8e4baec0d0f706e4d948819"
|
||||
checksum = "273d5f72926a58c7eea27aebc898d1d5b32d23d2342f692a94a2cf8746aa4a2f"
|
||||
dependencies = [
|
||||
"ra-ap-rustc_index",
|
||||
"rustc-hash",
|
||||
@ -1765,9 +1774,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "scip"
|
||||
version = "0.3.3"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5dc1bd66649133af84ab62436ddd2856c2605182b02dec2cd197f684dfe15ef"
|
||||
checksum = "8dfafd2fa14c6237fa1fc4310f739d02fa915d92977fa069426591f1de046f81"
|
||||
dependencies = [
|
||||
"protobuf",
|
||||
]
|
||||
@ -2093,10 +2102,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
"libc",
|
||||
"num-conv",
|
||||
"num_threads",
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2105,6 +2118,16 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.8.0"
|
||||
@ -2213,6 +2236,7 @@ checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
|
||||
dependencies = [
|
||||
"sharded-slab",
|
||||
"thread_local",
|
||||
"time",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
]
|
||||
|
@ -74,7 +74,7 @@ proc-macro-srv = { path = "./crates/proc-macro-srv", version = "0.0.0" }
|
||||
proc-macro-srv-cli = { path = "./crates/proc-macro-srv-cli", version = "0.0.0" }
|
||||
profile = { path = "./crates/profile", version = "0.0.0" }
|
||||
project-model = { path = "./crates/project-model", version = "0.0.0" }
|
||||
salsa = { path = "./crates/salsa", version = "0.0.0" }
|
||||
ra-salsa = { path = "./crates/ra-salsa", package = "salsa", version = "0.0.0" }
|
||||
span = { path = "./crates/span", version = "0.0.0" }
|
||||
stdx = { path = "./crates/stdx", version = "0.0.0" }
|
||||
syntax = { path = "./crates/syntax", version = "0.0.0" }
|
||||
@ -85,11 +85,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
|
||||
vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
|
||||
vfs = { path = "./crates/vfs", version = "0.0.0" }
|
||||
|
||||
ra-ap-rustc_lexer = { version = "0.68.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.68.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.68.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.68.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.68.0", default-features = false }
|
||||
ra-ap-rustc_lexer = { version = "0.71.0", default-features = false }
|
||||
ra-ap-rustc_parse_format = { version = "0.71.0", default-features = false }
|
||||
ra-ap-rustc_index = { version = "0.71.0", default-features = false }
|
||||
ra-ap-rustc_abi = { version = "0.71.0", default-features = false }
|
||||
ra-ap-rustc_pattern_analysis = { version = "0.71.0", default-features = false }
|
||||
|
||||
# local crates that aren't published to crates.io. These should not have versions.
|
||||
test-fixture = { path = "./crates/test-fixture" }
|
||||
@ -153,6 +153,9 @@ tracing-tree = "0.3.0"
|
||||
tracing-subscriber = { version = "0.3.18", default-features = false, features = [
|
||||
"registry",
|
||||
"fmt",
|
||||
"local-time",
|
||||
"std",
|
||||
"time",
|
||||
"tracing-log",
|
||||
] }
|
||||
triomphe = { version = "0.1.10", default-features = false, features = ["std"] }
|
||||
|
@ -16,7 +16,7 @@ doctest = false
|
||||
lz4_flex = { version = "0.11", default-features = false }
|
||||
|
||||
la-arena.workspace = true
|
||||
salsa.workspace = true
|
||||
ra-salsa.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
triomphe.workspace = true
|
||||
semver.workspace = true
|
||||
|
@ -3,8 +3,8 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use ra_salsa::Durability;
|
||||
use rustc_hash::FxHashMap;
|
||||
use salsa::Durability;
|
||||
use triomphe::Arc;
|
||||
use vfs::FileId;
|
||||
|
||||
|
@ -288,6 +288,11 @@ pub struct CrateData {
|
||||
/// The cfg options that could be used by the crate
|
||||
pub potential_cfg_options: Option<Arc<CfgOptions>>,
|
||||
pub env: Env,
|
||||
/// The dependencies of this crate.
|
||||
///
|
||||
/// Note that this may contain more dependencies than the crate actually uses.
|
||||
/// A common example is the test crate which is included but only actually is active when
|
||||
/// declared in source via `extern crate test`.
|
||||
pub dependencies: Vec<Dependency>,
|
||||
pub origin: CrateOrigin,
|
||||
pub is_proc_macro: bool,
|
||||
|
@ -5,8 +5,8 @@ mod input;
|
||||
|
||||
use std::panic;
|
||||
|
||||
use ra_salsa::Durability;
|
||||
use rustc_hash::FxHashMap;
|
||||
use salsa::Durability;
|
||||
use span::EditionedFileId;
|
||||
use syntax::{ast, Parse, SourceFile, SyntaxError};
|
||||
use triomphe::Arc;
|
||||
@ -20,7 +20,7 @@ pub use crate::{
|
||||
TargetLayoutLoadResult,
|
||||
},
|
||||
};
|
||||
pub use salsa::{self, Cancelled};
|
||||
pub use ra_salsa::{self, Cancelled};
|
||||
pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, VfsPath};
|
||||
|
||||
pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
|
||||
@ -28,11 +28,11 @@ pub use semver::{BuildMetadata, Prerelease, Version, VersionReq};
|
||||
#[macro_export]
|
||||
macro_rules! impl_intern_key {
|
||||
($name:ident) => {
|
||||
impl $crate::salsa::InternKey for $name {
|
||||
fn from_intern_id(v: $crate::salsa::InternId) -> Self {
|
||||
impl $crate::ra_salsa::InternKey for $name {
|
||||
fn from_intern_id(v: $crate::ra_salsa::InternId) -> Self {
|
||||
$name(v)
|
||||
}
|
||||
fn as_intern_id(&self) -> $crate::salsa::InternId {
|
||||
fn as_intern_id(&self) -> $crate::ra_salsa::InternId {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@ -55,30 +55,30 @@ pub trait FileLoader {
|
||||
|
||||
/// Database which stores all significant input facts: source code and project
|
||||
/// model. Everything else in rust-analyzer is derived from these queries.
|
||||
#[salsa::query_group(SourceDatabaseStorage)]
|
||||
#[ra_salsa::query_group(SourceDatabaseStorage)]
|
||||
pub trait SourceDatabase: FileLoader + std::fmt::Debug {
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn compressed_file_text(&self, file_id: FileId) -> Arc<[u8]>;
|
||||
|
||||
/// Text of the file.
|
||||
#[salsa::lru]
|
||||
#[ra_salsa::lru]
|
||||
fn file_text(&self, file_id: FileId) -> Arc<str>;
|
||||
|
||||
/// Parses the file into the syntax tree.
|
||||
#[salsa::lru]
|
||||
#[ra_salsa::lru]
|
||||
fn parse(&self, file_id: EditionedFileId) -> Parse<ast::SourceFile>;
|
||||
|
||||
/// Returns the set of errors obtained from parsing the file including validation errors.
|
||||
fn parse_errors(&self, file_id: EditionedFileId) -> Option<Arc<[SyntaxError]>>;
|
||||
|
||||
/// The crate graph.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn crate_graph(&self) -> Arc<CrateGraph>;
|
||||
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn crate_workspace_data(&self) -> Arc<FxHashMap<CrateId, Arc<CrateWorkspaceData>>>;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
fn toolchain_channel(&self, krate: CrateId) -> Option<ReleaseChannel>;
|
||||
}
|
||||
|
||||
@ -126,14 +126,14 @@ fn file_text(db: &dyn SourceDatabase, file_id: FileId) -> Arc<str> {
|
||||
|
||||
/// We don't want to give HIR knowledge of source roots, hence we extract these
|
||||
/// methods into a separate DB.
|
||||
#[salsa::query_group(SourceRootDatabaseStorage)]
|
||||
#[ra_salsa::query_group(SourceRootDatabaseStorage)]
|
||||
pub trait SourceRootDatabase: SourceDatabase {
|
||||
/// Path to a file, relative to the root of its source root.
|
||||
/// Source root of the file.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn file_source_root(&self, file_id: FileId) -> SourceRootId;
|
||||
/// Contents of the source root.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
|
||||
|
||||
/// Crates whose root fool is in `id`.
|
||||
|
@ -506,14 +506,17 @@ impl ExternCrateDeclData {
|
||||
let crate_id = if name == sym::self_.clone() {
|
||||
Some(krate)
|
||||
} else {
|
||||
db.crate_def_map(krate)
|
||||
.extern_prelude()
|
||||
.find(|&(prelude_name, ..)| *prelude_name == name)
|
||||
.map(|(_, (root, _))| root.krate())
|
||||
db.crate_graph()[krate].dependencies.iter().find_map(|dep| {
|
||||
if dep.name.symbol() == name.symbol() {
|
||||
Some(dep.crate_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
Arc::new(Self {
|
||||
name: extern_crate.name.clone(),
|
||||
name,
|
||||
visibility: item_tree[extern_crate.visibility].clone(),
|
||||
alias: extern_crate.alias.clone(),
|
||||
crate_id,
|
||||
|
@ -1,5 +1,5 @@
|
||||
//! Defines database & queries for name resolution.
|
||||
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
|
||||
use base_db::{ra_salsa, CrateId, SourceDatabase, Upcast};
|
||||
use either::Either;
|
||||
use hir_expand::{db::ExpandDatabase, HirFileId, MacroDefId};
|
||||
use intern::{sym, Interned};
|
||||
@ -31,71 +31,71 @@ use crate::{
|
||||
UseId, UseLoc, VariantId,
|
||||
};
|
||||
|
||||
#[salsa::query_group(InternDatabaseStorage)]
|
||||
#[ra_salsa::query_group(InternDatabaseStorage)]
|
||||
pub trait InternDatabase: SourceDatabase {
|
||||
// region: items
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_use(&self, loc: UseLoc) -> UseId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_extern_crate(&self, loc: ExternCrateLoc) -> ExternCrateId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_function(&self, loc: FunctionLoc) -> FunctionId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_struct(&self, loc: StructLoc) -> StructId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_union(&self, loc: UnionLoc) -> UnionId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_enum(&self, loc: EnumLoc) -> EnumId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_enum_variant(&self, loc: EnumVariantLoc) -> EnumVariantId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_const(&self, loc: ConstLoc) -> ConstId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_static(&self, loc: StaticLoc) -> StaticId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_trait(&self, loc: TraitLoc) -> TraitId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_trait_alias(&self, loc: TraitAliasLoc) -> TraitAliasId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_type_alias(&self, loc: TypeAliasLoc) -> TypeAliasId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_impl(&self, loc: ImplLoc) -> ImplId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_extern_block(&self, loc: ExternBlockLoc) -> ExternBlockId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_macro2(&self, loc: Macro2Loc) -> Macro2Id;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_proc_macro(&self, loc: ProcMacroLoc) -> ProcMacroId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_macro_rules(&self, loc: MacroRulesLoc) -> MacroRulesId;
|
||||
// endregion: items
|
||||
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_block(&self, loc: BlockLoc) -> BlockId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_anonymous_const(&self, id: ConstBlockLoc) -> ConstBlockId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_in_type_const(&self, id: InTypeConstLoc) -> InTypeConstId;
|
||||
}
|
||||
|
||||
#[salsa::query_group(DefDatabaseStorage)]
|
||||
#[ra_salsa::query_group(DefDatabaseStorage)]
|
||||
pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDatabase> {
|
||||
/// Whether to expand procedural macros during name resolution.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn expand_proc_attr_macros(&self) -> bool;
|
||||
|
||||
/// Computes an [`ItemTree`] for the given file or macro expansion.
|
||||
#[salsa::invoke(ItemTree::file_item_tree_query)]
|
||||
#[ra_salsa::invoke(ItemTree::file_item_tree_query)]
|
||||
fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(ItemTree::block_item_tree_query)]
|
||||
#[ra_salsa::invoke(ItemTree::block_item_tree_query)]
|
||||
fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
|
||||
|
||||
#[salsa::invoke(DefMap::crate_def_map_query)]
|
||||
#[ra_salsa::invoke(DefMap::crate_def_map_query)]
|
||||
fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
|
||||
|
||||
/// Computes the block-level `DefMap`.
|
||||
#[salsa::invoke(DefMap::block_def_map_query)]
|
||||
#[ra_salsa::invoke(DefMap::block_def_map_query)]
|
||||
fn block_def_map(&self, block: BlockId) -> Arc<DefMap>;
|
||||
|
||||
/// Turns a MacroId into a MacroDefId, describing the macro's definition post name resolution.
|
||||
@ -103,139 +103,139 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
|
||||
|
||||
// region:data
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(StructData::struct_data_query)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(StructData::struct_data_query)]
|
||||
fn struct_data(&self, id: StructId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::struct_data_with_diagnostics_query)]
|
||||
#[ra_salsa::invoke(StructData::struct_data_with_diagnostics_query)]
|
||||
fn struct_data_with_diagnostics(&self, id: StructId) -> (Arc<StructData>, DefDiagnostics);
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(StructData::union_data_query)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(StructData::union_data_query)]
|
||||
fn union_data(&self, id: UnionId) -> Arc<StructData>;
|
||||
|
||||
#[salsa::invoke(StructData::union_data_with_diagnostics_query)]
|
||||
#[ra_salsa::invoke(StructData::union_data_with_diagnostics_query)]
|
||||
fn union_data_with_diagnostics(&self, id: UnionId) -> (Arc<StructData>, DefDiagnostics);
|
||||
|
||||
#[salsa::invoke(EnumData::enum_data_query)]
|
||||
#[ra_salsa::invoke(EnumData::enum_data_query)]
|
||||
fn enum_data(&self, e: EnumId) -> Arc<EnumData>;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(EnumVariantData::enum_variant_data_query)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(EnumVariantData::enum_variant_data_query)]
|
||||
fn enum_variant_data(&self, id: EnumVariantId) -> Arc<EnumVariantData>;
|
||||
|
||||
#[salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)]
|
||||
#[ra_salsa::invoke(EnumVariantData::enum_variant_data_with_diagnostics_query)]
|
||||
fn enum_variant_data_with_diagnostics(
|
||||
&self,
|
||||
id: EnumVariantId,
|
||||
) -> (Arc<EnumVariantData>, DefDiagnostics);
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(VariantData::variant_data)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(VariantData::variant_data)]
|
||||
fn variant_data(&self, id: VariantId) -> Arc<VariantData>;
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(ImplData::impl_data_query)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(ImplData::impl_data_query)]
|
||||
fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
|
||||
|
||||
#[salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
|
||||
#[ra_salsa::invoke(ImplData::impl_data_with_diagnostics_query)]
|
||||
fn impl_data_with_diagnostics(&self, e: ImplId) -> (Arc<ImplData>, DefDiagnostics);
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(TraitData::trait_data_query)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(TraitData::trait_data_query)]
|
||||
fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
|
||||
|
||||
#[salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
|
||||
#[ra_salsa::invoke(TraitData::trait_data_with_diagnostics_query)]
|
||||
fn trait_data_with_diagnostics(&self, tr: TraitId) -> (Arc<TraitData>, DefDiagnostics);
|
||||
|
||||
#[salsa::invoke(TraitAliasData::trait_alias_query)]
|
||||
#[ra_salsa::invoke(TraitAliasData::trait_alias_query)]
|
||||
fn trait_alias_data(&self, e: TraitAliasId) -> Arc<TraitAliasData>;
|
||||
|
||||
#[salsa::invoke(TypeAliasData::type_alias_data_query)]
|
||||
#[ra_salsa::invoke(TypeAliasData::type_alias_data_query)]
|
||||
fn type_alias_data(&self, e: TypeAliasId) -> Arc<TypeAliasData>;
|
||||
|
||||
#[salsa::invoke(FunctionData::fn_data_query)]
|
||||
#[ra_salsa::invoke(FunctionData::fn_data_query)]
|
||||
fn function_data(&self, func: FunctionId) -> Arc<FunctionData>;
|
||||
|
||||
#[salsa::invoke(ConstData::const_data_query)]
|
||||
#[ra_salsa::invoke(ConstData::const_data_query)]
|
||||
fn const_data(&self, konst: ConstId) -> Arc<ConstData>;
|
||||
|
||||
#[salsa::invoke(StaticData::static_data_query)]
|
||||
#[ra_salsa::invoke(StaticData::static_data_query)]
|
||||
fn static_data(&self, statik: StaticId) -> Arc<StaticData>;
|
||||
|
||||
#[salsa::invoke(Macro2Data::macro2_data_query)]
|
||||
#[ra_salsa::invoke(Macro2Data::macro2_data_query)]
|
||||
fn macro2_data(&self, makro: Macro2Id) -> Arc<Macro2Data>;
|
||||
|
||||
#[salsa::invoke(MacroRulesData::macro_rules_data_query)]
|
||||
#[ra_salsa::invoke(MacroRulesData::macro_rules_data_query)]
|
||||
fn macro_rules_data(&self, makro: MacroRulesId) -> Arc<MacroRulesData>;
|
||||
|
||||
#[salsa::invoke(ProcMacroData::proc_macro_data_query)]
|
||||
#[ra_salsa::invoke(ProcMacroData::proc_macro_data_query)]
|
||||
fn proc_macro_data(&self, makro: ProcMacroId) -> Arc<ProcMacroData>;
|
||||
|
||||
#[salsa::invoke(ExternCrateDeclData::extern_crate_decl_data_query)]
|
||||
#[ra_salsa::invoke(ExternCrateDeclData::extern_crate_decl_data_query)]
|
||||
fn extern_crate_decl_data(&self, extern_crate: ExternCrateId) -> Arc<ExternCrateDeclData>;
|
||||
|
||||
// endregion:data
|
||||
|
||||
#[salsa::invoke(Body::body_with_source_map_query)]
|
||||
#[salsa::lru]
|
||||
#[ra_salsa::invoke(Body::body_with_source_map_query)]
|
||||
#[ra_salsa::lru]
|
||||
fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
|
||||
|
||||
#[salsa::invoke(Body::body_query)]
|
||||
#[ra_salsa::invoke(Body::body_query)]
|
||||
fn body(&self, def: DefWithBodyId) -> Arc<Body>;
|
||||
|
||||
#[salsa::invoke(ExprScopes::expr_scopes_query)]
|
||||
#[ra_salsa::invoke(ExprScopes::expr_scopes_query)]
|
||||
fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
|
||||
|
||||
#[salsa::invoke(GenericParams::generic_params_query)]
|
||||
#[ra_salsa::invoke(GenericParams::generic_params_query)]
|
||||
fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>;
|
||||
|
||||
// region:attrs
|
||||
|
||||
#[salsa::invoke(Attrs::fields_attrs_query)]
|
||||
#[ra_salsa::invoke(Attrs::fields_attrs_query)]
|
||||
fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>;
|
||||
|
||||
// should this really be a query?
|
||||
#[salsa::invoke(crate::attr::fields_attrs_source_map)]
|
||||
#[ra_salsa::invoke(crate::attr::fields_attrs_source_map)]
|
||||
fn fields_attrs_source_map(
|
||||
&self,
|
||||
def: VariantId,
|
||||
) -> Arc<ArenaMap<LocalFieldId, AstPtr<Either<ast::TupleField, ast::RecordField>>>>;
|
||||
|
||||
#[salsa::invoke(AttrsWithOwner::attrs_query)]
|
||||
#[ra_salsa::invoke(AttrsWithOwner::attrs_query)]
|
||||
fn attrs(&self, def: AttrDefId) -> Attrs;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(lang_item::lang_attr)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(lang_item::lang_attr)]
|
||||
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
|
||||
|
||||
// endregion:attrs
|
||||
|
||||
#[salsa::invoke(LangItems::lang_item_query)]
|
||||
#[ra_salsa::invoke(LangItems::lang_item_query)]
|
||||
fn lang_item(&self, start_crate: CrateId, item: LangItem) -> Option<LangItemTarget>;
|
||||
|
||||
#[salsa::invoke(ImportMap::import_map_query)]
|
||||
#[ra_salsa::invoke(ImportMap::import_map_query)]
|
||||
fn import_map(&self, krate: CrateId) -> Arc<ImportMap>;
|
||||
|
||||
// region:visibilities
|
||||
|
||||
#[salsa::invoke(visibility::field_visibilities_query)]
|
||||
#[ra_salsa::invoke(visibility::field_visibilities_query)]
|
||||
fn field_visibilities(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Visibility>>;
|
||||
|
||||
// FIXME: unify function_visibility and const_visibility?
|
||||
#[salsa::invoke(visibility::function_visibility_query)]
|
||||
#[ra_salsa::invoke(visibility::function_visibility_query)]
|
||||
fn function_visibility(&self, def: FunctionId) -> Visibility;
|
||||
|
||||
#[salsa::invoke(visibility::const_visibility_query)]
|
||||
#[ra_salsa::invoke(visibility::const_visibility_query)]
|
||||
fn const_visibility(&self, def: ConstId) -> Visibility;
|
||||
|
||||
// endregion:visibilities
|
||||
|
||||
#[salsa::invoke(LangItems::crate_lang_items_query)]
|
||||
#[ra_salsa::invoke(LangItems::crate_lang_items_query)]
|
||||
fn crate_lang_items(&self, krate: CrateId) -> Option<Arc<LangItems>>;
|
||||
|
||||
#[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
|
||||
#[ra_salsa::invoke(crate::lang_item::notable_traits_in_deps)]
|
||||
fn notable_traits_in_deps(&self, krate: CrateId) -> Arc<[Arc<[TraitId]>]>;
|
||||
#[salsa::invoke(crate::lang_item::crate_notable_traits)]
|
||||
#[ra_salsa::invoke(crate::lang_item::crate_notable_traits)]
|
||||
fn crate_notable_traits(&self, krate: CrateId) -> Option<Arc<[TraitId]>>;
|
||||
|
||||
fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
|
||||
|
@ -71,7 +71,7 @@ use std::{
|
||||
|
||||
use base_db::{
|
||||
impl_intern_key,
|
||||
salsa::{self, InternValueTrivial},
|
||||
ra_salsa::{self, InternValueTrivial},
|
||||
CrateId,
|
||||
};
|
||||
use hir_expand::{
|
||||
@ -206,85 +206,85 @@ macro_rules! impl_loc {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct FunctionId(salsa::InternId);
|
||||
pub struct FunctionId(ra_salsa::InternId);
|
||||
type FunctionLoc = AssocItemLoc<Function>;
|
||||
impl_intern!(FunctionId, FunctionLoc, intern_function, lookup_intern_function);
|
||||
impl_loc!(FunctionLoc, id: Function, container: ItemContainerId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct StructId(salsa::InternId);
|
||||
pub struct StructId(ra_salsa::InternId);
|
||||
type StructLoc = ItemLoc<Struct>;
|
||||
impl_intern!(StructId, StructLoc, intern_struct, lookup_intern_struct);
|
||||
impl_loc!(StructLoc, id: Struct, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct UnionId(salsa::InternId);
|
||||
pub struct UnionId(ra_salsa::InternId);
|
||||
pub type UnionLoc = ItemLoc<Union>;
|
||||
impl_intern!(UnionId, UnionLoc, intern_union, lookup_intern_union);
|
||||
impl_loc!(UnionLoc, id: Union, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct EnumId(salsa::InternId);
|
||||
pub struct EnumId(ra_salsa::InternId);
|
||||
pub type EnumLoc = ItemLoc<Enum>;
|
||||
impl_intern!(EnumId, EnumLoc, intern_enum, lookup_intern_enum);
|
||||
impl_loc!(EnumLoc, id: Enum, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ConstId(salsa::InternId);
|
||||
pub struct ConstId(ra_salsa::InternId);
|
||||
type ConstLoc = AssocItemLoc<Const>;
|
||||
impl_intern!(ConstId, ConstLoc, intern_const, lookup_intern_const);
|
||||
impl_loc!(ConstLoc, id: Const, container: ItemContainerId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct StaticId(salsa::InternId);
|
||||
pub struct StaticId(ra_salsa::InternId);
|
||||
pub type StaticLoc = AssocItemLoc<Static>;
|
||||
impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
|
||||
impl_loc!(StaticLoc, id: Static, container: ItemContainerId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||
pub struct TraitId(salsa::InternId);
|
||||
pub struct TraitId(ra_salsa::InternId);
|
||||
pub type TraitLoc = ItemLoc<Trait>;
|
||||
impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
|
||||
impl_loc!(TraitLoc, id: Trait, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TraitAliasId(salsa::InternId);
|
||||
pub struct TraitAliasId(ra_salsa::InternId);
|
||||
pub type TraitAliasLoc = ItemLoc<TraitAlias>;
|
||||
impl_intern!(TraitAliasId, TraitAliasLoc, intern_trait_alias, lookup_intern_trait_alias);
|
||||
impl_loc!(TraitAliasLoc, id: TraitAlias, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct TypeAliasId(salsa::InternId);
|
||||
pub struct TypeAliasId(ra_salsa::InternId);
|
||||
type TypeAliasLoc = AssocItemLoc<TypeAlias>;
|
||||
impl_intern!(TypeAliasId, TypeAliasLoc, intern_type_alias, lookup_intern_type_alias);
|
||||
impl_loc!(TypeAliasLoc, id: TypeAlias, container: ItemContainerId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ImplId(salsa::InternId);
|
||||
pub struct ImplId(ra_salsa::InternId);
|
||||
type ImplLoc = ItemLoc<Impl>;
|
||||
impl_intern!(ImplId, ImplLoc, intern_impl, lookup_intern_impl);
|
||||
impl_loc!(ImplLoc, id: Impl, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct UseId(salsa::InternId);
|
||||
pub struct UseId(ra_salsa::InternId);
|
||||
type UseLoc = ItemLoc<Use>;
|
||||
impl_intern!(UseId, UseLoc, intern_use, lookup_intern_use);
|
||||
impl_loc!(UseLoc, id: Use, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ExternCrateId(salsa::InternId);
|
||||
pub struct ExternCrateId(ra_salsa::InternId);
|
||||
type ExternCrateLoc = ItemLoc<ExternCrate>;
|
||||
impl_intern!(ExternCrateId, ExternCrateLoc, intern_extern_crate, lookup_intern_extern_crate);
|
||||
impl_loc!(ExternCrateLoc, id: ExternCrate, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ExternBlockId(salsa::InternId);
|
||||
pub struct ExternBlockId(ra_salsa::InternId);
|
||||
type ExternBlockLoc = ItemLoc<ExternBlock>;
|
||||
impl_intern!(ExternBlockId, ExternBlockLoc, intern_extern_block, lookup_intern_extern_block);
|
||||
impl_loc!(ExternBlockLoc, id: ExternBlock, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct EnumVariantId(salsa::InternId);
|
||||
pub struct EnumVariantId(ra_salsa::InternId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct EnumVariantLoc {
|
||||
@ -296,7 +296,7 @@ impl_intern!(EnumVariantId, EnumVariantLoc, intern_enum_variant, lookup_intern_e
|
||||
impl_loc!(EnumVariantLoc, id: Variant, parent: EnumId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct Macro2Id(salsa::InternId);
|
||||
pub struct Macro2Id(ra_salsa::InternId);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Macro2Loc {
|
||||
pub container: ModuleId,
|
||||
@ -309,7 +309,7 @@ impl_intern!(Macro2Id, Macro2Loc, intern_macro2, lookup_intern_macro2);
|
||||
impl_loc!(Macro2Loc, id: Macro2, container: ModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct MacroRulesId(salsa::InternId);
|
||||
pub struct MacroRulesId(ra_salsa::InternId);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct MacroRulesLoc {
|
||||
pub container: ModuleId,
|
||||
@ -338,7 +338,7 @@ pub enum MacroExpander {
|
||||
BuiltInEager(EagerExpander),
|
||||
}
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct ProcMacroId(salsa::InternId);
|
||||
pub struct ProcMacroId(ra_salsa::InternId);
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct ProcMacroLoc {
|
||||
pub container: CrateRootModuleId,
|
||||
@ -351,7 +351,7 @@ impl_intern!(ProcMacroId, ProcMacroLoc, intern_proc_macro, lookup_intern_proc_ma
|
||||
impl_loc!(ProcMacroLoc, id: Function, container: CrateRootModuleId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct BlockId(salsa::InternId);
|
||||
pub struct BlockId(ra_salsa::InternId);
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
||||
pub struct BlockLoc {
|
||||
ast_id: AstId<ast::BlockExpr>,
|
||||
@ -363,7 +363,7 @@ impl_intern!(BlockId, BlockLoc, intern_block, lookup_intern_block);
|
||||
/// Id of the anonymous const block expression and patterns. This is very similar to `ClosureId` and
|
||||
/// shouldn't be a `DefWithBodyId` since its type inference is dependent on its parent.
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct ConstBlockId(salsa::InternId);
|
||||
pub struct ConstBlockId(ra_salsa::InternId);
|
||||
impl_intern!(ConstBlockId, ConstBlockLoc, intern_anonymous_const, lookup_intern_anonymous_const);
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
||||
@ -803,7 +803,7 @@ impl Clone for Box<dyn OpaqueInternableThing> {
|
||||
/// length (like `[u8; 2 + 2]`). These constants are body owner and are a variant of `DefWithBodyId`. These
|
||||
/// are not called `AnonymousConstId` to prevent confusion with [`ConstBlockId`].
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct InTypeConstId(salsa::InternId);
|
||||
pub struct InTypeConstId(ra_salsa::InternId);
|
||||
impl_intern!(InTypeConstId, InTypeConstLoc, intern_in_type_const, lookup_intern_in_type_const);
|
||||
|
||||
// We would like to set `derive(PartialEq)`
|
||||
|
@ -30,8 +30,8 @@ use crate::{
|
||||
db::DefDatabase,
|
||||
item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
|
||||
item_tree::{
|
||||
self, AttrOwner, ExternCrate, FieldsShape, FileItemTreeId, ImportKind, ItemTree,
|
||||
ItemTreeId, ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
self, AttrOwner, FieldsShape, FileItemTreeId, ImportKind, ItemTree, ItemTreeId,
|
||||
ItemTreeNode, Macro2, MacroCall, MacroRules, Mod, ModItem, ModKind, TreeId,
|
||||
},
|
||||
macro_call_as_call_id, macro_call_as_call_id_with_eager,
|
||||
nameres::{
|
||||
@ -93,6 +93,7 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
|
||||
proc_macros,
|
||||
from_glob_import: Default::default(),
|
||||
skip_attrs: Default::default(),
|
||||
unresolved_extern_crates: Default::default(),
|
||||
is_proc_macro: krate.is_proc_macro,
|
||||
};
|
||||
if tree_id.is_block() {
|
||||
@ -126,9 +127,11 @@ impl PartialResolvedImport {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
enum ImportSource {
|
||||
Use { use_tree: Idx<ast::UseTree>, id: UseId, is_prelude: bool, kind: ImportKind },
|
||||
ExternCrate { id: ExternCrateId },
|
||||
struct ImportSource {
|
||||
use_tree: Idx<ast::UseTree>,
|
||||
id: UseId,
|
||||
is_prelude: bool,
|
||||
kind: ImportKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@ -154,25 +157,10 @@ impl Import {
|
||||
path,
|
||||
alias,
|
||||
visibility: visibility.clone(),
|
||||
source: ImportSource::Use { use_tree: idx, id, is_prelude, kind },
|
||||
source: ImportSource { use_tree: idx, id, is_prelude, kind },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
fn from_extern_crate(
|
||||
tree: &ItemTree,
|
||||
item_tree_id: ItemTreeId<item_tree::ExternCrate>,
|
||||
id: ExternCrateId,
|
||||
) -> Self {
|
||||
let it = &tree[item_tree_id.value];
|
||||
let visibility = &tree[it.visibility];
|
||||
Self {
|
||||
path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
|
||||
alias: it.alias.clone(),
|
||||
visibility: visibility.clone(),
|
||||
source: ImportSource::ExternCrate { id },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@ -218,11 +206,16 @@ enum MacroDirectiveKind {
|
||||
struct DefCollector<'a> {
|
||||
db: &'a dyn DefDatabase,
|
||||
def_map: DefMap,
|
||||
// The dependencies of the current crate, including optional deps like `test`.
|
||||
deps: FxHashMap<Name, Dependency>,
|
||||
glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, UseId)>>,
|
||||
unresolved_imports: Vec<ImportDirective>,
|
||||
indeterminate_imports: Vec<(ImportDirective, PerNs)>,
|
||||
unresolved_macros: Vec<MacroDirective>,
|
||||
// We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
|
||||
// resolve. When we emit diagnostics for unresolved imports, we only do so if the import
|
||||
// doesn't start with an unresolved crate's name.
|
||||
unresolved_extern_crates: FxHashSet<Name>,
|
||||
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
|
||||
cfg_options: &'a CfgOptions,
|
||||
/// List of procedural macros defined by this crate. This is read from the dynamic library
|
||||
@ -310,6 +303,7 @@ impl DefCollector<'_> {
|
||||
}
|
||||
|
||||
for (name, dep) in &self.deps {
|
||||
// Add all
|
||||
if dep.is_prelude() {
|
||||
// This is a bit confusing but the gist is that `no_core` and `no_std` remove the
|
||||
// sysroot dependence on `core` and `std` respectively. Our `CrateGraph` is eagerly
|
||||
@ -329,6 +323,7 @@ impl DefCollector<'_> {
|
||||
if skip {
|
||||
continue;
|
||||
}
|
||||
|
||||
crate_data
|
||||
.extern_prelude
|
||||
.insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
|
||||
@ -788,25 +783,6 @@ impl DefCollector<'_> {
|
||||
let _p = tracing::info_span!("resolve_import", import_path = %import.path.display(self.db.upcast(), Edition::LATEST))
|
||||
.entered();
|
||||
tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
|
||||
match import.source {
|
||||
ImportSource::ExternCrate { .. } => {
|
||||
let name = import
|
||||
.path
|
||||
.as_ident()
|
||||
.expect("extern crate should have been desugared to one-element path");
|
||||
|
||||
let res = self.resolve_extern_crate(name);
|
||||
|
||||
match res {
|
||||
Some(res) => PartialResolvedImport::Resolved(PerNs::types(
|
||||
res.into(),
|
||||
Visibility::Public,
|
||||
None,
|
||||
)),
|
||||
None => PartialResolvedImport::Unresolved,
|
||||
}
|
||||
}
|
||||
ImportSource::Use { .. } => {
|
||||
let res = self.def_map.resolve_path_fp_with_macro(
|
||||
self.db,
|
||||
ResolveMode::Import,
|
||||
@ -834,17 +810,6 @@ impl DefCollector<'_> {
|
||||
PartialResolvedImport::Indeterminate(def)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_extern_crate(&self, name: &Name) -> Option<CrateRootModuleId> {
|
||||
if *name == sym::self_.clone() {
|
||||
cov_mark::hit!(extern_crate_self_as);
|
||||
Some(self.def_map.crate_root())
|
||||
} else {
|
||||
self.deps.get(name).map(|dep| CrateRootModuleId { krate: dep.crate_id })
|
||||
}
|
||||
}
|
||||
|
||||
fn record_resolved_import(&mut self, directive: &ImportDirective) {
|
||||
let _p = tracing::info_span!("record_resolved_import").entered();
|
||||
@ -858,8 +823,12 @@ impl DefCollector<'_> {
|
||||
.unwrap_or(Visibility::Public);
|
||||
|
||||
match import.source {
|
||||
ImportSource::ExternCrate { .. }
|
||||
| ImportSource::Use { kind: ImportKind::Plain | ImportKind::TypeOnly, .. } => {
|
||||
ImportSource {
|
||||
kind: kind @ (ImportKind::Plain | ImportKind::TypeOnly),
|
||||
id,
|
||||
use_tree,
|
||||
..
|
||||
} => {
|
||||
let name = match &import.alias {
|
||||
Some(ImportAlias::Alias(name)) => Some(name),
|
||||
Some(ImportAlias::Underscore) => None,
|
||||
@ -872,40 +841,20 @@ impl DefCollector<'_> {
|
||||
},
|
||||
};
|
||||
|
||||
let imp = match import.source {
|
||||
// extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
|
||||
ImportSource::ExternCrate { id, .. } => {
|
||||
if self.def_map.block.is_none() && module_id == DefMap::ROOT {
|
||||
if let (Some(ModuleDefId::ModuleId(def)), Some(name)) =
|
||||
(def.take_types(), name)
|
||||
{
|
||||
if let Ok(def) = def.try_into() {
|
||||
Arc::get_mut(&mut self.def_map.data)
|
||||
.unwrap()
|
||||
.extern_prelude
|
||||
.insert(name.clone(), (def, Some(id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
ImportType::ExternCrate(id)
|
||||
}
|
||||
ImportSource::Use { kind, id, use_tree, .. } => {
|
||||
if kind == ImportKind::TypeOnly {
|
||||
def.values = None;
|
||||
def.macros = None;
|
||||
}
|
||||
ImportType::Import(ImportId { import: id, idx: use_tree })
|
||||
}
|
||||
};
|
||||
let imp = ImportType::Import(ImportId { import: id, idx: use_tree });
|
||||
tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
|
||||
|
||||
self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
|
||||
}
|
||||
ImportSource::Use { kind: ImportKind::Glob, id, .. } => {
|
||||
ImportSource { kind: ImportKind::Glob, id, is_prelude, .. } => {
|
||||
tracing::debug!("glob import: {:?}", import);
|
||||
match def.take_types() {
|
||||
Some(ModuleDefId::ModuleId(m)) => {
|
||||
if let ImportSource::Use { id, is_prelude: true, .. } = import.source {
|
||||
if is_prelude {
|
||||
// Note: This dodgily overrides the injected prelude. The rustc
|
||||
// implementation seems to work the same though.
|
||||
cov_mark::hit!(std_prelude);
|
||||
@ -1323,7 +1272,7 @@ impl DefCollector<'_> {
|
||||
_ => return Resolved::No,
|
||||
};
|
||||
|
||||
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
|
||||
// Skip #[test]/#[bench]/#[test_case] expansion, which would merely result in more memory usage
|
||||
// due to duplicating functions into macro expansions, but only if `cfg(test)` is active,
|
||||
// otherwise they are expanded to nothing and this can impact e.g. diagnostics (due to things
|
||||
// being cfg'ed out).
|
||||
@ -1332,7 +1281,7 @@ impl DefCollector<'_> {
|
||||
if matches!(
|
||||
def.kind,
|
||||
MacroDefKind::BuiltInAttr(_, expander)
|
||||
if expander.is_test() || expander.is_bench()
|
||||
if expander.is_test() || expander.is_bench() || expander.is_test_case()
|
||||
) {
|
||||
let test_is_active =
|
||||
self.cfg_options.check_atom(&CfgAtom::Flag(sym::test.clone()));
|
||||
@ -1560,46 +1509,30 @@ impl DefCollector<'_> {
|
||||
}
|
||||
|
||||
// Emit diagnostics for all remaining unresolved imports.
|
||||
|
||||
// We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
|
||||
// resolve. We first emit diagnostics for unresolved extern crates and collect the missing
|
||||
// crate names. Then we emit diagnostics for unresolved imports, but only if the import
|
||||
// doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
|
||||
// heuristic, but it works in practice.
|
||||
let mut diagnosed_extern_crates = FxHashSet::default();
|
||||
for directive in &self.unresolved_imports {
|
||||
if let ImportSource::ExternCrate { id } = directive.import.source {
|
||||
let item_tree_id = id.lookup(self.db).id;
|
||||
let item_tree = item_tree_id.item_tree(self.db);
|
||||
let extern_crate = &item_tree[item_tree_id.value];
|
||||
|
||||
diagnosed_extern_crates.insert(extern_crate.name.clone());
|
||||
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
|
||||
directive.module_id,
|
||||
InFile::new(item_tree_id.file_id(), extern_crate.ast_id),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
for directive in &self.unresolved_imports {
|
||||
if let ImportSource::Use { use_tree, id, is_prelude: _, kind: _ } =
|
||||
directive.import.source
|
||||
{
|
||||
for import in &self.unresolved_imports {
|
||||
let &ImportDirective {
|
||||
module_id,
|
||||
import:
|
||||
Import {
|
||||
ref path,
|
||||
source: ImportSource { use_tree, id, is_prelude: _, kind: _ },
|
||||
..
|
||||
},
|
||||
..
|
||||
} = import;
|
||||
if matches!(
|
||||
(directive.import.path.segments().first(), &directive.import.path.kind),
|
||||
(Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
|
||||
(path.segments().first(), &path.kind),
|
||||
(Some(krate), PathKind::Plain | PathKind::Abs) if self.unresolved_extern_crates.contains(krate)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
let item_tree_id = id.lookup(self.db).id;
|
||||
self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
|
||||
directive.module_id,
|
||||
module_id,
|
||||
item_tree_id,
|
||||
use_tree,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
self.def_map
|
||||
}
|
||||
@ -1623,7 +1556,8 @@ impl ModCollector<'_, '_> {
|
||||
|
||||
fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
|
||||
let krate = self.def_collector.def_map.krate;
|
||||
let is_crate_root = self.module_id == DefMap::ROOT;
|
||||
let is_crate_root =
|
||||
self.module_id == DefMap::ROOT && self.def_collector.def_map.block.is_none();
|
||||
|
||||
// Note: don't assert that inserted value is fresh: it's simply not true
|
||||
// for macros.
|
||||
@ -1632,10 +1566,7 @@ impl ModCollector<'_, '_> {
|
||||
// Prelude module is always considered to be `#[macro_use]`.
|
||||
if let Some((prelude_module, _use)) = self.def_collector.def_map.prelude {
|
||||
// Don't insert macros from the prelude into blocks, as they can be shadowed by other macros.
|
||||
if prelude_module.krate != krate
|
||||
&& is_crate_root
|
||||
&& self.def_collector.def_map.block.is_none()
|
||||
{
|
||||
if prelude_module.krate != krate && is_crate_root {
|
||||
cov_mark::hit!(prelude_is_macro_use);
|
||||
self.def_collector.import_macros_from_extern_crate(
|
||||
prelude_module.krate,
|
||||
@ -1709,26 +1640,73 @@ impl ModCollector<'_, '_> {
|
||||
id: ItemTreeId::new(self.tree_id, item_tree_id),
|
||||
}
|
||||
.intern(db);
|
||||
def_map.modules[self.module_id].scope.define_extern_crate_decl(id);
|
||||
|
||||
let item_tree::ExternCrate { name, visibility, alias, ast_id } =
|
||||
&self.item_tree[item_tree_id];
|
||||
|
||||
let is_self = *name == sym::self_;
|
||||
let resolved = if is_self {
|
||||
cov_mark::hit!(extern_crate_self_as);
|
||||
Some(def_map.crate_root())
|
||||
} else {
|
||||
self.def_collector
|
||||
.deps
|
||||
.get(name)
|
||||
.map(|dep| CrateRootModuleId { krate: dep.crate_id })
|
||||
};
|
||||
|
||||
let name = match alias {
|
||||
Some(ImportAlias::Alias(name)) => Some(name),
|
||||
Some(ImportAlias::Underscore) => None,
|
||||
None => Some(name),
|
||||
};
|
||||
|
||||
if let Some(resolved) = resolved {
|
||||
let vis = resolve_vis(def_map, &self.item_tree[*visibility]);
|
||||
|
||||
if is_crate_root {
|
||||
// extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
|
||||
if let Some(name) = name {
|
||||
Arc::get_mut(&mut def_map.data)
|
||||
.unwrap()
|
||||
.extern_prelude
|
||||
.insert(name.clone(), (resolved, Some(id)));
|
||||
}
|
||||
// they also allow `#[macro_use]`
|
||||
if !is_self {
|
||||
self.process_macro_use_extern_crate(
|
||||
item_tree_id,
|
||||
id,
|
||||
attrs.by_key(&sym::macro_use).attrs(),
|
||||
resolved.krate,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.def_collector.def_map.modules[self.module_id]
|
||||
.scope
|
||||
.define_extern_crate_decl(id);
|
||||
self.def_collector.unresolved_imports.push(ImportDirective {
|
||||
module_id: self.module_id,
|
||||
import: Import::from_extern_crate(
|
||||
self.item_tree,
|
||||
ItemTreeId::new(self.tree_id, item_tree_id),
|
||||
id,
|
||||
self.def_collector.update(
|
||||
module_id,
|
||||
&[(
|
||||
name.cloned(),
|
||||
PerNs::types(
|
||||
resolved.into(),
|
||||
vis,
|
||||
Some(ImportOrExternCrate::ExternCrate(id)),
|
||||
),
|
||||
status: PartialResolvedImport::Unresolved,
|
||||
})
|
||||
)],
|
||||
vis,
|
||||
Some(ImportType::ExternCrate(id)),
|
||||
);
|
||||
} else {
|
||||
if let Some(name) = name {
|
||||
self.def_collector.unresolved_extern_crates.insert(name.clone());
|
||||
}
|
||||
self.def_collector.def_map.diagnostics.push(
|
||||
DefDiagnostic::unresolved_extern_crate(
|
||||
module_id,
|
||||
InFile::new(self.file_id(), *ast_id),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
ModItem::ExternBlock(block) => self.collect(
|
||||
&self.item_tree[block].children,
|
||||
@ -1939,27 +1917,15 @@ impl ModCollector<'_, '_> {
|
||||
|
||||
fn process_macro_use_extern_crate<'a>(
|
||||
&mut self,
|
||||
extern_crate: FileItemTreeId<ExternCrate>,
|
||||
extern_crate_id: ExternCrateId,
|
||||
macro_use_attrs: impl Iterator<Item = &'a Attr>,
|
||||
target_crate: CrateId,
|
||||
) {
|
||||
let db = self.def_collector.db;
|
||||
|
||||
let target_crate =
|
||||
match self.def_collector.resolve_extern_crate(&self.item_tree[extern_crate].name) {
|
||||
Some(m) if m.krate == self.def_collector.def_map.krate => {
|
||||
cov_mark::hit!(ignore_macro_use_extern_crate_self);
|
||||
return;
|
||||
}
|
||||
Some(m) => m.krate,
|
||||
None => return,
|
||||
};
|
||||
|
||||
cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
|
||||
|
||||
let mut single_imports = Vec::new();
|
||||
for attr in macro_use_attrs {
|
||||
let Some(paths) = attr.parse_path_comma_token_tree(db.upcast()) else {
|
||||
let Some(paths) = attr.parse_path_comma_token_tree(self.def_collector.db.upcast())
|
||||
else {
|
||||
// `#[macro_use]` (without any paths) found, forget collected names and just import
|
||||
// all visible macros.
|
||||
self.def_collector.import_macros_from_extern_crate(
|
||||
@ -2523,6 +2489,7 @@ mod tests {
|
||||
from_glob_import: Default::default(),
|
||||
skip_attrs: Default::default(),
|
||||
is_proc_macro: false,
|
||||
unresolved_extern_crates: Default::default(),
|
||||
};
|
||||
collector.seed_with_top_level();
|
||||
collector.collect();
|
||||
|
@ -416,7 +416,6 @@ pub struct Arc;
|
||||
|
||||
#[test]
|
||||
fn macro_use_extern_crate_self() {
|
||||
cov_mark::check!(ignore_macro_use_extern_crate_self);
|
||||
check(
|
||||
r#"
|
||||
//- /main.rs crate:main
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::{fmt, panic, sync::Mutex};
|
||||
|
||||
use base_db::{
|
||||
salsa::{self, Durability},
|
||||
ra_salsa::{self, Durability},
|
||||
AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
|
||||
};
|
||||
use hir_expand::{db::ExpandDatabase, files::FilePosition, InFile};
|
||||
@ -18,7 +18,7 @@ use crate::{
|
||||
LocalModuleId, Lookup, ModuleDefId, ModuleId,
|
||||
};
|
||||
|
||||
#[salsa::database(
|
||||
#[ra_salsa::database(
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir_expand::db::ExpandDatabaseStorage,
|
||||
@ -26,8 +26,8 @@ use crate::{
|
||||
crate::db::DefDatabaseStorage
|
||||
)]
|
||||
pub(crate) struct TestDB {
|
||||
storage: salsa::Storage<TestDB>,
|
||||
events: Mutex<Option<Vec<salsa::Event>>>,
|
||||
storage: ra_salsa::Storage<TestDB>,
|
||||
events: Mutex<Option<Vec<ra_salsa::Event>>>,
|
||||
}
|
||||
|
||||
impl Default for TestDB {
|
||||
@ -51,8 +51,8 @@ impl Upcast<dyn DefDatabase> for TestDB {
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::Database for TestDB {
|
||||
fn salsa_event(&self, event: salsa::Event) {
|
||||
impl ra_salsa::Database for TestDB {
|
||||
fn salsa_event(&self, event: ra_salsa::Event) {
|
||||
let mut events = self.events.lock().unwrap();
|
||||
if let Some(events) = &mut *events {
|
||||
events.push(event);
|
||||
@ -215,7 +215,7 @@ impl TestDB {
|
||||
None
|
||||
}
|
||||
|
||||
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
|
||||
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<ra_salsa::Event> {
|
||||
*self.events.lock().unwrap() = Some(Vec::new());
|
||||
f();
|
||||
self.events.lock().unwrap().take().unwrap()
|
||||
@ -228,7 +228,7 @@ impl TestDB {
|
||||
.filter_map(|e| match e.kind {
|
||||
// This is pretty horrible, but `Debug` is the only way to inspect
|
||||
// QueryDescriptor at the moment.
|
||||
salsa::EventKind::WillExecute { database_key } => {
|
||||
ra_salsa::EventKind::WillExecute { database_key } => {
|
||||
Some(format!("{:?}", database_key.debug(self)))
|
||||
}
|
||||
_ => None,
|
||||
|
@ -51,6 +51,9 @@ impl BuiltinAttrExpander {
|
||||
pub fn is_bench(self) -> bool {
|
||||
matches!(self, BuiltinAttrExpander::Bench)
|
||||
}
|
||||
pub fn is_test_case(self) -> bool {
|
||||
matches!(self, BuiltinAttrExpander::TestCase)
|
||||
}
|
||||
}
|
||||
|
||||
register_builtin! {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Defines a unit of change that can applied to the database to get the next
|
||||
//! state. Changes are transactional.
|
||||
use base_db::{
|
||||
salsa::Durability, CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot,
|
||||
ra_salsa::Durability, CrateGraph, CrateId, CrateWorkspaceData, FileChange, SourceRoot,
|
||||
SourceRootDatabase,
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Defines database & queries for macro expansion.
|
||||
|
||||
use base_db::{salsa, CrateId, SourceDatabase};
|
||||
use base_db::{ra_salsa, CrateId, SourceDatabase};
|
||||
use either::Either;
|
||||
use limit::Limit;
|
||||
use mbe::MatchedArmIndex;
|
||||
@ -53,32 +53,32 @@ pub enum TokenExpander {
|
||||
ProcMacro(CustomProcMacroExpander),
|
||||
}
|
||||
|
||||
#[salsa::query_group(ExpandDatabaseStorage)]
|
||||
#[ra_salsa::query_group(ExpandDatabaseStorage)]
|
||||
pub trait ExpandDatabase: SourceDatabase {
|
||||
/// The proc macros.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn proc_macros(&self) -> Arc<ProcMacros>;
|
||||
|
||||
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
|
||||
|
||||
/// Main public API -- parses a hir file, not caring whether it's a real
|
||||
/// file or a macro expansion.
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode;
|
||||
/// Implementation for the macro case.
|
||||
#[salsa::lru]
|
||||
#[ra_salsa::lru]
|
||||
fn parse_macro_expansion(
|
||||
&self,
|
||||
macro_file: MacroFileId,
|
||||
) -> ExpandResult<(Parse<SyntaxNode>, Arc<ExpansionSpanMap>)>;
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(SpanMap::new)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(SpanMap::new)]
|
||||
fn span_map(&self, file_id: HirFileId) -> SpanMap;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(crate::span_map::expansion_span_map)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(crate::span_map::expansion_span_map)]
|
||||
fn expansion_span_map(&self, file_id: MacroFileId) -> Arc<ExpansionSpanMap>;
|
||||
#[salsa::invoke(crate::span_map::real_span_map)]
|
||||
#[ra_salsa::invoke(crate::span_map::real_span_map)]
|
||||
fn real_span_map(&self, file_id: EditionedFileId) -> Arc<RealSpanMap>;
|
||||
|
||||
/// Macro ids. That's probably the tricksiest bit in rust-analyzer, and the
|
||||
@ -86,15 +86,15 @@ pub trait ExpandDatabase: SourceDatabase {
|
||||
///
|
||||
/// We encode macro definitions into ids of macro calls, this what allows us
|
||||
/// to be incremental.
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_macro_call(&self, macro_call: MacroCallLoc) -> MacroCallId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_syntax_context(&self, ctx: SyntaxContextData) -> SyntaxContextId;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
fn setup_syntax_context_root(&self) -> ();
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(crate::hygiene::dump_syntax_contexts)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(crate::hygiene::dump_syntax_contexts)]
|
||||
fn dump_syntax_contexts(&self) -> String;
|
||||
|
||||
/// Lowers syntactic macro call to a token tree representation. That's a firewall
|
||||
@ -102,18 +102,18 @@ pub trait ExpandDatabase: SourceDatabase {
|
||||
/// subtree.
|
||||
#[deprecated = "calling this is incorrect, call `macro_arg_considering_derives` instead"]
|
||||
fn macro_arg(&self, id: MacroCallId) -> MacroArgResult;
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
fn macro_arg_considering_derives(
|
||||
&self,
|
||||
id: MacroCallId,
|
||||
kind: &MacroCallKind,
|
||||
) -> MacroArgResult;
|
||||
/// Fetches the expander for this macro.
|
||||
#[salsa::transparent]
|
||||
#[salsa::invoke(TokenExpander::macro_expander)]
|
||||
#[ra_salsa::transparent]
|
||||
#[ra_salsa::invoke(TokenExpander::macro_expander)]
|
||||
fn macro_expander(&self, id: MacroDefId) -> TokenExpander;
|
||||
/// Fetches (and compiles) the expander of this decl macro.
|
||||
#[salsa::invoke(DeclarativeMacroExpander::expander)]
|
||||
#[ra_salsa::invoke(DeclarativeMacroExpander::expander)]
|
||||
fn decl_macro_expander(
|
||||
&self,
|
||||
def_crate: CrateId,
|
||||
@ -135,7 +135,7 @@ pub trait ExpandDatabase: SourceDatabase {
|
||||
&self,
|
||||
macro_call: MacroCallId,
|
||||
) -> Option<Arc<ExpandResult<Arc<[SyntaxError]>>>>;
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
fn syntax_context(&self, file: HirFileId) -> SyntaxContextId;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ fn apply_mark_internal(
|
||||
call_id: MacroCallId,
|
||||
transparency: Transparency,
|
||||
) -> SyntaxContextId {
|
||||
use base_db::salsa;
|
||||
use base_db::ra_salsa;
|
||||
|
||||
let call_id = Some(call_id);
|
||||
|
||||
@ -107,7 +107,7 @@ fn apply_mark_internal(
|
||||
|
||||
if transparency >= Transparency::Opaque {
|
||||
let parent = opaque;
|
||||
opaque = salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert(
|
||||
opaque = ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert(
|
||||
(parent, call_id, transparency),
|
||||
|new_opaque| SyntaxContextData {
|
||||
outer_expn: call_id,
|
||||
@ -122,7 +122,7 @@ fn apply_mark_internal(
|
||||
if transparency >= Transparency::SemiTransparent {
|
||||
let parent = opaque_and_semitransparent;
|
||||
opaque_and_semitransparent =
|
||||
salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert(
|
||||
ra_salsa::plumbing::get_query_table::<InternSyntaxContextQuery>(db).get_or_insert(
|
||||
(parent, call_id, transparency),
|
||||
|new_opaque_and_semitransparent| SyntaxContextData {
|
||||
outer_expn: call_id,
|
||||
@ -200,7 +200,7 @@ pub fn marks_rev(
|
||||
|
||||
pub(crate) fn dump_syntax_contexts(db: &dyn ExpandDatabase) -> String {
|
||||
use crate::db::{InternMacroCallLookupQuery, InternSyntaxContextLookupQuery};
|
||||
use base_db::salsa::debug::DebugQueryTable;
|
||||
use base_db::ra_salsa::debug::DebugQueryTable;
|
||||
|
||||
let mut s = String::from("Expansions:");
|
||||
let mut entries = InternMacroCallLookupQuery.in_db(db).entries::<Vec<_>>();
|
||||
|
@ -30,7 +30,7 @@ use triomphe::Arc;
|
||||
|
||||
use std::hash::Hash;
|
||||
|
||||
use base_db::{salsa::InternValueTrivial, CrateId};
|
||||
use base_db::{ra_salsa::InternValueTrivial, CrateId};
|
||||
use either::Either;
|
||||
use span::{
|
||||
Edition, EditionedFileId, ErasedFileAstId, FileAstId, HirFileIdRepr, Span, SpanAnchor,
|
||||
|
@ -15,11 +15,14 @@ pub fn prettify_macro_expansion(
|
||||
span_map: &ExpansionSpanMap,
|
||||
target_crate_id: CrateId,
|
||||
) -> SyntaxNode {
|
||||
// Because `syntax_bridge::prettify_macro_expansion::prettify_macro_expansion()` clones subtree for `syn`,
|
||||
// that means it will be offsetted to the beginning.
|
||||
let span_offset = syn.text_range().start();
|
||||
let crate_graph = db.crate_graph();
|
||||
let target_crate = &crate_graph[target_crate_id];
|
||||
let mut syntax_ctx_id_to_dollar_crate_replacement = FxHashMap::default();
|
||||
syntax_bridge::prettify_macro_expansion::prettify_macro_expansion(syn, &mut |dollar_crate| {
|
||||
let ctx = span_map.span_at(dollar_crate.text_range().start()).ctx;
|
||||
let ctx = span_map.span_at(dollar_crate.text_range().start() + span_offset).ctx;
|
||||
let replacement =
|
||||
syntax_ctx_id_to_dollar_crate_replacement.entry(ctx).or_insert_with(|| {
|
||||
let ctx_data = db.lookup_intern_syntax_context(ctx);
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Constant evaluation details
|
||||
|
||||
use base_db::{salsa::Cycle, CrateId};
|
||||
use base_db::{ra_salsa::Cycle, CrateId};
|
||||
use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
|
@ -5,7 +5,7 @@ use std::sync;
|
||||
|
||||
use base_db::{
|
||||
impl_intern_key,
|
||||
salsa::{self, InternValueTrivial},
|
||||
ra_salsa::{self, InternValueTrivial},
|
||||
CrateId, Upcast,
|
||||
};
|
||||
use hir_def::{
|
||||
@ -30,22 +30,22 @@ use crate::{
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
|
||||
#[salsa::query_group(HirDatabaseStorage)]
|
||||
#[ra_salsa::query_group(HirDatabaseStorage)]
|
||||
pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
#[salsa::invoke(crate::infer::infer_query)]
|
||||
#[ra_salsa::invoke(crate::infer::infer_query)]
|
||||
fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
|
||||
|
||||
// region:mir
|
||||
|
||||
#[salsa::invoke(crate::mir::mir_body_query)]
|
||||
#[salsa::cycle(crate::mir::mir_body_recover)]
|
||||
#[ra_salsa::invoke(crate::mir::mir_body_query)]
|
||||
#[ra_salsa::cycle(crate::mir::mir_body_recover)]
|
||||
fn mir_body(&self, def: DefWithBodyId) -> Result<Arc<MirBody>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::mir::mir_body_for_closure_query)]
|
||||
#[ra_salsa::invoke(crate::mir::mir_body_for_closure_query)]
|
||||
fn mir_body_for_closure(&self, def: ClosureId) -> Result<Arc<MirBody>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::mir::monomorphized_mir_body_query)]
|
||||
#[salsa::cycle(crate::mir::monomorphized_mir_body_recover)]
|
||||
#[ra_salsa::invoke(crate::mir::monomorphized_mir_body_query)]
|
||||
#[ra_salsa::cycle(crate::mir::monomorphized_mir_body_recover)]
|
||||
fn monomorphized_mir_body(
|
||||
&self,
|
||||
def: DefWithBodyId,
|
||||
@ -53,7 +53,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<MirBody>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)]
|
||||
#[ra_salsa::invoke(crate::mir::monomorphized_mir_body_for_closure_query)]
|
||||
fn monomorphized_mir_body_for_closure(
|
||||
&self,
|
||||
def: ClosureId,
|
||||
@ -61,12 +61,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<MirBody>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::mir::borrowck_query)]
|
||||
#[salsa::lru]
|
||||
#[ra_salsa::invoke(crate::mir::borrowck_query)]
|
||||
#[ra_salsa::lru]
|
||||
fn borrowck(&self, def: DefWithBodyId) -> Result<Arc<[BorrowckResult]>, MirLowerError>;
|
||||
|
||||
#[salsa::invoke(crate::consteval::const_eval_query)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_recover)]
|
||||
#[ra_salsa::invoke(crate::consteval::const_eval_query)]
|
||||
#[ra_salsa::cycle(crate::consteval::const_eval_recover)]
|
||||
fn const_eval(
|
||||
&self,
|
||||
def: GeneralConstId,
|
||||
@ -74,15 +74,15 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
trait_env: Option<Arc<TraitEnvironment>>,
|
||||
) -> Result<Const, ConstEvalError>;
|
||||
|
||||
#[salsa::invoke(crate::consteval::const_eval_static_query)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_static_recover)]
|
||||
#[ra_salsa::invoke(crate::consteval::const_eval_static_query)]
|
||||
#[ra_salsa::cycle(crate::consteval::const_eval_static_recover)]
|
||||
fn const_eval_static(&self, def: StaticId) -> Result<Const, ConstEvalError>;
|
||||
|
||||
#[salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
|
||||
#[salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
||||
#[ra_salsa::invoke(crate::consteval::const_eval_discriminant_variant)]
|
||||
#[ra_salsa::cycle(crate::consteval::const_eval_discriminant_recover)]
|
||||
fn const_eval_discriminant(&self, def: EnumVariantId) -> Result<i128, ConstEvalError>;
|
||||
|
||||
#[salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
|
||||
#[ra_salsa::invoke(crate::method_resolution::lookup_impl_method_query)]
|
||||
fn lookup_impl_method(
|
||||
&self,
|
||||
env: Arc<TraitEnvironment>,
|
||||
@ -92,8 +92,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
|
||||
// endregion:mir
|
||||
|
||||
#[salsa::invoke(crate::layout::layout_of_adt_query)]
|
||||
#[salsa::cycle(crate::layout::layout_of_adt_recover)]
|
||||
#[ra_salsa::invoke(crate::layout::layout_of_adt_query)]
|
||||
#[ra_salsa::cycle(crate::layout::layout_of_adt_recover)]
|
||||
fn layout_of_adt(
|
||||
&self,
|
||||
def: AdtId,
|
||||
@ -101,49 +101,49 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Result<Arc<Layout>, LayoutError>;
|
||||
|
||||
#[salsa::invoke(crate::layout::layout_of_ty_query)]
|
||||
#[salsa::cycle(crate::layout::layout_of_ty_recover)]
|
||||
#[ra_salsa::invoke(crate::layout::layout_of_ty_query)]
|
||||
#[ra_salsa::cycle(crate::layout::layout_of_ty_recover)]
|
||||
fn layout_of_ty(&self, ty: Ty, env: Arc<TraitEnvironment>) -> Result<Arc<Layout>, LayoutError>;
|
||||
|
||||
#[salsa::invoke(crate::layout::target_data_layout_query)]
|
||||
#[ra_salsa::invoke(crate::layout::target_data_layout_query)]
|
||||
fn target_data_layout(&self, krate: CrateId) -> Result<Arc<TargetDataLayout>, Arc<str>>;
|
||||
|
||||
#[salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
|
||||
#[ra_salsa::invoke(crate::dyn_compatibility::dyn_compatibility_of_trait_query)]
|
||||
fn dyn_compatibility_of_trait(&self, trait_: TraitId) -> Option<DynCompatibilityViolation>;
|
||||
|
||||
#[salsa::invoke(crate::lower::ty_query)]
|
||||
#[salsa::cycle(crate::lower::ty_recover)]
|
||||
#[ra_salsa::invoke(crate::lower::ty_query)]
|
||||
#[ra_salsa::cycle(crate::lower::ty_recover)]
|
||||
fn ty(&self, def: TyDefId) -> Binders<Ty>;
|
||||
|
||||
/// Returns the type of the value of the given constant, or `None` if the `ValueTyDefId` is
|
||||
/// a `StructId` or `EnumVariantId` with a record constructor.
|
||||
#[salsa::invoke(crate::lower::value_ty_query)]
|
||||
#[ra_salsa::invoke(crate::lower::value_ty_query)]
|
||||
fn value_ty(&self, def: ValueTyDefId) -> Option<Binders<Ty>>;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_self_ty_query)]
|
||||
#[salsa::cycle(crate::lower::impl_self_ty_recover)]
|
||||
#[ra_salsa::invoke(crate::lower::impl_self_ty_query)]
|
||||
#[ra_salsa::cycle(crate::lower::impl_self_ty_recover)]
|
||||
fn impl_self_ty(&self, def: ImplId) -> Binders<Ty>;
|
||||
|
||||
#[salsa::invoke(crate::lower::const_param_ty_query)]
|
||||
#[ra_salsa::invoke(crate::lower::const_param_ty_query)]
|
||||
fn const_param_ty(&self, def: ConstParamId) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::lower::impl_trait_query)]
|
||||
#[ra_salsa::invoke(crate::lower::impl_trait_query)]
|
||||
fn impl_trait(&self, def: ImplId) -> Option<Binders<TraitRef>>;
|
||||
|
||||
#[salsa::invoke(crate::lower::field_types_query)]
|
||||
#[ra_salsa::invoke(crate::lower::field_types_query)]
|
||||
fn field_types(&self, var: VariantId) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>>;
|
||||
|
||||
#[salsa::invoke(crate::lower::callable_item_sig)]
|
||||
#[ra_salsa::invoke(crate::lower::callable_item_sig)]
|
||||
fn callable_item_signature(&self, def: CallableDefId) -> PolyFnSig;
|
||||
|
||||
#[salsa::invoke(crate::lower::return_type_impl_traits)]
|
||||
#[ra_salsa::invoke(crate::lower::return_type_impl_traits)]
|
||||
fn return_type_impl_traits(&self, def: FunctionId) -> Option<Arc<Binders<ImplTraits>>>;
|
||||
|
||||
#[salsa::invoke(crate::lower::type_alias_impl_traits)]
|
||||
#[ra_salsa::invoke(crate::lower::type_alias_impl_traits)]
|
||||
fn type_alias_impl_traits(&self, def: TypeAliasId) -> Option<Arc<Binders<ImplTraits>>>;
|
||||
|
||||
#[salsa::invoke(crate::lower::generic_predicates_for_param_query)]
|
||||
#[salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
|
||||
#[ra_salsa::invoke(crate::lower::generic_predicates_for_param_query)]
|
||||
#[ra_salsa::cycle(crate::lower::generic_predicates_for_param_recover)]
|
||||
fn generic_predicates_for_param(
|
||||
&self,
|
||||
def: GenericDefId,
|
||||
@ -151,118 +151,118 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
assoc_name: Option<Name>,
|
||||
) -> GenericPredicates;
|
||||
|
||||
#[salsa::invoke(crate::lower::generic_predicates_query)]
|
||||
#[ra_salsa::invoke(crate::lower::generic_predicates_query)]
|
||||
fn generic_predicates(&self, def: GenericDefId) -> GenericPredicates;
|
||||
|
||||
#[salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
|
||||
#[ra_salsa::invoke(crate::lower::generic_predicates_without_parent_query)]
|
||||
fn generic_predicates_without_parent(&self, def: GenericDefId) -> GenericPredicates;
|
||||
|
||||
#[salsa::invoke(crate::lower::trait_environment_for_body_query)]
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::invoke(crate::lower::trait_environment_for_body_query)]
|
||||
#[ra_salsa::transparent]
|
||||
fn trait_environment_for_body(&self, def: DefWithBodyId) -> Arc<TraitEnvironment>;
|
||||
|
||||
#[salsa::invoke(crate::lower::trait_environment_query)]
|
||||
#[ra_salsa::invoke(crate::lower::trait_environment_query)]
|
||||
fn trait_environment(&self, def: GenericDefId) -> Arc<TraitEnvironment>;
|
||||
|
||||
#[salsa::invoke(crate::lower::generic_defaults_query)]
|
||||
#[salsa::cycle(crate::lower::generic_defaults_recover)]
|
||||
#[ra_salsa::invoke(crate::lower::generic_defaults_query)]
|
||||
#[ra_salsa::cycle(crate::lower::generic_defaults_recover)]
|
||||
fn generic_defaults(&self, def: GenericDefId) -> GenericDefaults;
|
||||
|
||||
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
|
||||
#[ra_salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
|
||||
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
|
||||
|
||||
#[salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
|
||||
#[ra_salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
|
||||
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
|
||||
|
||||
/// Collects all crates in the dependency graph that have impls for the
|
||||
/// given fingerprint. This is only used for primitive types and types
|
||||
/// annotated with `rustc_has_incoherent_inherent_impls`; for other types
|
||||
/// we just look at the crate where the type is defined.
|
||||
#[salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)]
|
||||
#[ra_salsa::invoke(crate::method_resolution::incoherent_inherent_impl_crates)]
|
||||
fn incoherent_inherent_impl_crates(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
fp: TyFingerprint,
|
||||
) -> SmallVec<[CrateId; 2]>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
||||
#[ra_salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
||||
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_block_query)]
|
||||
#[ra_salsa::invoke(TraitImpls::trait_impls_in_block_query)]
|
||||
fn trait_impls_in_block(&self, block: BlockId) -> Option<Arc<TraitImpls>>;
|
||||
|
||||
#[salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
|
||||
#[ra_salsa::invoke(TraitImpls::trait_impls_in_deps_query)]
|
||||
fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<[Arc<TraitImpls>]>;
|
||||
|
||||
// Interned IDs for Chalk integration
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_callable_def(&self, callable_def: CallableDefId) -> InternedCallableDefId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_type_or_const_param_id(
|
||||
&self,
|
||||
param_id: TypeOrConstParamId,
|
||||
) -> InternedTypeOrConstParamId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_closure(&self, id: InternedClosure) -> InternedClosureId;
|
||||
#[salsa::interned]
|
||||
#[ra_salsa::interned]
|
||||
fn intern_coroutine(&self, id: InternedCoroutine) -> InternedCoroutineId;
|
||||
|
||||
#[salsa::invoke(chalk_db::associated_ty_data_query)]
|
||||
#[ra_salsa::invoke(chalk_db::associated_ty_data_query)]
|
||||
fn associated_ty_data(
|
||||
&self,
|
||||
id: chalk_db::AssocTypeId,
|
||||
) -> sync::Arc<chalk_db::AssociatedTyDatum>;
|
||||
|
||||
#[salsa::invoke(chalk_db::trait_datum_query)]
|
||||
#[ra_salsa::invoke(chalk_db::trait_datum_query)]
|
||||
fn trait_datum(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
trait_id: chalk_db::TraitId,
|
||||
) -> sync::Arc<chalk_db::TraitDatum>;
|
||||
|
||||
#[salsa::invoke(chalk_db::adt_datum_query)]
|
||||
#[ra_salsa::invoke(chalk_db::adt_datum_query)]
|
||||
fn adt_datum(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
struct_id: chalk_db::AdtId,
|
||||
) -> sync::Arc<chalk_db::AdtDatum>;
|
||||
|
||||
#[salsa::invoke(chalk_db::impl_datum_query)]
|
||||
#[ra_salsa::invoke(chalk_db::impl_datum_query)]
|
||||
fn impl_datum(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
impl_id: chalk_db::ImplId,
|
||||
) -> sync::Arc<chalk_db::ImplDatum>;
|
||||
|
||||
#[salsa::invoke(chalk_db::fn_def_datum_query)]
|
||||
#[ra_salsa::invoke(chalk_db::fn_def_datum_query)]
|
||||
fn fn_def_datum(&self, fn_def_id: FnDefId) -> sync::Arc<chalk_db::FnDefDatum>;
|
||||
|
||||
#[salsa::invoke(chalk_db::fn_def_variance_query)]
|
||||
#[ra_salsa::invoke(chalk_db::fn_def_variance_query)]
|
||||
fn fn_def_variance(&self, fn_def_id: FnDefId) -> chalk_db::Variances;
|
||||
|
||||
#[salsa::invoke(chalk_db::adt_variance_query)]
|
||||
#[ra_salsa::invoke(chalk_db::adt_variance_query)]
|
||||
fn adt_variance(&self, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
|
||||
|
||||
#[salsa::invoke(chalk_db::associated_ty_value_query)]
|
||||
#[ra_salsa::invoke(chalk_db::associated_ty_value_query)]
|
||||
fn associated_ty_value(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
id: chalk_db::AssociatedTyValueId,
|
||||
) -> sync::Arc<chalk_db::AssociatedTyValue>;
|
||||
|
||||
#[salsa::invoke(crate::traits::normalize_projection_query)]
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::invoke(crate::traits::normalize_projection_query)]
|
||||
#[ra_salsa::transparent]
|
||||
fn normalize_projection(
|
||||
&self,
|
||||
projection: crate::ProjectionTy,
|
||||
env: Arc<TraitEnvironment>,
|
||||
) -> Ty;
|
||||
|
||||
#[salsa::invoke(crate::traits::trait_solve_query)]
|
||||
#[ra_salsa::invoke(crate::traits::trait_solve_query)]
|
||||
fn trait_solve(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
@ -270,7 +270,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
||||
goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
|
||||
) -> Option<crate::Solution>;
|
||||
|
||||
#[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
|
||||
#[ra_salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
|
||||
fn program_clauses_for_chalk_env(
|
||||
&self,
|
||||
krate: CrateId,
|
||||
@ -285,23 +285,23 @@ fn hir_database_is_dyn_compatible() {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedTypeOrConstParamId(salsa::InternId);
|
||||
pub struct InternedTypeOrConstParamId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedTypeOrConstParamId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedLifetimeParamId(salsa::InternId);
|
||||
pub struct InternedLifetimeParamId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedLifetimeParamId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedConstParamId(salsa::InternId);
|
||||
pub struct InternedConstParamId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedConstParamId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedOpaqueTyId(salsa::InternId);
|
||||
pub struct InternedOpaqueTyId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedOpaqueTyId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedClosureId(salsa::InternId);
|
||||
pub struct InternedClosureId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedClosureId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -310,7 +310,7 @@ pub struct InternedClosure(pub DefWithBodyId, pub ExprId);
|
||||
impl InternValueTrivial for InternedClosure {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct InternedCoroutineId(salsa::InternId);
|
||||
pub struct InternedCoroutineId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedCoroutineId);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
@ -320,5 +320,5 @@ impl InternValueTrivial for InternedCoroutine {}
|
||||
/// This exists just for Chalk, because Chalk just has a single `FnDefId` where
|
||||
/// we have different IDs for struct and enum variant constructors.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub struct InternedCallableDefId(salsa::InternId);
|
||||
pub struct InternedCallableDefId(ra_salsa::InternId);
|
||||
impl_intern_key!(InternedCallableDefId);
|
||||
|
@ -1008,34 +1008,28 @@ impl HirDisplay for Ty {
|
||||
if let Safety::Unsafe = sig.safety {
|
||||
write!(f, "unsafe ")?;
|
||||
}
|
||||
if !matches!(sig.abi, FnAbi::Rust) {
|
||||
if !matches!(sig.abi, FnAbi::Rust | FnAbi::RustCall) {
|
||||
f.write_str("extern \"")?;
|
||||
f.write_str(sig.abi.as_str())?;
|
||||
f.write_str("\" ")?;
|
||||
}
|
||||
|
||||
match def {
|
||||
CallableDefId::FunctionId(ff) => {
|
||||
write!(f, "fn ")?;
|
||||
f.start_location_link(def.into());
|
||||
write!(
|
||||
match def {
|
||||
CallableDefId::FunctionId(ff) => write!(
|
||||
f,
|
||||
"{}",
|
||||
db.function_data(ff).name.display(f.db.upcast(), f.edition())
|
||||
)?
|
||||
}
|
||||
)?,
|
||||
CallableDefId::StructId(s) => {
|
||||
f.start_location_link(def.into());
|
||||
write!(f, "{}", db.struct_data(s).name.display(f.db.upcast(), f.edition()))?
|
||||
}
|
||||
CallableDefId::EnumVariantId(e) => {
|
||||
f.start_location_link(def.into());
|
||||
write!(
|
||||
CallableDefId::EnumVariantId(e) => write!(
|
||||
f,
|
||||
"{}",
|
||||
db.enum_variant_data(e).name.display(f.db.upcast(), f.edition())
|
||||
)?
|
||||
}
|
||||
)?,
|
||||
};
|
||||
f.end_location_link();
|
||||
|
||||
|
@ -57,7 +57,7 @@ use crate::{
|
||||
db::HirDatabase,
|
||||
fold_tys,
|
||||
generics::Generics,
|
||||
infer::{coerce::CoerceMany, unify::InferenceTable},
|
||||
infer::{coerce::CoerceMany, expr::ExprIsRead, unify::InferenceTable},
|
||||
lower::ImplTraitLoweringMode,
|
||||
mir::MirSpan,
|
||||
to_assoc_type_id,
|
||||
@ -1154,6 +1154,7 @@ impl<'a> InferenceContext<'a> {
|
||||
_ = self.infer_expr_coerce(
|
||||
self.body.body_expr,
|
||||
&Expectation::has_type(self.return_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ use hir_def::{hir::ExprId, AdtId};
|
||||
use stdx::never;
|
||||
|
||||
use crate::{
|
||||
infer::unify::InferenceTable, Adjustment, Binders, DynTy, InferenceDiagnostic, Interner,
|
||||
PlaceholderIndex, QuantifiedWhereClauses, Ty, TyExt, TyKind, TypeFlags, WhereClause,
|
||||
infer::{coerce::CoerceNever, unify::InferenceTable},
|
||||
Adjustment, Binders, DynTy, InferenceDiagnostic, Interner, PlaceholderIndex,
|
||||
QuantifiedWhereClauses, Ty, TyExt, TyKind, TypeFlags, WhereClause,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -70,8 +71,9 @@ pub enum CastError {
|
||||
NeedViaThinPtr,
|
||||
NeedViaInt,
|
||||
NonScalar,
|
||||
UnknownCastPtrKind,
|
||||
UnknownExprPtrKind,
|
||||
// We don't want to report errors with unknown types currently.
|
||||
// UnknownCastPtrKind,
|
||||
// UnknownExprPtrKind,
|
||||
}
|
||||
|
||||
impl CastError {
|
||||
@ -127,7 +129,7 @@ impl CastCheck {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &self.cast_ty) {
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &self.cast_ty, CoerceNever::Yes) {
|
||||
apply_adjustments(self.source_expr, adj);
|
||||
set_coercion_cast(self.source_expr);
|
||||
return Ok(());
|
||||
@ -153,7 +155,8 @@ impl CastCheck {
|
||||
let sig = self.expr_ty.callable_sig(table.db).expect("FnDef had no sig");
|
||||
let sig = table.normalize_associated_types_in(sig);
|
||||
let fn_ptr = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &fn_ptr) {
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &fn_ptr, CoerceNever::Yes)
|
||||
{
|
||||
apply_adjustments(self.source_expr, adj);
|
||||
} else {
|
||||
return Err(CastError::IllegalCast);
|
||||
@ -240,7 +243,8 @@ impl CastCheck {
|
||||
if let TyKind::Array(ety, _) = t_expr.kind(Interner) {
|
||||
// Coerce to a raw pointer so that we generate RawPtr in MIR.
|
||||
let array_ptr_type = TyKind::Raw(m_expr, t_expr.clone()).intern(Interner);
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &array_ptr_type) {
|
||||
if let Ok((adj, _)) = table.coerce(&self.expr_ty, &array_ptr_type, CoerceNever::Yes)
|
||||
{
|
||||
apply_adjustments(self.source_expr, adj);
|
||||
} else {
|
||||
never!(
|
||||
@ -252,7 +256,7 @@ impl CastCheck {
|
||||
|
||||
// This is a less strict condition than rustc's `demand_eqtype`,
|
||||
// but false negative is better than false positive
|
||||
if table.coerce(ety, t_cast).is_ok() {
|
||||
if table.coerce(ety, t_cast, CoerceNever::Yes).is_ok() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
@ -272,9 +276,10 @@ impl CastCheck {
|
||||
|
||||
match (src_kind, dst_kind) {
|
||||
(Some(PointerKind::Error), _) | (_, Some(PointerKind::Error)) => Ok(()),
|
||||
(_, None) => Err(CastError::UnknownCastPtrKind),
|
||||
// (_, None) => Err(CastError::UnknownCastPtrKind),
|
||||
// (None, _) => Err(CastError::UnknownExprPtrKind),
|
||||
(_, None) | (None, _) => Ok(()),
|
||||
(_, Some(PointerKind::Thin)) => Ok(()),
|
||||
(None, _) => Err(CastError::UnknownExprPtrKind),
|
||||
(Some(PointerKind::Thin), _) => Err(CastError::SizedUnsizedCast),
|
||||
(Some(PointerKind::VTable(src_tty)), Some(PointerKind::VTable(dst_tty))) => {
|
||||
let principal = |tty: &Binders<QuantifiedWhereClauses>| {
|
||||
@ -315,7 +320,8 @@ impl CastCheck {
|
||||
expr_ty: &Ty,
|
||||
) -> Result<(), CastError> {
|
||||
match pointer_kind(expr_ty, table).map_err(|_| CastError::Unknown)? {
|
||||
None => Err(CastError::UnknownExprPtrKind),
|
||||
// None => Err(CastError::UnknownExprPtrKind),
|
||||
None => Ok(()),
|
||||
Some(PointerKind::Error) => Ok(()),
|
||||
Some(PointerKind::Thin) => Ok(()),
|
||||
_ => Err(CastError::NeedViaThinPtr),
|
||||
@ -328,7 +334,8 @@ impl CastCheck {
|
||||
cast_ty: &Ty,
|
||||
) -> Result<(), CastError> {
|
||||
match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? {
|
||||
None => Err(CastError::UnknownCastPtrKind),
|
||||
// None => Err(CastError::UnknownCastPtrKind),
|
||||
None => Ok(()),
|
||||
Some(PointerKind::Error) => Ok(()),
|
||||
Some(PointerKind::Thin) => Ok(()),
|
||||
Some(PointerKind::VTable(_)) => Err(CastError::IntToFatCast),
|
||||
@ -343,7 +350,8 @@ impl CastCheck {
|
||||
cast_ty: &Ty,
|
||||
) -> Result<(), CastError> {
|
||||
match pointer_kind(cast_ty, table).map_err(|_| CastError::Unknown)? {
|
||||
None => Err(CastError::UnknownCastPtrKind),
|
||||
// None => Err(CastError::UnknownCastPtrKind),
|
||||
None => Ok(()),
|
||||
Some(PointerKind::Error) => Ok(()),
|
||||
Some(PointerKind::Thin) => Ok(()),
|
||||
_ => Err(CastError::IllegalCast),
|
||||
|
@ -29,6 +29,7 @@ use crate::{
|
||||
db::{HirDatabase, InternedClosure},
|
||||
error_lifetime, from_chalk_trait_id, from_placeholder_idx,
|
||||
generics::Generics,
|
||||
infer::coerce::CoerceNever,
|
||||
make_binders,
|
||||
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
|
||||
to_chalk_trait_id,
|
||||
@ -65,7 +66,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
|
||||
// Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
|
||||
let _ = self.coerce(Some(closure_expr), closure_ty, &expected_ty);
|
||||
let _ = self.coerce(Some(closure_expr), closure_ty, &expected_ty, CoerceNever::Yes);
|
||||
|
||||
// Coroutines are not Fn* so return early.
|
||||
if matches!(closure_ty.kind(Interner), TyKind::Coroutine(..)) {
|
||||
|
@ -139,8 +139,8 @@ impl CoerceMany {
|
||||
};
|
||||
if let Some(sig) = sig {
|
||||
let target_ty = TyKind::Function(sig.to_fn_ptr()).intern(Interner);
|
||||
let result1 = ctx.table.coerce_inner(self.merged_ty(), &target_ty);
|
||||
let result2 = ctx.table.coerce_inner(expr_ty.clone(), &target_ty);
|
||||
let result1 = ctx.table.coerce_inner(self.merged_ty(), &target_ty, CoerceNever::Yes);
|
||||
let result2 = ctx.table.coerce_inner(expr_ty.clone(), &target_ty, CoerceNever::Yes);
|
||||
if let (Ok(result1), Ok(result2)) = (result1, result2) {
|
||||
ctx.table.register_infer_ok(InferOk { value: (), goals: result1.goals });
|
||||
for &e in &self.expressions {
|
||||
@ -159,9 +159,9 @@ impl CoerceMany {
|
||||
// type is a type variable and the new one is `!`, trying it the other
|
||||
// way around first would mean we make the type variable `!`, instead of
|
||||
// just marking it as possibly diverging.
|
||||
if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty()) {
|
||||
if let Ok(res) = ctx.coerce(expr, &expr_ty, &self.merged_ty(), CoerceNever::Yes) {
|
||||
self.final_ty = Some(res);
|
||||
} else if let Ok(res) = ctx.coerce(expr, &self.merged_ty(), &expr_ty) {
|
||||
} else if let Ok(res) = ctx.coerce(expr, &self.merged_ty(), &expr_ty, CoerceNever::Yes) {
|
||||
self.final_ty = Some(res);
|
||||
} else {
|
||||
match cause {
|
||||
@ -197,7 +197,7 @@ pub(crate) fn coerce(
|
||||
let vars = table.fresh_subst(tys.binders.as_slice(Interner));
|
||||
let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
|
||||
let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
|
||||
let (adjustments, ty) = table.coerce(&ty1_with_vars, &ty2_with_vars)?;
|
||||
let (adjustments, ty) = table.coerce(&ty1_with_vars, &ty2_with_vars, CoerceNever::Yes)?;
|
||||
// default any type vars that weren't unified back to their original bound vars
|
||||
// (kind of hacky)
|
||||
let find_var = |iv| {
|
||||
@ -219,6 +219,12 @@ pub(crate) fn coerce(
|
||||
Ok((adjustments, table.resolve_with_fallback(ty, &fallback)))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum CoerceNever {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl InferenceContext<'_> {
|
||||
/// Unify two types, but may coerce the first one to the second one
|
||||
/// using "implicit coercion rules" if needed.
|
||||
@ -227,10 +233,16 @@ impl InferenceContext<'_> {
|
||||
expr: Option<ExprId>,
|
||||
from_ty: &Ty,
|
||||
to_ty: &Ty,
|
||||
// [Comment from rustc](https://github.com/rust-lang/rust/blob/4cc494bbfe9911d24f3ee521f98d5c6bb7e3ffe8/compiler/rustc_hir_typeck/src/coercion.rs#L85-L89)
|
||||
// Whether we allow `NeverToAny` coercions. This is unsound if we're
|
||||
// coercing a place expression without it counting as a read in the MIR.
|
||||
// This is a side-effect of HIR not really having a great distinction
|
||||
// between places and values.
|
||||
coerce_never: CoerceNever,
|
||||
) -> Result<Ty, TypeError> {
|
||||
let from_ty = self.resolve_ty_shallow(from_ty);
|
||||
let to_ty = self.resolve_ty_shallow(to_ty);
|
||||
let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty)?;
|
||||
let (adjustments, ty) = self.table.coerce(&from_ty, &to_ty, coerce_never)?;
|
||||
if let Some(expr) = expr {
|
||||
self.write_expr_adj(expr, adjustments);
|
||||
}
|
||||
@ -245,10 +257,11 @@ impl InferenceTable<'_> {
|
||||
&mut self,
|
||||
from_ty: &Ty,
|
||||
to_ty: &Ty,
|
||||
coerce_never: CoerceNever,
|
||||
) -> Result<(Vec<Adjustment>, Ty), TypeError> {
|
||||
let from_ty = self.resolve_ty_shallow(from_ty);
|
||||
let to_ty = self.resolve_ty_shallow(to_ty);
|
||||
match self.coerce_inner(from_ty, &to_ty) {
|
||||
match self.coerce_inner(from_ty, &to_ty, coerce_never) {
|
||||
Ok(InferOk { value: (adjustments, ty), goals }) => {
|
||||
self.register_infer_ok(InferOk { value: (), goals });
|
||||
Ok((adjustments, ty))
|
||||
@ -260,8 +273,12 @@ impl InferenceTable<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult {
|
||||
fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty, coerce_never: CoerceNever) -> CoerceResult {
|
||||
if from_ty.is_never() {
|
||||
if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
|
||||
self.set_diverging(*tv, true);
|
||||
}
|
||||
if coerce_never == CoerceNever::Yes {
|
||||
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
|
||||
// type variable, we want `?T` to fallback to `!` if not
|
||||
// otherwise constrained. An example where this arises:
|
||||
@ -269,10 +286,10 @@ impl InferenceTable<'_> {
|
||||
// let _: Option<?T> = Some({ return; });
|
||||
//
|
||||
// here, we would coerce from `!` to `?T`.
|
||||
if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
|
||||
self.set_diverging(*tv, true);
|
||||
}
|
||||
return success(simple(Adjust::NeverToAny)(to_ty.clone()), to_ty.clone(), vec![]);
|
||||
} else {
|
||||
return self.unify_and(&from_ty, to_ty, identity);
|
||||
}
|
||||
}
|
||||
|
||||
// If we are coercing into a TAIT, coerce into its proxy inference var, instead.
|
||||
|
@ -10,10 +10,11 @@ use either::Either;
|
||||
use hir_def::{
|
||||
hir::{
|
||||
ArithOp, Array, AsmOperand, AsmOptions, BinaryOp, ClosureKind, Expr, ExprId, LabelId,
|
||||
Literal, Statement, UnaryOp,
|
||||
Literal, Pat, PatId, Statement, UnaryOp,
|
||||
},
|
||||
lang_item::{LangItem, LangItemTarget},
|
||||
path::{GenericArg, GenericArgs, Path},
|
||||
resolver::ValueNs,
|
||||
BlockId, FieldId, GenericDefId, GenericParamId, ItemContainerId, Lookup, TupleFieldId, TupleId,
|
||||
};
|
||||
use hir_expand::name::Name;
|
||||
@ -28,7 +29,7 @@ use crate::{
|
||||
error_lifetime,
|
||||
generics::{generics, Generics},
|
||||
infer::{
|
||||
coerce::{CoerceMany, CoercionCause},
|
||||
coerce::{CoerceMany, CoerceNever, CoercionCause},
|
||||
find_continuable,
|
||||
pat::contains_explicit_ref_binding,
|
||||
BreakableKind,
|
||||
@ -52,9 +53,20 @@ use super::{
|
||||
Expectation, InferenceContext, InferenceDiagnostic, TypeMismatch,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub(crate) enum ExprIsRead {
|
||||
Yes,
|
||||
No,
|
||||
}
|
||||
|
||||
impl InferenceContext<'_> {
|
||||
pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
let ty = self.infer_expr_inner(tgt_expr, expected);
|
||||
pub(crate) fn infer_expr(
|
||||
&mut self,
|
||||
tgt_expr: ExprId,
|
||||
expected: &Expectation,
|
||||
is_read: ExprIsRead,
|
||||
) -> Ty {
|
||||
let ty = self.infer_expr_inner(tgt_expr, expected, is_read);
|
||||
if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
|
||||
let could_unify = self.unify(&ty, &expected_ty);
|
||||
if !could_unify {
|
||||
@ -67,16 +79,26 @@ impl InferenceContext<'_> {
|
||||
ty
|
||||
}
|
||||
|
||||
pub(crate) fn infer_expr_no_expect(&mut self, tgt_expr: ExprId) -> Ty {
|
||||
self.infer_expr_inner(tgt_expr, &Expectation::None)
|
||||
pub(crate) fn infer_expr_no_expect(&mut self, tgt_expr: ExprId, is_read: ExprIsRead) -> Ty {
|
||||
self.infer_expr_inner(tgt_expr, &Expectation::None, is_read)
|
||||
}
|
||||
|
||||
/// Infer type of expression with possibly implicit coerce to the expected type.
|
||||
/// Return the type after possible coercion.
|
||||
pub(super) fn infer_expr_coerce(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
||||
let ty = self.infer_expr_inner(expr, expected);
|
||||
pub(super) fn infer_expr_coerce(
|
||||
&mut self,
|
||||
expr: ExprId,
|
||||
expected: &Expectation,
|
||||
is_read: ExprIsRead,
|
||||
) -> Ty {
|
||||
let ty = self.infer_expr_inner(expr, expected, is_read);
|
||||
if let Some(target) = expected.only_has_type(&mut self.table) {
|
||||
match self.coerce(Some(expr), &ty, &target) {
|
||||
let coerce_never = if self.expr_guaranteed_to_constitute_read_for_never(expr, is_read) {
|
||||
CoerceNever::Yes
|
||||
} else {
|
||||
CoerceNever::No
|
||||
};
|
||||
match self.coerce(Some(expr), &ty, &target, coerce_never) {
|
||||
Ok(res) => res,
|
||||
Err(_) => {
|
||||
self.result.type_mismatches.insert(
|
||||
@ -91,8 +113,137 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_expr_coerce_never(&mut self, expr: ExprId, expected: &Expectation) -> Ty {
|
||||
let ty = self.infer_expr_inner(expr, expected);
|
||||
/// Whether this expression constitutes a read of value of the type that
|
||||
/// it evaluates to.
|
||||
///
|
||||
/// This is used to determine if we should consider the block to diverge
|
||||
/// if the expression evaluates to `!`, and if we should insert a `NeverToAny`
|
||||
/// coercion for values of type `!`.
|
||||
///
|
||||
/// This function generally returns `false` if the expression is a place
|
||||
/// expression and the *parent* expression is the scrutinee of a match or
|
||||
/// the pointee of an `&` addr-of expression, since both of those parent
|
||||
/// expressions take a *place* and not a value.
|
||||
pub(super) fn expr_guaranteed_to_constitute_read_for_never(
|
||||
&mut self,
|
||||
expr: ExprId,
|
||||
is_read: ExprIsRead,
|
||||
) -> bool {
|
||||
// rustc does the place expr check first, but since we are feeding
|
||||
// readness of the `expr` as a given value, we just can short-circuit
|
||||
// the place expr check if it's true(see codes and comments below)
|
||||
if is_read == ExprIsRead::Yes {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We only care about place exprs. Anything else returns an immediate
|
||||
// which would constitute a read. We don't care about distinguishing
|
||||
// "syntactic" place exprs since if the base of a field projection is
|
||||
// not a place then it would've been UB to read from it anyways since
|
||||
// that constitutes a read.
|
||||
if !self.is_syntactic_place_expr(expr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// rustc queries parent hir node of `expr` here and determine whether
|
||||
// the current `expr` is read of value per its parent.
|
||||
// But since we don't have hir node, we cannot follow such "bottom-up"
|
||||
// method.
|
||||
// So, we pass down such readness from the parent expression through the
|
||||
// recursive `infer_expr*` calls in a "top-down" manner.
|
||||
is_read == ExprIsRead::Yes
|
||||
}
|
||||
|
||||
/// Whether this pattern constitutes a read of value of the scrutinee that
|
||||
/// it is matching against. This is used to determine whether we should
|
||||
/// perform `NeverToAny` coercions.
|
||||
fn pat_guaranteed_to_constitute_read_for_never(&self, pat: PatId) -> bool {
|
||||
match &self.body[pat] {
|
||||
// Does not constitute a read.
|
||||
Pat::Wild => false,
|
||||
|
||||
// This is unnecessarily restrictive when the pattern that doesn't
|
||||
// constitute a read is unreachable.
|
||||
//
|
||||
// For example `match *never_ptr { value => {}, _ => {} }` or
|
||||
// `match *never_ptr { _ if false => {}, value => {} }`.
|
||||
//
|
||||
// It is however fine to be restrictive here; only returning `true`
|
||||
// can lead to unsoundness.
|
||||
Pat::Or(subpats) => {
|
||||
subpats.iter().all(|pat| self.pat_guaranteed_to_constitute_read_for_never(*pat))
|
||||
}
|
||||
|
||||
// All of these constitute a read, or match on something that isn't `!`,
|
||||
// which would require a `NeverToAny` coercion.
|
||||
Pat::Bind { .. }
|
||||
| Pat::TupleStruct { .. }
|
||||
| Pat::Path(_)
|
||||
| Pat::Tuple { .. }
|
||||
| Pat::Box { .. }
|
||||
| Pat::Ref { .. }
|
||||
| Pat::Lit(_)
|
||||
| Pat::Range { .. }
|
||||
| Pat::Slice { .. }
|
||||
| Pat::ConstBlock(_)
|
||||
| Pat::Record { .. }
|
||||
| Pat::Missing => true,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_syntactic_place_expr(&self, expr: ExprId) -> bool {
|
||||
match &self.body[expr] {
|
||||
// Lang item paths cannot currently be local variables or statics.
|
||||
Expr::Path(Path::LangItem(_, _)) => false,
|
||||
Expr::Path(Path::Normal { type_anchor: Some(_), .. }) => false,
|
||||
Expr::Path(path) => self
|
||||
.resolver
|
||||
.resolve_path_in_value_ns_fully(self.db.upcast(), path)
|
||||
.map_or(true, |res| matches!(res, ValueNs::LocalBinding(_) | ValueNs::StaticId(_))),
|
||||
Expr::Underscore => true,
|
||||
Expr::UnaryOp { op: UnaryOp::Deref, .. } => true,
|
||||
Expr::Field { .. } | Expr::Index { .. } => true,
|
||||
Expr::Call { .. }
|
||||
| Expr::MethodCall { .. }
|
||||
| Expr::Tuple { .. }
|
||||
| Expr::If { .. }
|
||||
| Expr::Match { .. }
|
||||
| Expr::Closure { .. }
|
||||
| Expr::Block { .. }
|
||||
| Expr::Array(..)
|
||||
| Expr::Break { .. }
|
||||
| Expr::Continue { .. }
|
||||
| Expr::Return { .. }
|
||||
| Expr::Become { .. }
|
||||
| Expr::Let { .. }
|
||||
| Expr::Loop { .. }
|
||||
| Expr::InlineAsm(..)
|
||||
| Expr::OffsetOf(..)
|
||||
| Expr::Literal(..)
|
||||
| Expr::Const(..)
|
||||
| Expr::UnaryOp { .. }
|
||||
| Expr::BinaryOp { .. }
|
||||
| Expr::Yield { .. }
|
||||
| Expr::Cast { .. }
|
||||
| Expr::Async { .. }
|
||||
| Expr::Unsafe { .. }
|
||||
| Expr::Await { .. }
|
||||
| Expr::Ref { .. }
|
||||
| Expr::Range { .. }
|
||||
| Expr::Box { .. }
|
||||
| Expr::RecordLit { .. }
|
||||
| Expr::Yeet { .. }
|
||||
| Expr::Missing => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_expr_coerce_never(
|
||||
&mut self,
|
||||
expr: ExprId,
|
||||
expected: &Expectation,
|
||||
is_read: ExprIsRead,
|
||||
) -> Ty {
|
||||
let ty = self.infer_expr_inner(expr, expected, is_read);
|
||||
// While we don't allow *arbitrary* coercions here, we *do* allow
|
||||
// coercions from `!` to `expected`.
|
||||
if ty.is_never() {
|
||||
@ -105,7 +256,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
|
||||
if let Some(target) = expected.only_has_type(&mut self.table) {
|
||||
self.coerce(Some(expr), &ty, &target)
|
||||
self.coerce(Some(expr), &ty, &target, CoerceNever::Yes)
|
||||
.expect("never-to-any coercion should always succeed")
|
||||
} else {
|
||||
ty
|
||||
@ -124,7 +275,12 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
|
||||
fn infer_expr_inner(
|
||||
&mut self,
|
||||
tgt_expr: ExprId,
|
||||
expected: &Expectation,
|
||||
is_read: ExprIsRead,
|
||||
) -> Ty {
|
||||
self.db.unwind_if_cancelled();
|
||||
|
||||
let ty = match &self.body[tgt_expr] {
|
||||
@ -134,17 +290,18 @@ impl InferenceContext<'_> {
|
||||
self.infer_expr_coerce_never(
|
||||
condition,
|
||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
|
||||
let condition_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
|
||||
let then_ty = self.infer_expr_inner(then_branch, expected);
|
||||
let then_ty = self.infer_expr_inner(then_branch, expected, ExprIsRead::Yes);
|
||||
let then_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
let mut coerce = CoerceMany::new(expected.coercion_target_type(&mut self.table));
|
||||
coerce.coerce(self, Some(then_branch), &then_ty, CoercionCause::Expr(then_branch));
|
||||
match else_branch {
|
||||
Some(else_branch) => {
|
||||
let else_ty = self.infer_expr_inner(else_branch, expected);
|
||||
let else_ty = self.infer_expr_inner(else_branch, expected, ExprIsRead::Yes);
|
||||
let else_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
coerce.coerce(
|
||||
self,
|
||||
@ -163,7 +320,12 @@ impl InferenceContext<'_> {
|
||||
coerce.complete(self)
|
||||
}
|
||||
&Expr::Let { pat, expr } => {
|
||||
let input_ty = self.infer_expr(expr, &Expectation::none());
|
||||
let child_is_read = if self.pat_guaranteed_to_constitute_read_for_never(pat) {
|
||||
ExprIsRead::Yes
|
||||
} else {
|
||||
ExprIsRead::No
|
||||
};
|
||||
let input_ty = self.infer_expr(expr, &Expectation::none(), child_is_read);
|
||||
self.infer_top_pat(pat, &input_ty);
|
||||
self.result.standard_types.bool_.clone()
|
||||
}
|
||||
@ -176,7 +338,7 @@ impl InferenceContext<'_> {
|
||||
Expr::Const(id) => {
|
||||
self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||
let loc = this.db.lookup_intern_anonymous_const(*id);
|
||||
this.infer_expr(loc.root, expected)
|
||||
this.infer_expr(loc.root, expected, ExprIsRead::Yes)
|
||||
})
|
||||
.1
|
||||
}
|
||||
@ -189,7 +351,11 @@ impl InferenceContext<'_> {
|
||||
let ty = self.table.new_type_var();
|
||||
let (breaks, ()) =
|
||||
self.with_breakable_ctx(BreakableKind::Loop, Some(ty), label, |this| {
|
||||
this.infer_expr(body, &Expectation::HasType(TyBuilder::unit()));
|
||||
this.infer_expr(
|
||||
body,
|
||||
&Expectation::HasType(TyBuilder::unit()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
});
|
||||
|
||||
match breaks {
|
||||
@ -312,7 +478,7 @@ impl InferenceContext<'_> {
|
||||
ty
|
||||
}
|
||||
Expr::Call { callee, args, .. } => {
|
||||
let callee_ty = self.infer_expr(*callee, &Expectation::none());
|
||||
let callee_ty = self.infer_expr(*callee, &Expectation::none(), ExprIsRead::Yes);
|
||||
let mut derefs = Autoderef::new(&mut self.table, callee_ty.clone(), false);
|
||||
let (res, derefed_callee) = loop {
|
||||
let Some((callee_deref_ty, _)) = derefs.next() else {
|
||||
@ -393,7 +559,12 @@ impl InferenceContext<'_> {
|
||||
expected,
|
||||
),
|
||||
Expr::Match { expr, arms } => {
|
||||
let input_ty = self.infer_expr(*expr, &Expectation::none());
|
||||
let scrutinee_is_read = arms
|
||||
.iter()
|
||||
.all(|arm| self.pat_guaranteed_to_constitute_read_for_never(arm.pat));
|
||||
let scrutinee_is_read =
|
||||
if scrutinee_is_read { ExprIsRead::Yes } else { ExprIsRead::No };
|
||||
let input_ty = self.infer_expr(*expr, &Expectation::none(), scrutinee_is_read);
|
||||
|
||||
if arms.is_empty() {
|
||||
self.diverges = Diverges::Always;
|
||||
@ -423,11 +594,12 @@ impl InferenceContext<'_> {
|
||||
self.infer_expr_coerce_never(
|
||||
guard_expr,
|
||||
&Expectation::HasType(self.result.standard_types.bool_.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
}
|
||||
self.diverges = Diverges::Maybe;
|
||||
|
||||
let arm_ty = self.infer_expr_inner(arm.expr, &expected);
|
||||
let arm_ty = self.infer_expr_inner(arm.expr, &expected, ExprIsRead::Yes);
|
||||
all_arms_diverge &= self.diverges;
|
||||
coerce.coerce(self, Some(arm.expr), &arm_ty, CoercionCause::Expr(arm.expr));
|
||||
}
|
||||
@ -480,7 +652,11 @@ impl InferenceContext<'_> {
|
||||
},
|
||||
None => self.err_ty(),
|
||||
};
|
||||
self.infer_expr_inner(expr, &Expectation::HasType(opt_coerce_to))
|
||||
self.infer_expr_inner(
|
||||
expr,
|
||||
&Expectation::HasType(opt_coerce_to),
|
||||
ExprIsRead::Yes,
|
||||
)
|
||||
} else {
|
||||
TyBuilder::unit()
|
||||
};
|
||||
@ -517,10 +693,14 @@ impl InferenceContext<'_> {
|
||||
Expr::Yield { expr } => {
|
||||
if let Some((resume_ty, yield_ty)) = self.resume_yield_tys.clone() {
|
||||
if let Some(expr) = expr {
|
||||
self.infer_expr_coerce(*expr, &Expectation::has_type(yield_ty));
|
||||
self.infer_expr_coerce(
|
||||
*expr,
|
||||
&Expectation::has_type(yield_ty),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
} else {
|
||||
let unit = self.result.standard_types.unit.clone();
|
||||
let _ = self.coerce(Some(tgt_expr), &unit, &yield_ty);
|
||||
let _ = self.coerce(Some(tgt_expr), &unit, &yield_ty, CoerceNever::Yes);
|
||||
}
|
||||
resume_ty
|
||||
} else {
|
||||
@ -530,7 +710,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
Expr::Yeet { expr } => {
|
||||
if let &Some(expr) = expr {
|
||||
self.infer_expr_no_expect(expr);
|
||||
self.infer_expr_no_expect(expr, ExprIsRead::Yes);
|
||||
}
|
||||
self.result.standard_types.never.clone()
|
||||
}
|
||||
@ -589,28 +769,37 @@ impl InferenceContext<'_> {
|
||||
// Field type might have some unknown types
|
||||
// FIXME: we may want to emit a single type variable for all instance of type fields?
|
||||
let field_ty = self.insert_type_vars(field_ty);
|
||||
self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
|
||||
self.infer_expr_coerce(
|
||||
field.expr,
|
||||
&Expectation::has_type(field_ty),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for field in fields.iter() {
|
||||
self.infer_expr_coerce(field.expr, &Expectation::None);
|
||||
// Field projections don't constitute reads.
|
||||
self.infer_expr_coerce(field.expr, &Expectation::None, ExprIsRead::No);
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(expr) = spread {
|
||||
self.infer_expr(*expr, &Expectation::has_type(ty.clone()));
|
||||
self.infer_expr(*expr, &Expectation::has_type(ty.clone()), ExprIsRead::Yes);
|
||||
}
|
||||
ty
|
||||
}
|
||||
Expr::Field { expr, name } => self.infer_field_access(tgt_expr, *expr, name, expected),
|
||||
Expr::Await { expr } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes);
|
||||
self.resolve_associated_type(inner_ty, self.resolve_future_future_output())
|
||||
}
|
||||
Expr::Cast { expr, type_ref } => {
|
||||
let cast_ty = self.make_ty(type_ref);
|
||||
let expr_ty = self.infer_expr(*expr, &Expectation::Castable(cast_ty.clone()));
|
||||
let expr_ty = self.infer_expr(
|
||||
*expr,
|
||||
&Expectation::Castable(cast_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
self.deferred_cast_checks.push(CastCheck::new(
|
||||
tgt_expr,
|
||||
*expr,
|
||||
@ -638,7 +827,7 @@ impl InferenceContext<'_> {
|
||||
} else {
|
||||
Expectation::none()
|
||||
};
|
||||
let inner_ty = self.infer_expr_inner(*expr, &expectation);
|
||||
let inner_ty = self.infer_expr_inner(*expr, &expectation, ExprIsRead::Yes);
|
||||
match rawness {
|
||||
Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
|
||||
Rawness::Ref => {
|
||||
@ -650,7 +839,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
&Expr::Box { expr } => self.infer_expr_box(expr, expected),
|
||||
Expr::UnaryOp { expr, op } => {
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
|
||||
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes);
|
||||
let inner_ty = self.resolve_ty_shallow(&inner_ty);
|
||||
// FIXME: Note down method resolution her
|
||||
match op {
|
||||
@ -720,19 +909,32 @@ impl InferenceContext<'_> {
|
||||
// cannot happen in destructuring assignments because of how
|
||||
// they are desugared.
|
||||
if is_ordinary {
|
||||
let lhs_ty = self.infer_expr(lhs, &Expectation::none());
|
||||
self.infer_expr_coerce(*rhs, &Expectation::has_type(lhs_ty));
|
||||
// LHS of assignment doesn't constitute reads.
|
||||
let lhs_ty = self.infer_expr(lhs, &Expectation::none(), ExprIsRead::No);
|
||||
self.infer_expr_coerce(
|
||||
*rhs,
|
||||
&Expectation::has_type(lhs_ty),
|
||||
ExprIsRead::No,
|
||||
);
|
||||
} else {
|
||||
let rhs_ty = self.infer_expr(*rhs, &Expectation::none());
|
||||
let rhs_ty = self.infer_expr(*rhs, &Expectation::none(), ExprIsRead::Yes);
|
||||
self.infer_assignee_expr(lhs, &rhs_ty);
|
||||
}
|
||||
self.result.standard_types.unit.clone()
|
||||
}
|
||||
Some(BinaryOp::LogicOp(_)) => {
|
||||
let bool_ty = self.result.standard_types.bool_.clone();
|
||||
self.infer_expr_coerce(*lhs, &Expectation::HasType(bool_ty.clone()));
|
||||
self.infer_expr_coerce(
|
||||
*lhs,
|
||||
&Expectation::HasType(bool_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
let lhs_diverges = self.diverges;
|
||||
self.infer_expr_coerce(*rhs, &Expectation::HasType(bool_ty.clone()));
|
||||
self.infer_expr_coerce(
|
||||
*rhs,
|
||||
&Expectation::HasType(bool_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
// Depending on the LHS' value, the RHS can never execute.
|
||||
self.diverges = lhs_diverges;
|
||||
bool_ty
|
||||
@ -741,11 +943,12 @@ impl InferenceContext<'_> {
|
||||
_ => self.err_ty(),
|
||||
},
|
||||
Expr::Range { lhs, rhs, range_type } => {
|
||||
let lhs_ty = lhs.map(|e| self.infer_expr_inner(e, &Expectation::none()));
|
||||
let lhs_ty =
|
||||
lhs.map(|e| self.infer_expr_inner(e, &Expectation::none(), ExprIsRead::Yes));
|
||||
let rhs_expect = lhs_ty
|
||||
.as_ref()
|
||||
.map_or_else(Expectation::none, |ty| Expectation::has_type(ty.clone()));
|
||||
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
|
||||
let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect, ExprIsRead::Yes));
|
||||
match (range_type, lhs_ty, rhs_ty) {
|
||||
(RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
|
||||
Some(adt) => TyBuilder::adt(self.db, adt).build(),
|
||||
@ -779,8 +982,8 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
}
|
||||
Expr::Index { base, index, is_assignee_expr } => {
|
||||
let base_ty = self.infer_expr_inner(*base, &Expectation::none());
|
||||
let index_ty = self.infer_expr(*index, &Expectation::none());
|
||||
let base_ty = self.infer_expr_inner(*base, &Expectation::none(), ExprIsRead::Yes);
|
||||
let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes);
|
||||
|
||||
if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
|
||||
let canonicalized = self.canonicalize(base_ty.clone());
|
||||
@ -851,7 +1054,11 @@ impl InferenceContext<'_> {
|
||||
};
|
||||
|
||||
for (expr, ty) in exprs.iter().zip(tys.iter_mut()) {
|
||||
*ty = self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
|
||||
*ty = self.infer_expr_coerce(
|
||||
*expr,
|
||||
&Expectation::has_type(ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
}
|
||||
|
||||
TyKind::Tuple(tys.len(), Substitution::from_iter(Interner, tys)).intern(Interner)
|
||||
@ -958,7 +1165,7 @@ impl InferenceContext<'_> {
|
||||
Expr::OffsetOf(_) => TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner),
|
||||
Expr::InlineAsm(asm) => {
|
||||
let mut check_expr_asm_operand = |expr, is_input: bool| {
|
||||
let ty = self.infer_expr_no_expect(expr);
|
||||
let ty = self.infer_expr_no_expect(expr, ExprIsRead::Yes);
|
||||
|
||||
// If this is an input value, we require its type to be fully resolved
|
||||
// at this point. This allows us to provide helpful coercions which help
|
||||
@ -975,11 +1182,11 @@ impl InferenceContext<'_> {
|
||||
CallableSig::from_def(self.db, *def, parameters).to_fn_ptr(),
|
||||
)
|
||||
.intern(Interner);
|
||||
_ = self.coerce(Some(expr), &ty, &fnptr_ty);
|
||||
_ = self.coerce(Some(expr), &ty, &fnptr_ty, CoerceNever::Yes);
|
||||
}
|
||||
TyKind::Ref(mutbl, _, base_ty) => {
|
||||
let ptr_ty = TyKind::Raw(*mutbl, base_ty.clone()).intern(Interner);
|
||||
_ = self.coerce(Some(expr), &ty, &ptr_ty);
|
||||
_ = self.coerce(Some(expr), &ty, &ptr_ty, CoerceNever::Yes);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -1016,7 +1223,9 @@ impl InferenceContext<'_> {
|
||||
// use a new type variable if we got unknown here
|
||||
let ty = self.insert_type_vars_shallow(ty);
|
||||
self.write_expr_ty(tgt_expr, ty.clone());
|
||||
if self.resolve_ty_shallow(&ty).is_never() {
|
||||
if self.resolve_ty_shallow(&ty).is_never()
|
||||
&& self.expr_guaranteed_to_constitute_read_for_never(tgt_expr, is_read)
|
||||
{
|
||||
// Any expression that produces a value of type `!` must have diverged
|
||||
self.diverges = Diverges::Always;
|
||||
}
|
||||
@ -1041,7 +1250,7 @@ impl InferenceContext<'_> {
|
||||
let (_, inner_ty) = self.with_breakable_ctx(BreakableKind::Border, None, None, |this| {
|
||||
let ty = this.infer_block(tgt_expr, *id, statements, *tail, None, expected);
|
||||
if let Some(target) = expected.only_has_type(&mut this.table) {
|
||||
match this.coerce(Some(tgt_expr), &ty, &target) {
|
||||
match this.coerce(Some(tgt_expr), &ty, &target, CoerceNever::Yes) {
|
||||
Ok(res) => res,
|
||||
Err(_) => {
|
||||
this.result.type_mismatches.insert(
|
||||
@ -1153,7 +1362,7 @@ impl InferenceContext<'_> {
|
||||
Array::ElementList { elements, .. } => {
|
||||
let mut coerce = CoerceMany::new(elem_ty);
|
||||
for &expr in elements.iter() {
|
||||
let cur_elem_ty = self.infer_expr_inner(expr, &expected);
|
||||
let cur_elem_ty = self.infer_expr_inner(expr, &expected, ExprIsRead::Yes);
|
||||
coerce.coerce(self, Some(expr), &cur_elem_ty, CoercionCause::Expr(expr));
|
||||
}
|
||||
(
|
||||
@ -1162,13 +1371,17 @@ impl InferenceContext<'_> {
|
||||
)
|
||||
}
|
||||
&Array::Repeat { initializer, repeat } => {
|
||||
self.infer_expr_coerce(initializer, &Expectation::has_type(elem_ty.clone()));
|
||||
self.infer_expr_coerce(
|
||||
initializer,
|
||||
&Expectation::has_type(elem_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
let usize = TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(Interner);
|
||||
match self.body[repeat] {
|
||||
Expr::Underscore => {
|
||||
self.write_expr_ty(repeat, usize);
|
||||
}
|
||||
_ => _ = self.infer_expr(repeat, &Expectation::HasType(usize)),
|
||||
_ => _ = self.infer_expr(repeat, &Expectation::HasType(usize), ExprIsRead::Yes),
|
||||
}
|
||||
|
||||
(
|
||||
@ -1193,7 +1406,8 @@ impl InferenceContext<'_> {
|
||||
.as_mut()
|
||||
.expect("infer_return called outside function body")
|
||||
.expected_ty();
|
||||
let return_expr_ty = self.infer_expr_inner(expr, &Expectation::HasType(ret_ty));
|
||||
let return_expr_ty =
|
||||
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty), ExprIsRead::Yes);
|
||||
let mut coerce_many = self.return_coercion.take().unwrap();
|
||||
coerce_many.coerce(self, Some(expr), &return_expr_ty, CoercionCause::Expr(expr));
|
||||
self.return_coercion = Some(coerce_many);
|
||||
@ -1213,7 +1427,7 @@ impl InferenceContext<'_> {
|
||||
None => {
|
||||
// FIXME: diagnose return outside of function
|
||||
if let Some(expr) = expr {
|
||||
self.infer_expr_no_expect(expr);
|
||||
self.infer_expr_no_expect(expr, ExprIsRead::Yes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1225,8 +1439,11 @@ impl InferenceContext<'_> {
|
||||
Some(return_coercion) => {
|
||||
let ret_ty = return_coercion.expected_ty();
|
||||
|
||||
let call_expr_ty =
|
||||
self.infer_expr_inner(expr, &Expectation::HasType(ret_ty.clone()));
|
||||
let call_expr_ty = self.infer_expr_inner(
|
||||
expr,
|
||||
&Expectation::HasType(ret_ty.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
|
||||
// NB: this should *not* coerce.
|
||||
// tail calls don't support any coercions except lifetimes ones (like `&'static u8 -> &'a u8`).
|
||||
@ -1234,7 +1451,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
None => {
|
||||
// FIXME: diagnose `become` outside of functions
|
||||
self.infer_expr_no_expect(expr);
|
||||
self.infer_expr_no_expect(expr, ExprIsRead::Yes);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1255,7 +1472,7 @@ impl InferenceContext<'_> {
|
||||
})
|
||||
.unwrap_or_else(Expectation::none);
|
||||
|
||||
let inner_ty = self.infer_expr_inner(inner_expr, &inner_exp);
|
||||
let inner_ty = self.infer_expr_inner(inner_expr, &inner_exp, ExprIsRead::Yes);
|
||||
TyBuilder::adt(self.db, box_id)
|
||||
.push(inner_ty)
|
||||
.fill_with_defaults(self.db, || self.table.new_type_var())
|
||||
@ -1333,12 +1550,13 @@ impl InferenceContext<'_> {
|
||||
Expr::Underscore => rhs_ty.clone(),
|
||||
_ => {
|
||||
// `lhs` is a place expression, a unit struct, or an enum variant.
|
||||
let lhs_ty = self.infer_expr_inner(lhs, &Expectation::none());
|
||||
// LHS of assignment doesn't constitute reads.
|
||||
let lhs_ty = self.infer_expr_inner(lhs, &Expectation::none(), ExprIsRead::No);
|
||||
|
||||
// This is the only branch where this function may coerce any type.
|
||||
// We are returning early to avoid the unifiability check below.
|
||||
let lhs_ty = self.insert_type_vars_shallow(lhs_ty);
|
||||
let ty = match self.coerce(None, &rhs_ty, &lhs_ty) {
|
||||
let ty = match self.coerce(None, &rhs_ty, &lhs_ty, CoerceNever::Yes) {
|
||||
Ok(ty) => ty,
|
||||
Err(_) => {
|
||||
self.result.type_mismatches.insert(
|
||||
@ -1373,7 +1591,12 @@ impl InferenceContext<'_> {
|
||||
tgt_expr: ExprId,
|
||||
) -> Ty {
|
||||
let lhs_expectation = Expectation::none();
|
||||
let lhs_ty = self.infer_expr(lhs, &lhs_expectation);
|
||||
let is_read = if matches!(op, BinaryOp::Assignment { .. }) {
|
||||
ExprIsRead::Yes
|
||||
} else {
|
||||
ExprIsRead::No
|
||||
};
|
||||
let lhs_ty = self.infer_expr(lhs, &lhs_expectation, is_read);
|
||||
let rhs_ty = self.table.new_type_var();
|
||||
|
||||
let trait_func = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
|
||||
@ -1396,7 +1619,7 @@ impl InferenceContext<'_> {
|
||||
self.err_ty()
|
||||
};
|
||||
|
||||
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty));
|
||||
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty), ExprIsRead::Yes);
|
||||
|
||||
return ret_ty;
|
||||
}
|
||||
@ -1415,7 +1638,7 @@ impl InferenceContext<'_> {
|
||||
let method_ty = self.db.value_ty(func.into()).unwrap().substitute(Interner, &subst);
|
||||
self.register_obligations_for_call(&method_ty);
|
||||
|
||||
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()));
|
||||
self.infer_expr_coerce(rhs, &Expectation::has_type(rhs_ty.clone()), ExprIsRead::Yes);
|
||||
|
||||
let ret_ty = match method_ty.callable_sig(self.db) {
|
||||
Some(sig) => {
|
||||
@ -1487,12 +1710,25 @@ impl InferenceContext<'_> {
|
||||
.unwrap_or_else(|| this.table.new_type_var());
|
||||
|
||||
let ty = if let Some(expr) = initializer {
|
||||
// If we have a subpattern that performs a read, we want to consider this
|
||||
// to diverge for compatibility to support something like `let x: () = *never_ptr;`.
|
||||
let target_is_read =
|
||||
if this.pat_guaranteed_to_constitute_read_for_never(*pat) {
|
||||
ExprIsRead::Yes
|
||||
} else {
|
||||
ExprIsRead::No
|
||||
};
|
||||
let ty = if contains_explicit_ref_binding(this.body, *pat) {
|
||||
this.infer_expr(*expr, &Expectation::has_type(decl_ty.clone()))
|
||||
this.infer_expr(
|
||||
*expr,
|
||||
&Expectation::has_type(decl_ty.clone()),
|
||||
target_is_read,
|
||||
)
|
||||
} else {
|
||||
this.infer_expr_coerce(
|
||||
*expr,
|
||||
&Expectation::has_type(decl_ty.clone()),
|
||||
target_is_read,
|
||||
)
|
||||
};
|
||||
if type_ref.is_some() {
|
||||
@ -1512,17 +1748,19 @@ impl InferenceContext<'_> {
|
||||
this.infer_expr_coerce(
|
||||
*expr,
|
||||
&Expectation::HasType(this.result.standard_types.never.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
this.diverges = previous_diverges;
|
||||
}
|
||||
}
|
||||
&Statement::Expr { expr, has_semi } => {
|
||||
if has_semi {
|
||||
this.infer_expr(expr, &Expectation::none());
|
||||
this.infer_expr(expr, &Expectation::none(), ExprIsRead::Yes);
|
||||
} else {
|
||||
this.infer_expr_coerce(
|
||||
expr,
|
||||
&Expectation::HasType(this.result.standard_types.unit.clone()),
|
||||
ExprIsRead::Yes,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1532,7 +1770,7 @@ impl InferenceContext<'_> {
|
||||
|
||||
// FIXME: This should make use of the breakable CoerceMany
|
||||
if let Some(expr) = tail {
|
||||
this.infer_expr_coerce(expr, expected)
|
||||
this.infer_expr_coerce(expr, expected, ExprIsRead::Yes)
|
||||
} else {
|
||||
// Citing rustc: if there is no explicit tail expression,
|
||||
// that is typically equivalent to a tail expression
|
||||
@ -1545,8 +1783,20 @@ impl InferenceContext<'_> {
|
||||
// we don't even make an attempt at coercion
|
||||
this.table.new_maybe_never_var()
|
||||
} else if let Some(t) = expected.only_has_type(&mut this.table) {
|
||||
let coerce_never = if this
|
||||
.expr_guaranteed_to_constitute_read_for_never(expr, ExprIsRead::Yes)
|
||||
{
|
||||
CoerceNever::Yes
|
||||
} else {
|
||||
CoerceNever::No
|
||||
};
|
||||
if this
|
||||
.coerce(Some(expr), &this.result.standard_types.unit.clone(), &t)
|
||||
.coerce(
|
||||
Some(expr),
|
||||
&this.result.standard_types.unit.clone(),
|
||||
&t,
|
||||
coerce_never,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
this.result.type_mismatches.insert(
|
||||
@ -1658,7 +1908,8 @@ impl InferenceContext<'_> {
|
||||
name: &Name,
|
||||
expected: &Expectation,
|
||||
) -> Ty {
|
||||
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none());
|
||||
// Field projections don't constitute reads.
|
||||
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::No);
|
||||
|
||||
if name.is_missing() {
|
||||
// Bail out early, don't even try to look up field. Also, we don't issue an unresolved
|
||||
@ -1730,7 +1981,7 @@ impl InferenceContext<'_> {
|
||||
generic_args: Option<&GenericArgs>,
|
||||
expected: &Expectation,
|
||||
) -> Ty {
|
||||
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none());
|
||||
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes);
|
||||
let canonicalized_receiver = self.canonicalize(receiver_ty.clone());
|
||||
|
||||
let resolved = method_resolution::lookup_method(
|
||||
@ -1917,7 +2168,7 @@ impl InferenceContext<'_> {
|
||||
let expected_ty = self.normalize_associated_types_in(expected_ty);
|
||||
let expected = Expectation::rvalue_hint(self, expected_ty);
|
||||
// infer with the expected type we have...
|
||||
let ty = self.infer_expr_inner(arg, &expected);
|
||||
let ty = self.infer_expr_inner(arg, &expected, ExprIsRead::Yes);
|
||||
|
||||
// then coerce to either the expected type or just the formal parameter type
|
||||
let coercion_target = if let Some(ty) = expected.only_has_type(&mut self.table) {
|
||||
@ -1931,7 +2182,20 @@ impl InferenceContext<'_> {
|
||||
// The function signature may contain some unknown types, so we need to insert
|
||||
// type vars here to avoid type mismatch false positive.
|
||||
let coercion_target = self.insert_type_vars(coercion_target);
|
||||
if self.coerce(Some(arg), &ty, &coercion_target).is_err() && !arg_count_mismatch {
|
||||
|
||||
// Any expression that produces a value of type `!` must have diverged,
|
||||
// unless it's a place expression that isn't being read from, in which case
|
||||
// diverging would be unsound since we may never actually read the `!`.
|
||||
// e.g. `let _ = *never_ptr;` with `never_ptr: *const !`.
|
||||
let coerce_never =
|
||||
if self.expr_guaranteed_to_constitute_read_for_never(arg, ExprIsRead::Yes) {
|
||||
CoerceNever::Yes
|
||||
} else {
|
||||
CoerceNever::No
|
||||
};
|
||||
if self.coerce(Some(arg), &ty, &coercion_target, coerce_never).is_err()
|
||||
&& !arg_count_mismatch
|
||||
{
|
||||
self.result.type_mismatches.insert(
|
||||
arg.into(),
|
||||
TypeMismatch { expected: coercion_target, actual: ty.clone() },
|
||||
@ -2106,7 +2370,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
let _ty = arg.data(Interner).ty.clone();
|
||||
let expected = Expectation::none(); // FIXME use actual const ty, when that is lowered correctly
|
||||
self.infer_expr(args[arg_idx as usize], &expected);
|
||||
self.infer_expr(args[arg_idx as usize], &expected, ExprIsRead::Yes);
|
||||
// FIXME: evaluate and unify with the const
|
||||
}
|
||||
let mut indices = legacy_const_generics_indices.as_ref().clone();
|
||||
|
@ -12,12 +12,11 @@ use hir_expand::name::Name;
|
||||
use intern::sym;
|
||||
|
||||
use crate::{
|
||||
infer::Expectation, lower::lower_to_chalk_mutability, Adjust, Adjustment, AutoBorrow, Interner,
|
||||
OverloadedDeref, TyBuilder, TyKind,
|
||||
infer::{expr::ExprIsRead, Expectation, InferenceContext},
|
||||
lower::lower_to_chalk_mutability,
|
||||
Adjust, Adjustment, AutoBorrow, Interner, OverloadedDeref, TyBuilder, TyKind,
|
||||
};
|
||||
|
||||
use super::InferenceContext;
|
||||
|
||||
impl InferenceContext<'_> {
|
||||
pub(crate) fn infer_mut_body(&mut self) {
|
||||
self.infer_mut_expr(self.body.body_expr, Mutability::Not);
|
||||
@ -164,7 +163,11 @@ impl InferenceContext<'_> {
|
||||
if let Some(ty) = self.result.type_of_expr.get(index) {
|
||||
ty.clone()
|
||||
} else {
|
||||
self.infer_expr(index, &Expectation::none())
|
||||
self.infer_expr(
|
||||
index,
|
||||
&Expectation::none(),
|
||||
ExprIsRead::Yes,
|
||||
)
|
||||
};
|
||||
let trait_ref = TyBuilder::trait_ref(self.db, index_trait)
|
||||
.push(base_ty)
|
||||
@ -180,6 +183,7 @@ impl InferenceContext<'_> {
|
||||
self.infer_mut_expr(index, Mutability::Not);
|
||||
}
|
||||
Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
|
||||
let mut mutability = mutability;
|
||||
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
|
||||
if mutability == Mutability::Mut {
|
||||
if let Some(deref_trait) = self
|
||||
@ -187,7 +191,17 @@ impl InferenceContext<'_> {
|
||||
.lang_item(self.table.trait_env.krate, LangItem::DerefMut)
|
||||
.and_then(|l| l.as_trait())
|
||||
{
|
||||
if let Some(deref_fn) = self
|
||||
let ty = self.result.type_of_expr.get(*expr);
|
||||
let is_mut_ptr = ty.is_some_and(|ty| {
|
||||
let ty = self.table.resolve_ty_shallow(ty);
|
||||
matches!(
|
||||
ty.kind(Interner),
|
||||
chalk_ir::TyKind::Raw(Mutability::Mut, _)
|
||||
)
|
||||
});
|
||||
if is_mut_ptr {
|
||||
mutability = Mutability::Not;
|
||||
} else if let Some(deref_fn) = self
|
||||
.db
|
||||
.trait_data(deref_trait)
|
||||
.method_by_name(&Name::new_symbol_root(sym::deref_mut.clone()))
|
||||
|
@ -12,7 +12,7 @@ use stdx::TupleExt;
|
||||
|
||||
use crate::{
|
||||
consteval::{try_const_usize, usize_const},
|
||||
infer::{BindingMode, Expectation, InferenceContext, TypeMismatch},
|
||||
infer::{expr::ExprIsRead, BindingMode, Expectation, InferenceContext, TypeMismatch},
|
||||
lower::lower_to_chalk_mutability,
|
||||
primitive::UintTy,
|
||||
static_lifetime, InferenceDiagnostic, Interner, Mutability, Scalar, Substitution, Ty,
|
||||
@ -361,7 +361,7 @@ impl InferenceContext<'_> {
|
||||
None => self.err_ty(),
|
||||
},
|
||||
Pat::ConstBlock(expr) => {
|
||||
self.infer_expr(*expr, &Expectation::has_type(expected.clone()))
|
||||
self.infer_expr(*expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes)
|
||||
}
|
||||
Pat::Missing => self.err_ty(),
|
||||
};
|
||||
@ -497,7 +497,7 @@ impl InferenceContext<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
self.infer_expr(expr, &Expectation::has_type(expected.clone()))
|
||||
self.infer_expr(expr, &Expectation::has_type(expected.clone()), ExprIsRead::Yes)
|
||||
}
|
||||
|
||||
fn is_non_ref_pat(&mut self, body: &hir_def::body::Body, pat: PatId) -> bool {
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
ProgramClauseData, ProgramClauses, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
|
||||
Substitution, Ty, TyData, TyKind, VariableKind, VariableKinds,
|
||||
};
|
||||
use base_db::salsa::InternId;
|
||||
use base_db::ra_salsa::InternId;
|
||||
use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance};
|
||||
use hir_def::TypeAliasId;
|
||||
use intern::{impl_internable, Interned};
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use base_db::salsa::Cycle;
|
||||
use base_db::ra_salsa::Cycle;
|
||||
use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
|
||||
use hir_def::{
|
||||
layout::{
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::{cmp, ops::Bound};
|
||||
|
||||
use base_db::salsa::Cycle;
|
||||
use base_db::ra_salsa::Cycle;
|
||||
use hir_def::{
|
||||
data::adt::VariantData,
|
||||
layout::{Integer, ReprOptions, TargetDataLayout},
|
||||
|
@ -56,7 +56,7 @@ use std::{
|
||||
hash::{BuildHasherDefault, Hash},
|
||||
};
|
||||
|
||||
use base_db::salsa::InternValueTrivial;
|
||||
use base_db::ra_salsa::InternValueTrivial;
|
||||
use chalk_ir::{
|
||||
fold::{Shift, TypeFoldable},
|
||||
interner::HasInterner,
|
||||
|
@ -11,7 +11,7 @@ use std::{
|
||||
ops::{self, Not as _},
|
||||
};
|
||||
|
||||
use base_db::{salsa::Cycle, CrateId};
|
||||
use base_db::{ra_salsa::Cycle, CrateId};
|
||||
use chalk_ir::{
|
||||
cast::Cast,
|
||||
fold::{Shift, TypeFoldable},
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
use chalk_solve::rust_ir;
|
||||
|
||||
use base_db::salsa::{self, InternKey};
|
||||
use base_db::ra_salsa::{self, InternKey};
|
||||
use hir_def::{LifetimeParamId, TraitId, TypeAliasId, TypeOrConstParamId};
|
||||
|
||||
use crate::{
|
||||
@ -116,24 +116,24 @@ impl From<crate::db::InternedCoroutineId> for chalk_ir::CoroutineId<Interner> {
|
||||
}
|
||||
|
||||
pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
|
||||
chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
|
||||
chalk_ir::ForeignDefId(ra_salsa::InternKey::as_intern_id(&id))
|
||||
}
|
||||
|
||||
pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
|
||||
salsa::InternKey::from_intern_id(id.0)
|
||||
ra_salsa::InternKey::from_intern_id(id.0)
|
||||
}
|
||||
|
||||
pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
|
||||
chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
|
||||
chalk_ir::AssocTypeId(ra_salsa::InternKey::as_intern_id(&id))
|
||||
}
|
||||
|
||||
pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
|
||||
salsa::InternKey::from_intern_id(id.0)
|
||||
ra_salsa::InternKey::from_intern_id(id.0)
|
||||
}
|
||||
|
||||
pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId {
|
||||
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
||||
let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
|
||||
let interned_id = ra_salsa::InternKey::from_intern_id(ra_salsa::InternId::from(idx.idx));
|
||||
db.lookup_intern_type_or_const_param_id(interned_id)
|
||||
}
|
||||
|
||||
@ -141,13 +141,13 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Place
|
||||
let interned_id = db.intern_type_or_const_param_id(id);
|
||||
PlaceholderIndex {
|
||||
ui: chalk_ir::UniverseIndex::ROOT,
|
||||
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||
idx: ra_salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
|
||||
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
|
||||
let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
|
||||
let interned_id = ra_salsa::InternKey::from_intern_id(ra_salsa::InternId::from(idx.idx));
|
||||
db.lookup_intern_lifetime_param_id(interned_id)
|
||||
}
|
||||
|
||||
@ -155,14 +155,14 @@ pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> Place
|
||||
let interned_id = db.intern_lifetime_param_id(id);
|
||||
PlaceholderIndex {
|
||||
ui: chalk_ir::UniverseIndex::ROOT,
|
||||
idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||
idx: ra_salsa::InternKey::as_intern_id(&interned_id).as_usize(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
|
||||
chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
|
||||
chalk_ir::TraitId(ra_salsa::InternKey::as_intern_id(&id))
|
||||
}
|
||||
|
||||
pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
|
||||
salsa::InternKey::from_intern_id(id.0)
|
||||
ra_salsa::InternKey::from_intern_id(id.0)
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use std::{fmt::Write, iter, mem};
|
||||
|
||||
use base_db::salsa::Cycle;
|
||||
use base_db::ra_salsa::Cycle;
|
||||
use chalk_ir::{BoundVar, ConstData, DebruijnIndex, TyKind};
|
||||
use hir_def::{
|
||||
body::Body,
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
use std::mem;
|
||||
|
||||
use base_db::salsa::Cycle;
|
||||
use base_db::ra_salsa::Cycle;
|
||||
use chalk_ir::{
|
||||
fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable},
|
||||
ConstData, DebruijnIndex,
|
||||
|
@ -3,7 +3,7 @@
|
||||
use std::{fmt, panic, sync::Mutex};
|
||||
|
||||
use base_db::{
|
||||
salsa::{self, Durability},
|
||||
ra_salsa::{self, Durability},
|
||||
AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
|
||||
};
|
||||
use hir_def::{db::DefDatabase, ModuleId};
|
||||
@ -14,7 +14,7 @@ use syntax::TextRange;
|
||||
use test_utils::extract_annotations;
|
||||
use triomphe::Arc;
|
||||
|
||||
#[salsa::database(
|
||||
#[ra_salsa::database(
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir_expand::db::ExpandDatabaseStorage,
|
||||
@ -23,8 +23,8 @@ use triomphe::Arc;
|
||||
crate::db::HirDatabaseStorage
|
||||
)]
|
||||
pub(crate) struct TestDB {
|
||||
storage: salsa::Storage<TestDB>,
|
||||
events: Mutex<Option<Vec<salsa::Event>>>,
|
||||
storage: ra_salsa::Storage<TestDB>,
|
||||
events: Mutex<Option<Vec<ra_salsa::Event>>>,
|
||||
}
|
||||
|
||||
impl Default for TestDB {
|
||||
@ -54,8 +54,8 @@ impl Upcast<dyn DefDatabase> for TestDB {
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::Database for TestDB {
|
||||
fn salsa_event(&self, event: salsa::Event) {
|
||||
impl ra_salsa::Database for TestDB {
|
||||
fn salsa_event(&self, event: ra_salsa::Event) {
|
||||
let mut events = self.events.lock().unwrap();
|
||||
if let Some(events) = &mut *events {
|
||||
events.push(event);
|
||||
@ -63,9 +63,9 @@ impl salsa::Database for TestDB {
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::ParallelDatabase for TestDB {
|
||||
fn snapshot(&self) -> salsa::Snapshot<TestDB> {
|
||||
salsa::Snapshot::new(TestDB {
|
||||
impl ra_salsa::ParallelDatabase for TestDB {
|
||||
fn snapshot(&self) -> ra_salsa::Snapshot<TestDB> {
|
||||
ra_salsa::Snapshot::new(TestDB {
|
||||
storage: self.storage.snapshot(),
|
||||
events: Default::default(),
|
||||
})
|
||||
@ -128,7 +128,7 @@ impl TestDB {
|
||||
}
|
||||
|
||||
impl TestDB {
|
||||
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<salsa::Event> {
|
||||
pub(crate) fn log(&self, f: impl FnOnce()) -> Vec<ra_salsa::Event> {
|
||||
*self.events.lock().unwrap() = Some(Vec::new());
|
||||
f();
|
||||
self.events.lock().unwrap().take().unwrap()
|
||||
@ -141,7 +141,7 @@ impl TestDB {
|
||||
.filter_map(|e| match e.kind {
|
||||
// This is pretty horrible, but `Debug` is the only way to inspect
|
||||
// QueryDescriptor at the moment.
|
||||
salsa::EventKind::WillExecute { database_key } => {
|
||||
ra_salsa::EventKind::WillExecute { database_key } => {
|
||||
Some(format!("{:?}", database_key.debug(self)))
|
||||
}
|
||||
_ => None,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use base_db::salsa::InternKey;
|
||||
use base_db::ra_salsa::InternKey;
|
||||
use expect_test::{expect, Expect};
|
||||
use hir_def::db::DefDatabase;
|
||||
use hir_expand::files::InFileWrapper;
|
||||
|
@ -64,7 +64,7 @@ fn infer_macros_expanded() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
!0..17 '{Foo(v...,2,])}': Foo
|
||||
!1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo
|
||||
!1..4 'Foo': fn Foo({unknown}) -> Foo
|
||||
!1..16 'Foo(vec![1,2,])': Foo
|
||||
!5..15 'vec![1,2,]': {unknown}
|
||||
155..181 '{ ...,2); }': ()
|
||||
@ -97,7 +97,7 @@ fn infer_legacy_textual_scoped_macros_expanded() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
!0..17 '{Foo(v...,2,])}': Foo
|
||||
!1..4 'Foo': extern "rust-call" Foo({unknown}) -> Foo
|
||||
!1..4 'Foo': fn Foo({unknown}) -> Foo
|
||||
!1..16 'Foo(vec![1,2,])': Foo
|
||||
!5..15 'vec![1,2,]': {unknown}
|
||||
194..250 '{ ...,2); }': ()
|
||||
|
@ -539,3 +539,249 @@ fn test() {
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match1() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn not_a_read() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let _: ! = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
21..100 '{ ... } }': !
|
||||
27..98 'unsafe... }': !
|
||||
48..49 'x': *const !
|
||||
62..63 '0': i32
|
||||
62..68 '0 as _': *const !
|
||||
82..83 '_': !
|
||||
89..91 '*x': !
|
||||
90..91 'x': *const !
|
||||
27..98: expected !, got ()
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match2() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn not_a_read_implicit() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let _ = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
30..106 '{ ... } }': !
|
||||
36..104 'unsafe... }': !
|
||||
57..58 'x': *const !
|
||||
71..72 '0': i32
|
||||
71..77 '0 as _': *const !
|
||||
91..92 '_': !
|
||||
95..97 '*x': !
|
||||
96..97 'x': *const !
|
||||
36..104: expected !, got ()
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match3() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn not_a_read_guide_coercion() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let _: () = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
36..116 '{ ... } }': !
|
||||
42..114 'unsafe... }': !
|
||||
63..64 'x': *const !
|
||||
77..78 '0': i32
|
||||
77..83 '0 as _': *const !
|
||||
97..98 '_': ()
|
||||
105..107 '*x': !
|
||||
106..107 'x': *const !
|
||||
42..114: expected !, got ()
|
||||
105..107: expected (), got !
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match4() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn empty_match() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
match *x { _ => {} };
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
22..108 '{ ... } }': !
|
||||
28..106 'unsafe... }': !
|
||||
49..50 'x': *const !
|
||||
63..64 '0': i32
|
||||
63..69 '0 as _': *const !
|
||||
79..99 'match ...> {} }': ()
|
||||
85..87 '*x': !
|
||||
86..87 'x': *const !
|
||||
90..91 '_': !
|
||||
95..97 '{}': ()
|
||||
28..106: expected !, got ()
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match5() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn field_projection() -> ! {
|
||||
unsafe {
|
||||
let x: *const (!, ()) = 0 as _;
|
||||
let _ = (*x).0;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
27..113 '{ ... } }': !
|
||||
33..111 'unsafe... }': !
|
||||
54..55 'x': *const (!, ())
|
||||
74..75 '0': i32
|
||||
74..80 '0 as _': *const (!, ())
|
||||
94..95 '_': !
|
||||
98..104 '(*x).0': !
|
||||
99..101 '*x': (!, ())
|
||||
100..101 'x': *const (!, ())
|
||||
33..111: expected !, got ()
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match6() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn covered_arm() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let (_ | 1i32) = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
22..107 '{ ... } }': !
|
||||
28..105 'unsafe... }': !
|
||||
49..50 'x': *const !
|
||||
63..64 '0': i32
|
||||
63..69 '0 as _': *const !
|
||||
84..85 '_': !
|
||||
84..92 '_ | 1i32': !
|
||||
88..92 '1i32': i32
|
||||
88..92 '1i32': i32
|
||||
96..98 '*x': !
|
||||
97..98 'x': *const !
|
||||
28..105: expected !, got ()
|
||||
88..92: expected !, got i32
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match7() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn uncovered_arm() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let (1i32 | _) = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
24..109 '{ ... } }': !
|
||||
30..107 'unsafe... }': !
|
||||
51..52 'x': *const !
|
||||
65..66 '0': i32
|
||||
65..71 '0 as _': *const !
|
||||
86..90 '1i32': i32
|
||||
86..90 '1i32': i32
|
||||
86..94 '1i32 | _': !
|
||||
93..94 '_': !
|
||||
98..100 '*x': !
|
||||
99..100 'x': *const !
|
||||
30..107: expected !, got ()
|
||||
86..90: expected !, got i32
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn diverging_place_match8() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn coerce_ref_binding() -> ! {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
let ref _x: () = *x;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
29..114 '{ ... } }': !
|
||||
35..112 'unsafe... }': !
|
||||
56..57 'x': *const !
|
||||
70..71 '0': i32
|
||||
70..76 '0 as _': *const !
|
||||
90..96 'ref _x': &'? ()
|
||||
103..105 '*x': !
|
||||
104..105 'x': *const !
|
||||
103..105: expected (), got !
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn never_place_isnt_diverging() {
|
||||
check_infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn make_up_a_pointer<T>() -> *const T {
|
||||
unsafe {
|
||||
let x: *const ! = 0 as _;
|
||||
&raw const *x
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
38..116 '{ ... } }': *const T
|
||||
44..114 'unsafe... }': *const T
|
||||
65..66 'x': *const !
|
||||
79..80 '0': i32
|
||||
79..85 '0 as _': *const !
|
||||
95..108 '&raw const *x': *const !
|
||||
106..108 '*x': !
|
||||
107..108 'x': *const !
|
||||
95..108: expected *const T, got *const !
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
@ -227,13 +227,13 @@ fn infer_pattern_match_ergonomics() {
|
||||
37..41 'A(n)': A<i32>
|
||||
39..40 'n': &'? i32
|
||||
44..49 '&A(1)': &'? A<i32>
|
||||
45..46 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
45..46 'A': fn A<i32>(i32) -> A<i32>
|
||||
45..49 'A(1)': A<i32>
|
||||
47..48 '1': i32
|
||||
59..63 'A(n)': A<i32>
|
||||
61..62 'n': &'? mut i32
|
||||
66..75 '&mut A(1)': &'? mut A<i32>
|
||||
71..72 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
71..72 'A': fn A<i32>(i32) -> A<i32>
|
||||
71..75 'A(1)': A<i32>
|
||||
73..74 '1': i32
|
||||
"#]],
|
||||
@ -548,18 +548,18 @@ impl Foo {
|
||||
56..64 'Self(s,)': Foo
|
||||
61..62 's': &'? usize
|
||||
67..75 '&Foo(0,)': &'? Foo
|
||||
68..71 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
68..71 'Foo': fn Foo(usize) -> Foo
|
||||
68..75 'Foo(0,)': Foo
|
||||
72..73 '0': usize
|
||||
89..97 'Self(s,)': Foo
|
||||
94..95 's': &'? mut usize
|
||||
100..112 '&mut Foo(0,)': &'? mut Foo
|
||||
105..108 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
105..108 'Foo': fn Foo(usize) -> Foo
|
||||
105..112 'Foo(0,)': Foo
|
||||
109..110 '0': usize
|
||||
126..134 'Self(s,)': Foo
|
||||
131..132 's': usize
|
||||
137..140 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
137..140 'Foo': fn Foo(usize) -> Foo
|
||||
137..144 'Foo(0,)': Foo
|
||||
141..142 '0': usize
|
||||
"#]],
|
||||
@ -933,7 +933,7 @@ fn foo(foo: Foo) {
|
||||
48..51 'foo': Foo
|
||||
62..84 'const ... 32) }': Foo
|
||||
68..84 '{ Foo(... 32) }': Foo
|
||||
70..73 'Foo': extern "rust-call" Foo(usize) -> Foo
|
||||
70..73 'Foo': fn Foo(usize) -> Foo
|
||||
70..82 'Foo(15 + 32)': Foo
|
||||
74..76 '15': usize
|
||||
74..81 '15 + 32': usize
|
||||
|
@ -645,7 +645,7 @@ fn issue_4953() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
58..72 '{ Self(0i64) }': Foo
|
||||
60..64 'Self': extern "rust-call" Foo(i64) -> Foo
|
||||
60..64 'Self': fn Foo(i64) -> Foo
|
||||
60..70 'Self(0i64)': Foo
|
||||
65..69 '0i64': i64
|
||||
"#]],
|
||||
@ -659,7 +659,7 @@ fn issue_4953() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
64..78 '{ Self(0i64) }': Foo<i64>
|
||||
66..70 'Self': extern "rust-call" Foo<i64>(i64) -> Foo<i64>
|
||||
66..70 'Self': fn Foo<i64>(i64) -> Foo<i64>
|
||||
66..76 'Self(0i64)': Foo<i64>
|
||||
71..75 '0i64': i64
|
||||
"#]],
|
||||
@ -859,7 +859,7 @@ fn main() {
|
||||
94..96 '{}': ()
|
||||
109..160 '{ ...10); }': ()
|
||||
119..120 's': S<i32>
|
||||
123..124 'S': extern "rust-call" S<i32>() -> S<i32>
|
||||
123..124 'S': fn S<i32>() -> S<i32>
|
||||
123..126 'S()': S<i32>
|
||||
132..133 's': S<i32>
|
||||
132..144 's.g(|_x| {})': ()
|
||||
@ -1616,7 +1616,7 @@ fn main() {
|
||||
37..48 'S(.., a, b)': S
|
||||
43..44 'a': usize
|
||||
46..47 'b': {unknown}
|
||||
51..52 'S': extern "rust-call" S(usize) -> S
|
||||
51..52 'S': fn S(usize) -> S
|
||||
51..55 'S(1)': S
|
||||
53..54 '1': usize
|
||||
65..75 '(.., a, b)': (i32, {unknown})
|
||||
|
@ -236,14 +236,14 @@ fn test() {
|
||||
expect![[r#"
|
||||
71..153 '{ ...a.c; }': ()
|
||||
81..82 'c': C
|
||||
85..86 'C': extern "rust-call" C(usize) -> C
|
||||
85..86 'C': fn C(usize) -> C
|
||||
85..89 'C(1)': C
|
||||
87..88 '1': usize
|
||||
95..96 'B': B
|
||||
106..107 'a': A
|
||||
113..132 'A { b:...C(1) }': A
|
||||
120..121 'B': B
|
||||
126..127 'C': extern "rust-call" C(usize) -> C
|
||||
126..127 'C': fn C(usize) -> C
|
||||
126..130 'C(1)': C
|
||||
128..129 '1': usize
|
||||
138..139 'a': A
|
||||
@ -629,12 +629,12 @@ impl E {
|
||||
86..107 '{ ... }': ()
|
||||
96..100 'Self': S1
|
||||
134..158 '{ ... }': ()
|
||||
144..148 'Self': extern "rust-call" S2(isize) -> S2
|
||||
144..148 'Self': fn S2(isize) -> S2
|
||||
144..151 'Self(1)': S2
|
||||
149..150 '1': isize
|
||||
184..230 '{ ... }': ()
|
||||
194..202 'Self::V1': E
|
||||
212..220 'Self::V2': extern "rust-call" V2(u32) -> E
|
||||
212..220 'Self::V2': fn V2(u32) -> E
|
||||
212..223 'Self::V2(1)': E
|
||||
221..222 '1': u32
|
||||
"#]],
|
||||
@ -860,11 +860,11 @@ fn test() {
|
||||
256..277 'A::foo...42))))': &'? i32
|
||||
263..276 '&&B(B(A(42)))': &'? &'? B<B<A<i32>>>
|
||||
264..276 '&B(B(A(42)))': &'? B<B<A<i32>>>
|
||||
265..266 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
265..266 'B': fn B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
265..276 'B(B(A(42)))': B<B<A<i32>>>
|
||||
267..268 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
267..268 'B': fn B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
267..275 'B(A(42))': B<A<i32>>
|
||||
269..270 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
269..270 'A': fn A<i32>(i32) -> A<i32>
|
||||
269..274 'A(42)': A<i32>
|
||||
271..273 '42': i32
|
||||
"#]],
|
||||
@ -914,16 +914,16 @@ fn test(a: A<i32>) {
|
||||
253..254 'a': A<i32>
|
||||
264..310 '{ ...))); }': ()
|
||||
274..275 't': &'? i32
|
||||
278..279 'A': extern "rust-call" A<i32>(*mut i32) -> A<i32>
|
||||
278..279 'A': fn A<i32>(*mut i32) -> A<i32>
|
||||
278..292 'A(0 as *mut _)': A<i32>
|
||||
278..307 'A(0 as...B(a)))': &'? i32
|
||||
280..281 '0': usize
|
||||
280..291 '0 as *mut _': *mut i32
|
||||
297..306 '&&B(B(a))': &'? &'? B<B<A<i32>>>
|
||||
298..306 '&B(B(a))': &'? B<B<A<i32>>>
|
||||
299..300 'B': extern "rust-call" B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
299..300 'B': fn B<B<A<i32>>>(B<A<i32>>) -> B<B<A<i32>>>
|
||||
299..306 'B(B(a))': B<B<A<i32>>>
|
||||
301..302 'B': extern "rust-call" B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
301..302 'B': fn B<A<i32>>(A<i32>) -> B<A<i32>>
|
||||
301..305 'B(a)': B<A<i32>>
|
||||
303..304 'a': A<i32>
|
||||
"#]],
|
||||
@ -1277,16 +1277,16 @@ fn infer_tuple_struct_generics() {
|
||||
"#,
|
||||
expect![[r#"
|
||||
75..183 '{ ...one; }': ()
|
||||
81..82 'A': extern "rust-call" A<i32>(i32) -> A<i32>
|
||||
81..82 'A': fn A<i32>(i32) -> A<i32>
|
||||
81..86 'A(42)': A<i32>
|
||||
83..85 '42': i32
|
||||
92..93 'A': extern "rust-call" A<u128>(u128) -> A<u128>
|
||||
92..93 'A': fn A<u128>(u128) -> A<u128>
|
||||
92..101 'A(42u128)': A<u128>
|
||||
94..100 '42u128': u128
|
||||
107..111 'Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
107..111 'Some': fn Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
107..116 'Some("x")': Option<&'static str>
|
||||
112..115 '"x"': &'static str
|
||||
122..134 'Option::Some': extern "rust-call" Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
122..134 'Option::Some': fn Some<&'static str>(&'static str) -> Option<&'static str>
|
||||
122..139 'Option...e("x")': Option<&'static str>
|
||||
135..138 '"x"': &'static str
|
||||
145..149 'None': Option<{unknown}>
|
||||
@ -1572,7 +1572,7 @@ fn infer_type_alias() {
|
||||
204..207 'z.y': i8
|
||||
298..362 '{ ... &e; }': ()
|
||||
308..309 'e': Enum
|
||||
312..325 'm::Alias::Foo': extern "rust-call" Foo(u8) -> Enum
|
||||
312..325 'm::Alias::Foo': fn Foo(u8) -> Enum
|
||||
312..328 'm::Ali...Foo(0)': Enum
|
||||
326..327 '0': u8
|
||||
338..354 'm::Ali...Foo(x)': Enum
|
||||
@ -2191,10 +2191,10 @@ fn main() {
|
||||
103..231 '{ ... }); }': ()
|
||||
109..161 'async ... }': impl Future<Output = Result<(), ()>>
|
||||
125..139 'return Err(())': !
|
||||
132..135 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
|
||||
132..135 'Err': fn Err<(), ()>(()) -> Result<(), ()>
|
||||
132..139 'Err(())': Result<(), ()>
|
||||
136..138 '()': ()
|
||||
149..151 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
|
||||
149..151 'Ok': fn Ok<(), ()>(()) -> Result<(), ()>
|
||||
149..155 'Ok(())': Result<(), ()>
|
||||
152..154 '()': ()
|
||||
167..171 'test': fn test<(), (), impl FnMut() -> impl Future<Output = Result<(), ()>>, impl Future<Output = Result<(), ()>>>(impl FnMut() -> impl Future<Output = Result<(), ()>>)
|
||||
@ -2202,10 +2202,10 @@ fn main() {
|
||||
172..227 '|| asy... }': impl FnMut() -> impl Future<Output = Result<(), ()>>
|
||||
175..227 'async ... }': impl Future<Output = Result<(), ()>>
|
||||
191..205 'return Err(())': !
|
||||
198..201 'Err': extern "rust-call" Err<(), ()>(()) -> Result<(), ()>
|
||||
198..201 'Err': fn Err<(), ()>(()) -> Result<(), ()>
|
||||
198..205 'Err(())': Result<(), ()>
|
||||
202..204 '()': ()
|
||||
215..217 'Ok': extern "rust-call" Ok<(), ()>(()) -> Result<(), ()>
|
||||
215..217 'Ok': fn Ok<(), ()>(()) -> Result<(), ()>
|
||||
215..221 'Ok(())': Result<(), ()>
|
||||
218..220 '()': ()
|
||||
"#]],
|
||||
@ -2234,7 +2234,7 @@ fn infer_generic_from_later_assignment() {
|
||||
94..127 '{ ... }': ()
|
||||
104..107 'end': Option<bool>
|
||||
104..120 'end = ...(true)': ()
|
||||
110..114 'Some': extern "rust-call" Some<bool>(bool) -> Option<bool>
|
||||
110..114 'Some': fn Some<bool>(bool) -> Option<bool>
|
||||
110..120 'Some(true)': Option<bool>
|
||||
115..119 'true': bool
|
||||
"#]],
|
||||
@ -2269,7 +2269,7 @@ fn infer_loop_break_with_val() {
|
||||
111..121 'break None': !
|
||||
117..121 'None': Option<bool>
|
||||
142..158 'break ...(true)': !
|
||||
148..152 'Some': extern "rust-call" Some<bool>(bool) -> Option<bool>
|
||||
148..152 'Some': fn Some<bool>(bool) -> Option<bool>
|
||||
148..158 'Some(true)': Option<bool>
|
||||
153..157 'true': bool
|
||||
"#]],
|
||||
@ -2516,7 +2516,7 @@ fn generic_default_in_struct_literal() {
|
||||
254..281 'OtherT...1i32 }': OtherThing<i32>
|
||||
275..279 '1i32': i32
|
||||
291..292 'b': OtherThing<i32>
|
||||
295..310 'OtherThing::Two': extern "rust-call" Two<i32>(i32) -> OtherThing<i32>
|
||||
295..310 'OtherThing::Two': fn Two<i32>(i32) -> OtherThing<i32>
|
||||
295..316 'OtherT...(1i32)': OtherThing<i32>
|
||||
311..315 '1i32': i32
|
||||
"#]],
|
||||
@ -3028,7 +3028,7 @@ fn f() {
|
||||
expect![[r#"
|
||||
72..166 '{ ... } }': ()
|
||||
78..164 'match ... }': ()
|
||||
84..92 'Foo::Bar': extern "rust-call" Bar(i32) -> Foo
|
||||
84..92 'Foo::Bar': fn Bar(i32) -> Foo
|
||||
84..95 'Foo::Bar(3)': Foo
|
||||
93..94 '3': i32
|
||||
106..119 'Qux::Bar(bar)': Foo
|
||||
@ -3087,9 +3087,9 @@ fn main() {
|
||||
322..324 '{}': Foo<T>
|
||||
338..559 '{ ...r(); }': ()
|
||||
348..353 'boxed': Box<Foo<i32>>
|
||||
356..359 'Box': extern "rust-call" Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
|
||||
356..359 'Box': fn Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>
|
||||
356..371 'Box(Foo(0_i32))': Box<Foo<i32>>
|
||||
360..363 'Foo': extern "rust-call" Foo<i32>(i32) -> Foo<i32>
|
||||
360..363 'Foo': fn Foo<i32>(i32) -> Foo<i32>
|
||||
360..370 'Foo(0_i32)': Foo<i32>
|
||||
364..369 '0_i32': i32
|
||||
382..386 'bad1': &'? i32
|
||||
|
@ -523,7 +523,7 @@ fn test() -> u64 {
|
||||
expect![[r#"
|
||||
37..86 '{ ... a.1 }': u64
|
||||
47..48 'a': S
|
||||
51..52 'S': extern "rust-call" S(i32, u64) -> S
|
||||
51..52 'S': fn S(i32, u64) -> S
|
||||
51..58 'S(4, 6)': S
|
||||
53..54 '4': i32
|
||||
56..57 '6': u64
|
||||
@ -549,7 +549,7 @@ fn test() -> u64 {
|
||||
expect![[r#"
|
||||
43..108 '{ ...0(2) }': u64
|
||||
53..54 'a': S
|
||||
57..58 'S': extern "rust-call" S(fn(u32) -> u64) -> S
|
||||
57..58 'S': fn S(fn(u32) -> u64) -> S
|
||||
57..74 'S(|i| ...s u64)': S
|
||||
59..73 '|i| 2*i as u64': impl Fn(u32) -> u64
|
||||
60..61 'i': u32
|
||||
@ -1027,7 +1027,7 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
|
||||
201..202 'x': impl Trait<u64>
|
||||
208..209 'y': &'? impl Trait<u32>
|
||||
219..220 'z': S<u16>
|
||||
223..224 'S': extern "rust-call" S<u16>(u16) -> S<u16>
|
||||
223..224 'S': fn S<u16>(u16) -> S<u16>
|
||||
223..227 'S(1)': S<u16>
|
||||
225..226 '1': u16
|
||||
233..236 'bar': fn bar(S<u16>)
|
||||
@ -1269,10 +1269,10 @@ fn bar() {
|
||||
226..229 'foo': fn foo<i32>([R<(), i32>; 2]) -> i32
|
||||
226..250 'foo([R...B(7)])': i32
|
||||
230..249 '[R::A(...:B(7)]': [R<(), i32>; 2]
|
||||
231..235 'R::A': extern "rust-call" A<(), i32>(()) -> R<(), i32>
|
||||
231..235 'R::A': fn A<(), i32>(()) -> R<(), i32>
|
||||
231..239 'R::A(())': R<(), i32>
|
||||
236..238 '()': ()
|
||||
241..245 'R::B': extern "rust-call" B<(), i32>(i32) -> R<(), i32>
|
||||
241..245 'R::B': fn B<(), i32>(i32) -> R<(), i32>
|
||||
241..248 'R::B(7)': R<(), i32>
|
||||
246..247 '7': i32
|
||||
"#]],
|
||||
@ -1421,7 +1421,7 @@ fn foo<const C: u8, T>() -> (impl FnOnce(&str, T), impl Trait<u8>) {
|
||||
142..147 'input': &'? str
|
||||
149..150 't': T
|
||||
152..154 '{}': ()
|
||||
156..159 'Bar': extern "rust-call" Bar<u8>(u8) -> Bar<u8>
|
||||
156..159 'Bar': fn Bar<u8>(u8) -> Bar<u8>
|
||||
156..162 'Bar(C)': Bar<u8>
|
||||
160..161 'C': u8
|
||||
"#]],
|
||||
@ -2046,7 +2046,7 @@ fn test() {
|
||||
118..120 '{}': ()
|
||||
136..255 '{ ... 1); }': ()
|
||||
146..147 'x': Option<u32>
|
||||
150..162 'Option::Some': extern "rust-call" Some<u32>(u32) -> Option<u32>
|
||||
150..162 'Option::Some': fn Some<u32>(u32) -> Option<u32>
|
||||
150..168 'Option...(1u32)': Option<u32>
|
||||
163..167 '1u32': u32
|
||||
174..175 'x': Option<u32>
|
||||
@ -2602,7 +2602,7 @@ fn test() -> impl Trait<i32> {
|
||||
178..180 '{}': ()
|
||||
213..309 '{ ...t()) }': S<i32>
|
||||
223..225 's1': S<u32>
|
||||
228..229 'S': extern "rust-call" S<u32>(u32) -> S<u32>
|
||||
228..229 'S': fn S<u32>(u32) -> S<u32>
|
||||
228..240 'S(default())': S<u32>
|
||||
230..237 'default': fn default<u32>() -> u32
|
||||
230..239 'default()': u32
|
||||
@ -2612,11 +2612,11 @@ fn test() -> impl Trait<i32> {
|
||||
263..264 'x': i32
|
||||
272..275 'bar': fn bar<i32>(S<i32>) -> i32
|
||||
272..289 'bar(S(...lt()))': i32
|
||||
276..277 'S': extern "rust-call" S<i32>(i32) -> S<i32>
|
||||
276..277 'S': fn S<i32>(i32) -> S<i32>
|
||||
276..288 'S(default())': S<i32>
|
||||
278..285 'default': fn default<i32>() -> i32
|
||||
278..287 'default()': i32
|
||||
295..296 'S': extern "rust-call" S<i32>(i32) -> S<i32>
|
||||
295..296 'S': fn S<i32>(i32) -> S<i32>
|
||||
295..307 'S(default())': S<i32>
|
||||
297..304 'default': fn default<i32>() -> i32
|
||||
297..306 'default()': i32
|
||||
@ -2846,7 +2846,7 @@ fn main() {
|
||||
1036..1041 'x > 0': bool
|
||||
1040..1041 '0': i32
|
||||
1042..1060 '{ Some...u32) }': Option<u32>
|
||||
1044..1048 'Some': extern "rust-call" Some<u32>(u32) -> Option<u32>
|
||||
1044..1048 'Some': fn Some<u32>(u32) -> Option<u32>
|
||||
1044..1058 'Some(x as u32)': Option<u32>
|
||||
1049..1050 'x': i32
|
||||
1049..1057 'x as u32': u32
|
||||
@ -2982,9 +2982,9 @@ fn test() {
|
||||
175..185 'foo.test()': bool
|
||||
191..194 'bar': fn bar<{unknown}>({unknown}) -> {unknown}
|
||||
191..201 'bar.test()': bool
|
||||
207..213 'Struct': extern "rust-call" Struct(usize) -> Struct
|
||||
207..213 'Struct': fn Struct(usize) -> Struct
|
||||
207..220 'Struct.test()': bool
|
||||
226..239 'Enum::Variant': extern "rust-call" Variant(usize) -> Enum
|
||||
226..239 'Enum::Variant': fn Variant(usize) -> Enum
|
||||
226..246 'Enum::...test()': bool
|
||||
"#]],
|
||||
);
|
||||
@ -3563,12 +3563,12 @@ fn main(){
|
||||
95..99 'self': Wrapper
|
||||
101..104 'rhs': u32
|
||||
122..150 '{ ... }': Wrapper
|
||||
132..139 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
|
||||
132..139 'Wrapper': fn Wrapper(u32) -> Wrapper
|
||||
132..144 'Wrapper(rhs)': Wrapper
|
||||
140..143 'rhs': u32
|
||||
162..248 '{ ...um; }': ()
|
||||
172..179 'wrapped': Wrapper
|
||||
182..189 'Wrapper': extern "rust-call" Wrapper(u32) -> Wrapper
|
||||
182..189 'Wrapper': fn Wrapper(u32) -> Wrapper
|
||||
182..193 'Wrapper(10)': Wrapper
|
||||
190..192 '10': u32
|
||||
203..206 'num': u32
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Applies changes to the IDE state transactionally.
|
||||
|
||||
use base_db::{
|
||||
salsa::{
|
||||
ra_salsa::{
|
||||
debug::{DebugQueryTable, TableEntry},
|
||||
Database, Durability, Query, QueryTable,
|
||||
},
|
||||
|
@ -48,7 +48,7 @@ pub use hir::ChangeWithProcMacros;
|
||||
use std::{fmt, mem::ManuallyDrop};
|
||||
|
||||
use base_db::{
|
||||
salsa::{self, Durability},
|
||||
ra_salsa::{self, Durability},
|
||||
AnchoredPath, CrateId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast,
|
||||
DEFAULT_FILE_TEXT_LRU_CAP,
|
||||
};
|
||||
@ -74,7 +74,7 @@ pub type FxIndexMap<K, V> =
|
||||
pub type FilePosition = FilePositionWrapper<FileId>;
|
||||
pub type FileRange = FileRangeWrapper<FileId>;
|
||||
|
||||
#[salsa::database(
|
||||
#[ra_salsa::database(
|
||||
base_db::SourceRootDatabaseStorage,
|
||||
base_db::SourceDatabaseStorage,
|
||||
hir::db::ExpandDatabaseStorage,
|
||||
@ -89,7 +89,7 @@ pub struct RootDatabase {
|
||||
// `&RootDatabase -> &dyn OtherDatabase` cast will instantiate its drop glue in the vtable,
|
||||
// which duplicates `Weak::drop` and `Arc::drop` tens of thousands of times, which makes
|
||||
// compile times of all `ide_*` and downstream crates suffer greatly.
|
||||
storage: ManuallyDrop<salsa::Storage<RootDatabase>>,
|
||||
storage: ManuallyDrop<ra_salsa::Storage<RootDatabase>>,
|
||||
}
|
||||
|
||||
impl Drop for RootDatabase {
|
||||
@ -134,7 +134,7 @@ impl FileLoader for RootDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::Database for RootDatabase {}
|
||||
impl ra_salsa::Database for RootDatabase {}
|
||||
|
||||
impl Default for RootDatabase {
|
||||
fn default() -> RootDatabase {
|
||||
@ -144,7 +144,7 @@ impl Default for RootDatabase {
|
||||
|
||||
impl RootDatabase {
|
||||
pub fn new(lru_capacity: Option<u16>) -> RootDatabase {
|
||||
let mut db = RootDatabase { storage: ManuallyDrop::new(salsa::Storage::default()) };
|
||||
let mut db = RootDatabase { storage: ManuallyDrop::new(ra_salsa::Storage::default()) };
|
||||
db.set_crate_graph_with_durability(Default::default(), Durability::HIGH);
|
||||
db.set_proc_macros_with_durability(Default::default(), Durability::HIGH);
|
||||
db.set_local_roots_with_durability(Default::default(), Durability::HIGH);
|
||||
@ -195,13 +195,15 @@ impl RootDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
impl salsa::ParallelDatabase for RootDatabase {
|
||||
fn snapshot(&self) -> salsa::Snapshot<RootDatabase> {
|
||||
salsa::Snapshot::new(RootDatabase { storage: ManuallyDrop::new(self.storage.snapshot()) })
|
||||
impl ra_salsa::ParallelDatabase for RootDatabase {
|
||||
fn snapshot(&self) -> ra_salsa::Snapshot<RootDatabase> {
|
||||
ra_salsa::Snapshot::new(RootDatabase {
|
||||
storage: ManuallyDrop::new(self.storage.snapshot()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[salsa::query_group(LineIndexDatabaseStorage)]
|
||||
#[ra_salsa::query_group(LineIndexDatabaseStorage)]
|
||||
pub trait LineIndexDatabase: base_db::SourceDatabase {
|
||||
fn line_index(&self, file_id: FileId) -> Arc<LineIndex>;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ use hir::db::DefDatabase;
|
||||
|
||||
use crate::{
|
||||
base_db::{
|
||||
salsa::{Database, ParallelDatabase, Snapshot},
|
||||
ra_salsa::{Database, ParallelDatabase, Snapshot},
|
||||
Cancelled, CrateId, SourceDatabase, SourceRootDatabase,
|
||||
},
|
||||
symbol_index::SymbolsDatabase,
|
||||
|
@ -7,7 +7,7 @@
|
||||
use std::mem;
|
||||
use std::{cell::LazyCell, cmp::Reverse};
|
||||
|
||||
use base_db::{salsa::Database, SourceDatabase, SourceRootDatabase};
|
||||
use base_db::{ra_salsa::Database, SourceDatabase, SourceRootDatabase};
|
||||
use either::Either;
|
||||
use hir::{
|
||||
sym, Adt, AsAssocItem, DefWithBody, FileRange, FileRangeWrapper, HasAttrs, HasContainer,
|
||||
|
@ -28,7 +28,7 @@ use std::{
|
||||
};
|
||||
|
||||
use base_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
ra_salsa::{self, ParallelDatabase},
|
||||
SourceRootDatabase, SourceRootId, Upcast,
|
||||
};
|
||||
use fst::{raw::IndexedValue, Automaton, Streamer};
|
||||
@ -99,7 +99,7 @@ impl Query {
|
||||
}
|
||||
}
|
||||
|
||||
#[salsa::query_group(SymbolsDatabaseStorage)]
|
||||
#[ra_salsa::query_group(SymbolsDatabaseStorage)]
|
||||
pub trait SymbolsDatabase: HirDatabase + SourceRootDatabase + Upcast<dyn HirDatabase> {
|
||||
/// The symbol index for a given module. These modules should only be in source roots that
|
||||
/// are inside local_roots.
|
||||
@ -108,18 +108,18 @@ pub trait SymbolsDatabase: HirDatabase + SourceRootDatabase + Upcast<dyn HirData
|
||||
/// The symbol index for a given source root within library_roots.
|
||||
fn library_symbols(&self, source_root_id: SourceRootId) -> Arc<SymbolIndex>;
|
||||
|
||||
#[salsa::transparent]
|
||||
#[ra_salsa::transparent]
|
||||
/// The symbol indices of modules that make up a given crate.
|
||||
fn crate_symbols(&self, krate: Crate) -> Box<[Arc<SymbolIndex>]>;
|
||||
|
||||
/// The set of "local" (that is, from the current workspace) roots.
|
||||
/// Files in local roots are assumed to change frequently.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn local_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
|
||||
|
||||
/// The set of roots for crates.io libraries.
|
||||
/// Files in libraries are assumed to never change.
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn library_roots(&self) -> Arc<FxHashSet<SourceRootId>>;
|
||||
}
|
||||
|
||||
@ -155,13 +155,13 @@ pub fn crate_symbols(db: &dyn SymbolsDatabase, krate: Crate) -> Box<[Arc<SymbolI
|
||||
|
||||
/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
|
||||
struct Snap<DB>(DB);
|
||||
impl<DB: ParallelDatabase> Snap<salsa::Snapshot<DB>> {
|
||||
impl<DB: ParallelDatabase> Snap<ra_salsa::Snapshot<DB>> {
|
||||
fn new(db: &DB) -> Self {
|
||||
Self(db.snapshot())
|
||||
}
|
||||
}
|
||||
impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
|
||||
fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
|
||||
impl<DB: ParallelDatabase> Clone for Snap<ra_salsa::Snapshot<DB>> {
|
||||
fn clone(&self) -> Snap<ra_salsa::Snapshot<DB>> {
|
||||
Snap(self.0.snapshot())
|
||||
}
|
||||
}
|
||||
|
@ -95,10 +95,10 @@ pub(crate) fn invalid_cast(ctx: &DiagnosticsContext<'_>, d: &hir::InvalidCast) -
|
||||
DiagnosticCode::RustcHardError("E0605"),
|
||||
format_ty!(ctx, "non-primitive cast: `{}` as `{}`", d.expr_ty, d.cast_ty),
|
||||
),
|
||||
CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => (
|
||||
DiagnosticCode::RustcHardError("E0641"),
|
||||
"cannot cast to a pointer of an unknown kind".to_owned(),
|
||||
),
|
||||
// CastError::UnknownCastPtrKind | CastError::UnknownExprPtrKind => (
|
||||
// DiagnosticCode::RustcHardError("E0641"),
|
||||
// "cannot cast to a pointer of an unknown kind".to_owned(),
|
||||
// ),
|
||||
};
|
||||
Diagnostic::new(code, message, display_range)
|
||||
}
|
||||
@ -457,20 +457,20 @@ fn foo<T: ?Sized>() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn order_dependent_cast_inference() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: sized
|
||||
fn main() {
|
||||
let x = &"hello";
|
||||
let mut y = 0 as *const _;
|
||||
//^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind
|
||||
y = x as *const _;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
// #[test]
|
||||
// fn order_dependent_cast_inference() {
|
||||
// check_diagnostics(
|
||||
// r#"
|
||||
// //- minicore: sized
|
||||
// fn main() {
|
||||
// let x = &"hello";
|
||||
// let mut y = 0 as *const _;
|
||||
// //^^^^^^^^^^^^^ error: cannot cast to a pointer of an unknown kind
|
||||
// y = x as *const _;
|
||||
// }
|
||||
// "#,
|
||||
// );
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn ptr_to_ptr_different_regions() {
|
||||
@ -1107,6 +1107,24 @@ where
|
||||
r#"
|
||||
fn foo() {
|
||||
0 as char;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cast_isize_to_infer_pointer() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: coerce_unsized
|
||||
struct Foo {}
|
||||
|
||||
struct Wrap<'a>(&'a mut Foo);
|
||||
|
||||
fn main() {
|
||||
let lparam: isize = 0;
|
||||
|
||||
let _wrap = Wrap(unsafe { &mut *(lparam as *mut _) });
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -1255,6 +1255,31 @@ pub unsafe fn foo(a: *mut A) {
|
||||
//^^^^^ 💡 warn: variable does not need to be mutable
|
||||
let _ = b();
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_15799() {
|
||||
check_diagnostics(
|
||||
r#"
|
||||
//- minicore: deref_mut
|
||||
struct WrapPtr(*mut u32);
|
||||
|
||||
impl core::ops::Deref for WrapPtr {
|
||||
type Target = *mut u32;
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut x = 0u32;
|
||||
let wrap = WrapPtr(&mut x);
|
||||
unsafe {
|
||||
**wrap = 6;
|
||||
}
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ fn add_missing_ok_or_some(
|
||||
if d.actual.is_unit() {
|
||||
if let Expr::BlockExpr(block) = &expr {
|
||||
if block.tail_expr().is_none() {
|
||||
// Fix for forms like `fn foo() -> Result<(), String> {}`
|
||||
let mut builder = TextEdit::builder();
|
||||
let block_indent = block.indent_level();
|
||||
|
||||
@ -156,6 +157,20 @@ fn add_missing_ok_or_some(
|
||||
acc.push(fix("insert_wrapped_unit", &name, source_change, expr_range));
|
||||
}
|
||||
return Some(());
|
||||
} else if let Expr::ReturnExpr(ret_expr) = &expr {
|
||||
// Fix for forms like `fn foo() -> Result<(), String> { return; }`
|
||||
if ret_expr.expr().is_none() {
|
||||
let mut builder = TextEdit::builder();
|
||||
builder
|
||||
.insert(ret_expr.syntax().text_range().end(), format!(" {variant_name}(())"));
|
||||
let source_change = SourceChange::from_text_edit(
|
||||
expr_ptr.file_id.original_file(ctx.sema.db),
|
||||
builder.finish(),
|
||||
);
|
||||
let name = format!("Insert {variant_name}(()) as the return value");
|
||||
acc.push(fix("insert_wrapped_unit", &name, source_change, expr_range));
|
||||
}
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
|
||||
@ -603,6 +618,29 @@ fn foo() -> Result<(), ()> {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_wrapped_unit_as_return_expr() {
|
||||
check_fix(
|
||||
r#"
|
||||
//- minicore: result
|
||||
fn foo(b: bool) -> Result<(), String> {
|
||||
if b {
|
||||
return$0;
|
||||
}
|
||||
|
||||
Err("oh dear".to_owned())
|
||||
}"#,
|
||||
r#"
|
||||
fn foo(b: bool) -> Result<(), String> {
|
||||
if b {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err("oh dear".to_owned())
|
||||
}"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_in_const_and_static() {
|
||||
check_fix(
|
||||
|
@ -1,7 +1,7 @@
|
||||
use expect_test::{expect, Expect};
|
||||
use hir::{FilePosition, FileRange};
|
||||
use ide_db::{
|
||||
base_db::{salsa::Durability, SourceDatabase},
|
||||
base_db::{ra_salsa::Durability, SourceDatabase},
|
||||
EditionedFileId, FxHashSet,
|
||||
};
|
||||
use test_utils::RangeOrOffset;
|
||||
|
@ -19,6 +19,12 @@ pub struct CallItem {
|
||||
pub ranges: Vec<FileRange>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct CallHierarchyConfig {
|
||||
/// Whether to exclude tests from the call hierarchy
|
||||
pub exclude_tests: bool,
|
||||
}
|
||||
|
||||
pub(crate) fn call_hierarchy(
|
||||
db: &RootDatabase,
|
||||
position: FilePosition,
|
||||
@ -28,6 +34,7 @@ pub(crate) fn call_hierarchy(
|
||||
|
||||
pub(crate) fn incoming_calls(
|
||||
db: &RootDatabase,
|
||||
CallHierarchyConfig { exclude_tests }: CallHierarchyConfig,
|
||||
FilePosition { file_id, offset }: FilePosition,
|
||||
) -> Option<Vec<CallItem>> {
|
||||
let sema = &Semantics::new(db);
|
||||
@ -56,11 +63,18 @@ pub(crate) fn incoming_calls(
|
||||
references.iter().filter_map(|FileReference { name, .. }| name.as_name_ref());
|
||||
for name in references {
|
||||
// This target is the containing function
|
||||
let nav = sema.ancestors_with_macros(name.syntax().clone()).find_map(|node| {
|
||||
let def_nav = sema.ancestors_with_macros(name.syntax().clone()).find_map(|node| {
|
||||
let def = ast::Fn::cast(node).and_then(|fn_| sema.to_def(&fn_))?;
|
||||
def.try_to_nav(sema.db)
|
||||
// We should return def before check if it is a test, so that we
|
||||
// will not continue to search for outer fn in nested fns
|
||||
def.try_to_nav(sema.db).map(|nav| (def, nav))
|
||||
});
|
||||
if let Some(nav) = nav {
|
||||
|
||||
if let Some((def, nav)) = def_nav {
|
||||
if exclude_tests && def.is_test(db) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let range = sema.original_range(name.syntax());
|
||||
calls.add(nav.call_site, range.into());
|
||||
if let Some(other) = nav.def_site {
|
||||
@ -75,6 +89,7 @@ pub(crate) fn incoming_calls(
|
||||
|
||||
pub(crate) fn outgoing_calls(
|
||||
db: &RootDatabase,
|
||||
CallHierarchyConfig { exclude_tests }: CallHierarchyConfig,
|
||||
FilePosition { file_id, offset }: FilePosition,
|
||||
) -> Option<Vec<CallItem>> {
|
||||
let sema = Semantics::new(db);
|
||||
@ -103,7 +118,12 @@ pub(crate) fn outgoing_calls(
|
||||
let expr = call.expr()?;
|
||||
let callable = sema.type_of_expr(&expr)?.original.as_callable(db)?;
|
||||
match callable.kind() {
|
||||
hir::CallableKind::Function(it) => it.try_to_nav(db),
|
||||
hir::CallableKind::Function(it) => {
|
||||
if exclude_tests && it.is_test(db) {
|
||||
return None;
|
||||
}
|
||||
it.try_to_nav(db)
|
||||
}
|
||||
hir::CallableKind::TupleEnumVariant(it) => it.try_to_nav(db),
|
||||
hir::CallableKind::TupleStruct(it) => it.try_to_nav(db),
|
||||
_ => None,
|
||||
@ -112,6 +132,9 @@ pub(crate) fn outgoing_calls(
|
||||
}
|
||||
ast::CallableExpr::MethodCall(expr) => {
|
||||
let function = sema.resolve_method_call(&expr)?;
|
||||
if exclude_tests && function.is_test(db) {
|
||||
return None;
|
||||
}
|
||||
function
|
||||
.try_to_nav(db)
|
||||
.zip(Some(sema.original_range(expr.name_ref()?.syntax())))
|
||||
@ -149,6 +172,7 @@ mod tests {
|
||||
use crate::fixture;
|
||||
|
||||
fn check_hierarchy(
|
||||
exclude_tests: bool,
|
||||
ra_fixture: &str,
|
||||
expected_nav: Expect,
|
||||
expected_incoming: Expect,
|
||||
@ -172,18 +196,21 @@ mod tests {
|
||||
let nav = navs.pop().unwrap();
|
||||
expected_nav.assert_eq(&nav.debug_render());
|
||||
|
||||
let config = crate::CallHierarchyConfig { exclude_tests };
|
||||
|
||||
let item_pos =
|
||||
FilePosition { file_id: nav.file_id, offset: nav.focus_or_full_range().start() };
|
||||
let incoming_calls = analysis.incoming_calls(item_pos).unwrap().unwrap();
|
||||
let incoming_calls = analysis.incoming_calls(config, item_pos).unwrap().unwrap();
|
||||
expected_incoming.assert_eq(&incoming_calls.into_iter().map(debug_render).join("\n"));
|
||||
|
||||
let outgoing_calls = analysis.outgoing_calls(item_pos).unwrap().unwrap();
|
||||
let outgoing_calls = analysis.outgoing_calls(config, item_pos).unwrap().unwrap();
|
||||
expected_outgoing.assert_eq(&outgoing_calls.into_iter().map(debug_render).join("\n"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_hierarchy_on_ref() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn callee() {}
|
||||
@ -200,6 +227,7 @@ fn caller() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_on_def() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn call$0ee() {}
|
||||
@ -216,6 +244,7 @@ fn caller() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_same_fn() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn callee() {}
|
||||
@ -233,6 +262,7 @@ fn caller() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_different_fn() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn callee() {}
|
||||
@ -255,6 +285,7 @@ fn caller2() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_tests_mod() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs cfg:test
|
||||
fn callee() {}
|
||||
@ -283,6 +314,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_different_files() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
mod foo;
|
||||
@ -304,6 +336,7 @@ pub fn callee() {}
|
||||
#[test]
|
||||
fn test_call_hierarchy_outgoing() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn callee() {}
|
||||
@ -321,6 +354,7 @@ fn call$0er() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_outgoing_in_different_files() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
mod foo;
|
||||
@ -342,6 +376,7 @@ pub fn callee() {}
|
||||
#[test]
|
||||
fn test_call_hierarchy_incoming_outgoing() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
fn caller1() {
|
||||
@ -365,6 +400,7 @@ fn caller3() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_issue_5103() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
fn a() {
|
||||
b()
|
||||
@ -382,6 +418,7 @@ fn main() {
|
||||
);
|
||||
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
fn a() {
|
||||
b$0()
|
||||
@ -402,6 +439,7 @@ fn main() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_incoming() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
@ -423,6 +461,7 @@ fn caller() {
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
@ -448,6 +487,7 @@ fn caller() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_outgoing() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
macro_rules! define {
|
||||
($ident:ident) => {
|
||||
@ -473,6 +513,7 @@ fn caller$0() {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_incoming_different_files() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
@ -498,6 +539,7 @@ macro_rules! call {
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
@ -523,6 +565,7 @@ macro_rules! call {
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
@ -558,6 +601,7 @@ macro_rules! call {
|
||||
#[test]
|
||||
fn test_call_hierarchy_in_macros_outgoing_different_files() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
@ -585,6 +629,7 @@ macro_rules! call {
|
||||
expect![[]],
|
||||
);
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
//- /lib.rs
|
||||
#[macro_use]
|
||||
@ -616,6 +661,7 @@ macro_rules! call {
|
||||
#[test]
|
||||
fn test_trait_method_call_hierarchy() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
trait T1 {
|
||||
fn call$0ee();
|
||||
@ -636,4 +682,64 @@ fn caller() {
|
||||
expect![[]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_call_hierarchy_excluding_tests() {
|
||||
check_hierarchy(
|
||||
false,
|
||||
r#"
|
||||
fn main() {
|
||||
f1();
|
||||
}
|
||||
|
||||
fn f1$0() {
|
||||
f2(); f3();
|
||||
}
|
||||
|
||||
fn f2() {
|
||||
f1(); f3();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f3() {
|
||||
f1(); f2();
|
||||
}
|
||||
"#,
|
||||
expect!["f1 Function FileId(0) 25..52 28..30"],
|
||||
expect![[r#"
|
||||
main Function FileId(0) 0..23 3..7 : FileId(0):16..18
|
||||
f2 Function FileId(0) 54..81 57..59 : FileId(0):68..70
|
||||
f3 Function FileId(0) 83..118 94..96 : FileId(0):105..107"#]],
|
||||
expect![[r#"
|
||||
f2 Function FileId(0) 54..81 57..59 : FileId(0):39..41
|
||||
f3 Function FileId(0) 83..118 94..96 : FileId(0):45..47"#]],
|
||||
);
|
||||
|
||||
check_hierarchy(
|
||||
true,
|
||||
r#"
|
||||
fn main() {
|
||||
f1();
|
||||
}
|
||||
|
||||
fn f1$0() {
|
||||
f2(); f3();
|
||||
}
|
||||
|
||||
fn f2() {
|
||||
f1(); f3();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn f3() {
|
||||
f1(); f2();
|
||||
}
|
||||
"#,
|
||||
expect!["f1 Function FileId(0) 25..52 28..30"],
|
||||
expect![[r#"
|
||||
main Function FileId(0) 0..23 3..7 : FileId(0):16..18
|
||||
f2 Function FileId(0) 54..81 57..59 : FileId(0):68..70"#]],
|
||||
expect!["f2 Function FileId(0) 54..81 57..59 : FileId(0):39..41"],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -281,16 +281,11 @@ fn highlight_references(
|
||||
}
|
||||
}
|
||||
|
||||
// If `file_id` is None,
|
||||
pub(crate) fn highlight_exit_points(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
token: SyntaxToken,
|
||||
) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
|
||||
fn hl(
|
||||
fn hl_exit_points(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
def_token: Option<SyntaxToken>,
|
||||
body: ast::Expr,
|
||||
) -> Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>> {
|
||||
) -> Option<FxHashMap<EditionedFileId, FxHashSet<HighlightedRange>>> {
|
||||
let mut highlights: FxHashMap<EditionedFileId, FxHashSet<_>> = FxHashMap::default();
|
||||
|
||||
let mut push_to_highlights = |file_id, range| {
|
||||
@ -310,9 +305,7 @@ pub(crate) fn highlight_exit_points(
|
||||
let file_id = sema.hir_file_for(expr.syntax());
|
||||
|
||||
let range = match &expr {
|
||||
ast::Expr::TryExpr(try_) => {
|
||||
try_.question_mark_token().map(|token| token.text_range())
|
||||
}
|
||||
ast::Expr::TryExpr(try_) => try_.question_mark_token().map(|token| token.text_range()),
|
||||
ast::Expr::MethodCallExpr(_) | ast::Expr::CallExpr(_) | ast::Expr::MacroExpr(_)
|
||||
if sema.type_of_expr(&expr).map_or(false, |ty| ty.original.is_never()) =>
|
||||
{
|
||||
@ -332,9 +325,7 @@ pub(crate) fn highlight_exit_points(
|
||||
let file_id = sema.hir_file_for(expr.syntax());
|
||||
|
||||
let range = match &expr {
|
||||
ast::Expr::ReturnExpr(expr) => {
|
||||
expr.return_token().map(|token| token.text_range())
|
||||
}
|
||||
ast::Expr::ReturnExpr(expr) => expr.return_token().map(|token| token.text_range()),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
@ -359,21 +350,26 @@ pub(crate) fn highlight_exit_points(
|
||||
});
|
||||
}
|
||||
Some(highlights)
|
||||
}
|
||||
}
|
||||
|
||||
// If `file_id` is None,
|
||||
pub(crate) fn highlight_exit_points(
|
||||
sema: &Semantics<'_, RootDatabase>,
|
||||
token: SyntaxToken,
|
||||
) -> FxHashMap<EditionedFileId, Vec<HighlightedRange>> {
|
||||
let mut res = FxHashMap::default();
|
||||
for def in goto_definition::find_fn_or_blocks(sema, &token) {
|
||||
let new_map = match_ast! {
|
||||
match def {
|
||||
ast::Fn(fn_) => fn_.body().and_then(|body| hl(sema, fn_.fn_token(), body.into())),
|
||||
ast::Fn(fn_) => fn_.body().and_then(|body| hl_exit_points(sema, fn_.fn_token(), body.into())),
|
||||
ast::ClosureExpr(closure) => {
|
||||
let pipe_tok = closure.param_list().and_then(|p| p.pipe_token());
|
||||
closure.body().and_then(|body| hl(sema, pipe_tok, body))
|
||||
closure.body().and_then(|body| hl_exit_points(sema, pipe_tok, body))
|
||||
},
|
||||
ast::BlockExpr(blk) => match blk.modifier() {
|
||||
Some(ast::BlockModifier::Async(t)) => hl(sema, Some(t), blk.into()),
|
||||
Some(ast::BlockModifier::Async(t)) => hl_exit_points(sema, Some(t), blk.into()),
|
||||
Some(ast::BlockModifier::Try(t)) if token.kind() != T![return] => {
|
||||
hl(sema, Some(t), blk.into())
|
||||
hl_exit_points(sema, Some(t), blk.into())
|
||||
},
|
||||
_ => continue,
|
||||
},
|
||||
@ -517,10 +513,23 @@ pub(crate) fn highlight_yield_points(
|
||||
match anc {
|
||||
ast::Fn(fn_) => hl(sema, fn_.async_token(), fn_.body().map(ast::Expr::BlockExpr)),
|
||||
ast::BlockExpr(block_expr) => {
|
||||
if block_expr.async_token().is_none() {
|
||||
let Some(async_token) = block_expr.async_token() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
// Async blocks act similar to closures. So we want to
|
||||
// highlight their exit points too, but only if we are on
|
||||
// the async token.
|
||||
if async_token == token {
|
||||
let exit_points = hl_exit_points(
|
||||
sema,
|
||||
Some(async_token.clone()),
|
||||
block_expr.clone().into(),
|
||||
);
|
||||
merge_map(&mut res, exit_points);
|
||||
}
|
||||
hl(sema, block_expr.async_token(), Some(block_expr.into()))
|
||||
|
||||
hl(sema, Some(async_token), Some(block_expr.into()))
|
||||
},
|
||||
ast::ClosureExpr(closure) => hl(sema, closure.async_token(), closure.body()),
|
||||
_ => continue,
|
||||
@ -876,6 +885,27 @@ pub async$0 fn foo() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hl_exit_points_of_async_blocks() {
|
||||
check(
|
||||
r#"
|
||||
pub fn foo() {
|
||||
let x = async$0 {
|
||||
// ^^^^^
|
||||
0.await;
|
||||
// ^^^^^
|
||||
0?;
|
||||
// ^
|
||||
return 0;
|
||||
// ^^^^^^
|
||||
0
|
||||
// ^
|
||||
};
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hl_let_else_yield_points() {
|
||||
check(
|
||||
@ -925,11 +955,9 @@ async fn foo() {
|
||||
async fn foo() {
|
||||
(async {
|
||||
// ^^^^^
|
||||
(async {
|
||||
0.await
|
||||
}).await$0 }
|
||||
(async { 0.await }).await$0
|
||||
// ^^^^^
|
||||
).await;
|
||||
}).await;
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
@ -8988,3 +8988,33 @@ mod m {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_18238() {
|
||||
check(
|
||||
r#"
|
||||
macro_rules! foo {
|
||||
($name:ident) => {
|
||||
pub static $name = Foo::new(|| {
|
||||
$crate;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
foo!(BAR_$0);
|
||||
"#,
|
||||
expect![[r#"
|
||||
*BAR_*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
pub static BAR_: {error} = Foo::new(||{
|
||||
crate;
|
||||
})
|
||||
```
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -64,7 +64,7 @@ use fetch_crates::CrateInfo;
|
||||
use hir::{sym, ChangeWithProcMacros};
|
||||
use ide_db::{
|
||||
base_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
ra_salsa::{self, ParallelDatabase},
|
||||
CrateOrigin, CrateWorkspaceData, Env, FileLoader, FileSet, SourceDatabase,
|
||||
SourceRootDatabase, VfsPath,
|
||||
},
|
||||
@ -79,7 +79,7 @@ use crate::navigation_target::ToNav;
|
||||
|
||||
pub use crate::{
|
||||
annotations::{Annotation, AnnotationConfig, AnnotationKind, AnnotationLocation},
|
||||
call_hierarchy::CallItem,
|
||||
call_hierarchy::{CallHierarchyConfig, CallItem},
|
||||
expand_macro::ExpandedMacro,
|
||||
file_structure::{StructureNode, StructureNodeKind},
|
||||
folding_ranges::{Fold, FoldKind},
|
||||
@ -218,7 +218,7 @@ impl Default for AnalysisHost {
|
||||
/// `Analysis` are canceled (most method return `Err(Canceled)`).
|
||||
#[derive(Debug)]
|
||||
pub struct Analysis {
|
||||
db: salsa::Snapshot<RootDatabase>,
|
||||
db: ra_salsa::Snapshot<RootDatabase>,
|
||||
}
|
||||
|
||||
// As a general design guideline, `Analysis` API are intended to be independent
|
||||
@ -564,13 +564,21 @@ impl Analysis {
|
||||
}
|
||||
|
||||
/// Computes incoming calls for the given file position.
|
||||
pub fn incoming_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> {
|
||||
self.with_db(|db| call_hierarchy::incoming_calls(db, position))
|
||||
pub fn incoming_calls(
|
||||
&self,
|
||||
config: CallHierarchyConfig,
|
||||
position: FilePosition,
|
||||
) -> Cancellable<Option<Vec<CallItem>>> {
|
||||
self.with_db(|db| call_hierarchy::incoming_calls(db, config, position))
|
||||
}
|
||||
|
||||
/// Computes outgoing calls for the given file position.
|
||||
pub fn outgoing_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> {
|
||||
self.with_db(|db| call_hierarchy::outgoing_calls(db, position))
|
||||
pub fn outgoing_calls(
|
||||
&self,
|
||||
config: CallHierarchyConfig,
|
||||
position: FilePosition,
|
||||
) -> Cancellable<Option<Vec<CallItem>>> {
|
||||
self.with_db(|db| call_hierarchy::outgoing_calls(db, config, position))
|
||||
}
|
||||
|
||||
/// Returns a `mod name;` declaration which created the current module.
|
||||
|
@ -792,6 +792,7 @@ pub(crate) fn orig_range_with_focus_r(
|
||||
.definition_range(db)
|
||||
};
|
||||
|
||||
// FIXME: Also make use of the syntax context to determine which site we are at?
|
||||
let value_range = InFile::new(hir_file, value).original_node_file_range_opt(db);
|
||||
let ((call_site_range, call_site_focus), def_site) =
|
||||
match InFile::new(hir_file, name).original_node_file_range_opt(db) {
|
||||
|
@ -421,7 +421,8 @@ fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Opt
|
||||
None
|
||||
}
|
||||
|
||||
let impl_def = self_param.syntax().ancestors().find_map(ast::Impl::cast)?;
|
||||
match self_param.syntax().ancestors().find_map(ast::Impl::cast) {
|
||||
Some(impl_def) => {
|
||||
let type_name = target_type_name(&impl_def)?;
|
||||
|
||||
let mut replacement_text = String::from(new_name);
|
||||
@ -434,6 +435,14 @@ fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: &str) -> Opt
|
||||
replacement_text.push_str(type_name.as_str());
|
||||
|
||||
Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
|
||||
}
|
||||
None => {
|
||||
cov_mark::hit!(rename_self_outside_of_methods);
|
||||
let mut replacement_text = String::from(new_name);
|
||||
replacement_text.push_str(": _");
|
||||
Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -1977,6 +1986,26 @@ impl Foo {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_self_outside_of_methods() {
|
||||
cov_mark::check!(rename_self_outside_of_methods);
|
||||
check(
|
||||
"foo",
|
||||
r#"
|
||||
fn f($0self) -> i32 {
|
||||
use self as _;
|
||||
self.i
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
fn f(foo: _) -> i32 {
|
||||
use self as _;
|
||||
foo.i
|
||||
}
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_self_in_path_to_parameter() {
|
||||
check(
|
||||
|
@ -59,7 +59,7 @@ mod tests {
|
||||
use expect_test::expect;
|
||||
use ide_assists::{Assist, AssistResolveStrategy};
|
||||
use ide_db::{
|
||||
base_db::salsa::Durability, symbol_index::SymbolsDatabase, FileRange, FxHashSet,
|
||||
base_db::ra_salsa::Durability, symbol_index::SymbolsDatabase, FileRange, FxHashSet,
|
||||
RootDatabase,
|
||||
};
|
||||
use test_fixture::WithFixture;
|
||||
|
@ -6,7 +6,7 @@ use hir::{
|
||||
};
|
||||
use ide_db::{
|
||||
base_db::{
|
||||
salsa::{
|
||||
ra_salsa::{
|
||||
debug::{DebugQueryTable, TableEntry},
|
||||
Query, QueryTable,
|
||||
},
|
||||
|
@ -45,7 +45,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||
.invalid_escape_sequence { color: #FC5555; text-decoration: wavy underline; }
|
||||
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
|
||||
</style>
|
||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
||||
<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span> <span class="keyword">as</span> <span class="module crate_root declaration">this</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">std</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">alloc</span> <span class="keyword">as</span> <span class="module crate_root declaration">abc</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="unresolved_reference">unresolved</span> <span class="keyword">as</span> <span class="module crate_root declaration">definitely_unresolved</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="unresolved_reference">unresolved</span> <span class="keyword">as</span> <span class="punctuation">_</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">test</span> <span class="keyword">as</span> <span class="module crate_root declaration">opt_in_crate</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">test</span> <span class="keyword">as</span> <span class="punctuation">_</span><span class="semicolon">;</span>
|
||||
<span class="keyword">extern</span> <span class="keyword">crate</span> <span class="module crate_root default_library library">proc_macro</span><span class="semicolon">;</span>
|
||||
</code></pre>
|
@ -874,14 +874,23 @@ pub fn block_comments2() {}
|
||||
fn test_extern_crate() {
|
||||
check_highlighting(
|
||||
r#"
|
||||
//- /main.rs crate:main deps:std,alloc
|
||||
//- /main.rs crate:main deps:std,alloc,test,proc_macro extern-prelude:std,alloc
|
||||
extern crate self as this;
|
||||
extern crate std;
|
||||
extern crate alloc as abc;
|
||||
extern crate unresolved as definitely_unresolved;
|
||||
extern crate unresolved as _;
|
||||
extern crate test as opt_in_crate;
|
||||
extern crate test as _;
|
||||
extern crate proc_macro;
|
||||
//- /std/lib.rs crate:std
|
||||
pub struct S;
|
||||
//- /alloc/lib.rs crate:alloc
|
||||
pub struct A
|
||||
pub struct A;
|
||||
//- /test/lib.rs crate:test
|
||||
pub struct T;
|
||||
//- /proc_macro/lib.rs crate:proc_macro
|
||||
pub struct ProcMacro;
|
||||
"#,
|
||||
expect_file!["./test_data/highlight_extern_crate.html"],
|
||||
false,
|
||||
|
@ -145,7 +145,7 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
|
||||
T![for] => types::for_type(p, false),
|
||||
// test precise_capturing
|
||||
// fn captures<'a: 'a, 'b: 'b, T>() -> impl Sized + use<'b, T> {}
|
||||
T![use] => {
|
||||
T![use] if p.nth_at(1, T![<]) => {
|
||||
p.bump_any();
|
||||
generic_param_list(p)
|
||||
}
|
||||
|
@ -188,10 +188,11 @@ impl<'a> Converter<'a> {
|
||||
|
||||
rustc_lexer::TokenKind::RawIdent => IDENT,
|
||||
|
||||
rustc_lexer::TokenKind::GuardedStrPrefix => {
|
||||
rustc_lexer::TokenKind::GuardedStrPrefix if self.edition.at_least_2024() => {
|
||||
err = "Invalid string literal (reserved syntax)";
|
||||
ERROR
|
||||
},
|
||||
}
|
||||
rustc_lexer::TokenKind::GuardedStrPrefix => POUND,
|
||||
|
||||
rustc_lexer::TokenKind::Literal { kind, .. } => {
|
||||
self.extend_literal(token_text.len(), kind);
|
||||
|
@ -0,0 +1,26 @@
|
||||
SOURCE_FILE
|
||||
IMPL
|
||||
IMPL_KW "impl"
|
||||
GENERIC_PARAM_LIST
|
||||
L_ANGLE "<"
|
||||
TYPE_PARAM
|
||||
NAME
|
||||
IDENT "T"
|
||||
COLON ":"
|
||||
WHITESPACE "\n"
|
||||
TYPE_BOUND_LIST
|
||||
ERROR
|
||||
USE_KW "use"
|
||||
WHITESPACE " "
|
||||
MACRO_CALL
|
||||
PATH
|
||||
PATH_SEGMENT
|
||||
NAME_REF
|
||||
IDENT "std"
|
||||
SEMICOLON ";"
|
||||
WHITESPACE "\n"
|
||||
error 8: expected R_ANGLE
|
||||
error 8: expected type
|
||||
error 11: expected `{`
|
||||
error 15: expected BANG
|
||||
error 15: expected `{`, `[`, `(`
|
@ -0,0 +1,2 @@
|
||||
impl<T:
|
||||
use std;
|
@ -553,7 +553,7 @@ impl ProjectWorkspace {
|
||||
ProjectWorkspaceKind::Json(project) => project
|
||||
.crates()
|
||||
.filter_map(|(_, krate)| krate.build.as_ref().map(|build| build.build_file.clone()))
|
||||
.map(AbsPathBuf::assert)
|
||||
.map(|build_file| self.workspace_root().join(build_file))
|
||||
.collect(),
|
||||
_ => vec![],
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ description = "A generic framework for on-demand, incrementalized computation (e
|
||||
rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
name = "salsa"
|
||||
name = "ra_salsa"
|
||||
|
||||
[dependencies]
|
||||
indexmap = "2.1.0"
|
||||
@ -23,7 +23,7 @@ oorandom = "11"
|
||||
triomphe = "0.1.11"
|
||||
itertools.workspace = true
|
||||
|
||||
salsa-macros = { version = "0.0.0", path = "salsa-macros" }
|
||||
ra-salsa-macros = { version = "0.0.0", path = "ra-salsa-macros", package = "salsa-macros" }
|
||||
|
||||
[dev-dependencies]
|
||||
linked-hash-map = "0.5.6"
|
@ -11,7 +11,7 @@ rust-version.workspace = true
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
name = "salsa_macros"
|
||||
name = "ra_salsa_macros"
|
||||
|
||||
[dependencies]
|
||||
heck = "0.4"
|
@ -1,4 +1,4 @@
|
||||
//! Implementation for `[salsa::database]` decorator.
|
||||
//! Implementation for `[ra_salsa::database]` decorator.
|
||||
|
||||
use heck::ToSnakeCase;
|
||||
use proc_macro::TokenStream;
|
||||
@ -32,7 +32,7 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
.iter()
|
||||
.map(|QueryGroup { group_path }| {
|
||||
quote! {
|
||||
<#group_path as salsa::plumbing::QueryGroup>::GroupStorage
|
||||
<#group_path as ra_salsa::plumbing::QueryGroup>::GroupStorage
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
@ -64,12 +64,12 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
|
||||
// ANCHOR:HasQueryGroup
|
||||
has_group_impls.extend(quote! {
|
||||
impl salsa::plumbing::HasQueryGroup<#group_path> for #database_name {
|
||||
impl ra_salsa::plumbing::HasQueryGroup<#group_path> for #database_name {
|
||||
fn group_storage(&self) -> &#group_storage {
|
||||
&self.#db_storage_field.query_store().#group_name_snake
|
||||
}
|
||||
|
||||
fn group_storage_mut(&mut self) -> (&#group_storage, &mut salsa::Runtime) {
|
||||
fn group_storage_mut(&mut self) -> (&#group_storage, &mut ra_salsa::Runtime) {
|
||||
let (query_store_mut, runtime) = self.#db_storage_field.query_store_mut();
|
||||
(&query_store_mut.#group_name_snake, runtime)
|
||||
}
|
||||
@ -98,13 +98,13 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let mut database_data = vec![];
|
||||
for QueryGroup { group_path } in query_groups {
|
||||
database_data.push(quote! {
|
||||
<#group_path as salsa::plumbing::QueryGroup>::GroupData
|
||||
<#group_path as ra_salsa::plumbing::QueryGroup>::GroupData
|
||||
});
|
||||
}
|
||||
|
||||
// ANCHOR:DatabaseStorageTypes
|
||||
output.extend(quote! {
|
||||
impl salsa::plumbing::DatabaseStorageTypes for #database_name {
|
||||
impl ra_salsa::plumbing::DatabaseStorageTypes for #database_name {
|
||||
type DatabaseStorage = __SalsaDatabaseStorage;
|
||||
}
|
||||
});
|
||||
@ -121,81 +121,81 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
fmt_ops.extend(quote! {
|
||||
#group_index => {
|
||||
let storage: &#group_storage =
|
||||
<Self as salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
<Self as ra_salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
storage.fmt_index(self, input, fmt)
|
||||
}
|
||||
});
|
||||
maybe_changed_ops.extend(quote! {
|
||||
#group_index => {
|
||||
let storage: &#group_storage =
|
||||
<Self as salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
<Self as ra_salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
storage.maybe_changed_after(self, input, revision)
|
||||
}
|
||||
});
|
||||
cycle_recovery_strategy_ops.extend(quote! {
|
||||
#group_index => {
|
||||
let storage: &#group_storage =
|
||||
<Self as salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
<Self as ra_salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
storage.cycle_recovery_strategy(self, input)
|
||||
}
|
||||
});
|
||||
for_each_ops.extend(quote! {
|
||||
let storage: &#group_storage =
|
||||
<Self as salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
<Self as ra_salsa::plumbing::HasQueryGroup<#group_path>>::group_storage(self);
|
||||
storage.for_each_query(runtime, &mut op);
|
||||
});
|
||||
}
|
||||
output.extend(quote! {
|
||||
impl salsa::plumbing::DatabaseOps for #database_name {
|
||||
fn ops_database(&self) -> &dyn salsa::Database {
|
||||
impl ra_salsa::plumbing::DatabaseOps for #database_name {
|
||||
fn ops_database(&self) -> &dyn ra_salsa::Database {
|
||||
self
|
||||
}
|
||||
|
||||
fn ops_salsa_runtime(&self) -> &salsa::Runtime {
|
||||
fn ops_salsa_runtime(&self) -> &ra_salsa::Runtime {
|
||||
self.#db_storage_field.salsa_runtime()
|
||||
}
|
||||
|
||||
fn synthetic_write(&mut self, durability: salsa::Durability) {
|
||||
fn synthetic_write(&mut self, durability: ra_salsa::Durability) {
|
||||
self.#db_storage_field.salsa_runtime_mut().synthetic_write(durability)
|
||||
}
|
||||
|
||||
fn fmt_index(
|
||||
&self,
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
fmt: &mut std::fmt::Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
match input.group_index() {
|
||||
#fmt_ops
|
||||
i => panic!("salsa: invalid group index {}", i)
|
||||
i => panic!("ra_salsa: invalid group index {}", i)
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_changed_after(
|
||||
&self,
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
revision: salsa::Revision
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
revision: ra_salsa::Revision
|
||||
) -> bool {
|
||||
match input.group_index() {
|
||||
#maybe_changed_ops
|
||||
i => panic!("salsa: invalid group index {}", i)
|
||||
i => panic!("ra_salsa: invalid group index {}", i)
|
||||
}
|
||||
}
|
||||
|
||||
fn cycle_recovery_strategy(
|
||||
&self,
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
) -> salsa::plumbing::CycleRecoveryStrategy {
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
) -> ra_salsa::plumbing::CycleRecoveryStrategy {
|
||||
match input.group_index() {
|
||||
#cycle_recovery_strategy_ops
|
||||
i => panic!("salsa: invalid group index {}", i)
|
||||
i => panic!("ra_salsa: invalid group index {}", i)
|
||||
}
|
||||
}
|
||||
|
||||
fn for_each_query(
|
||||
&self,
|
||||
mut op: &mut dyn FnMut(&dyn salsa::plumbing::QueryStorageMassOps),
|
||||
mut op: &mut dyn FnMut(&dyn ra_salsa::plumbing::QueryStorageMassOps),
|
||||
) {
|
||||
let runtime = salsa::Database::salsa_runtime(self);
|
||||
let runtime = ra_salsa::Database::salsa_runtime(self);
|
||||
#for_each_ops
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
//! Implementation for `[salsa::query_group]` decorator.
|
||||
//! Implementation for `[ra_salsa::query_group]` decorator.
|
||||
|
||||
use crate::parenthesized::Parenthesized;
|
||||
use heck::ToUpperCamelCase;
|
||||
@ -10,7 +10,7 @@ use syn::{
|
||||
ReturnType, TraitItem, Type,
|
||||
};
|
||||
|
||||
/// Implementation for `[salsa::query_group]` decorator.
|
||||
/// Implementation for `[ra_salsa::query_group]` decorator.
|
||||
pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let group_struct = parse_macro_input!(args as Ident);
|
||||
let input: ItemTrait = parse_macro_input!(input as ItemTrait);
|
||||
@ -82,7 +82,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
num_storages += 1;
|
||||
}
|
||||
_ => {
|
||||
return Error::new(span, format!("unknown salsa attribute `{name}`"))
|
||||
return Error::new(span, format!("unknown ra_salsa attribute `{name}`"))
|
||||
.to_compile_error()
|
||||
.into();
|
||||
}
|
||||
@ -100,7 +100,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
Some(invoke) if storage == QueryStorage::Input => {
|
||||
return Error::new(
|
||||
invoke.span(),
|
||||
"#[salsa::invoke] cannot be set on #[salsa::input] queries",
|
||||
"#[ra_salsa::invoke] cannot be set on #[ra_salsa::input] queries",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into();
|
||||
@ -155,7 +155,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
}
|
||||
};
|
||||
|
||||
// For `#[salsa::interned]` keys, we create a "lookup key" automatically.
|
||||
// For `#[ra_salsa::interned]` keys, we create a "lookup key" automatically.
|
||||
//
|
||||
// For a query like:
|
||||
//
|
||||
@ -257,7 +257,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
// difference in total compilation time in rust-analyzer, though
|
||||
// it's not totally obvious why that should be.
|
||||
fn __shim(db: &(dyn #trait_name + '_), #(#key_names: #keys),*) -> #value {
|
||||
salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*))
|
||||
ra_salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*))
|
||||
}
|
||||
__shim(self, #(#key_names),*)
|
||||
|
||||
@ -302,20 +302,20 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
|
||||
|
||||
# [doc = #set_constant_fn_docs]
|
||||
fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: salsa::Durability);
|
||||
fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability);
|
||||
});
|
||||
|
||||
query_fn_definitions.extend(quote! {
|
||||
fn #set_fn_name(&mut self, #(#key_names: #keys,)* value__: #value) {
|
||||
fn __shim(db: &mut dyn #trait_name, #(#key_names: #keys,)* value__: #value) {
|
||||
salsa::plumbing::get_query_table_mut::<#qt>(db).set((#(#key_names),*), value__)
|
||||
ra_salsa::plumbing::get_query_table_mut::<#qt>(db).set((#(#key_names),*), value__)
|
||||
}
|
||||
__shim(self, #(#key_names,)* value__)
|
||||
}
|
||||
|
||||
fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: salsa::Durability) {
|
||||
fn __shim(db: &mut dyn #trait_name, #(#key_names: #keys,)* value__: #value, durability__: salsa::Durability) {
|
||||
salsa::plumbing::get_query_table_mut::<#qt>(db).set_with_durability((#(#key_names),*), value__, durability__)
|
||||
fn #set_with_durability_fn_name(&mut self, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability) {
|
||||
fn __shim(db: &mut dyn #trait_name, #(#key_names: #keys,)* value__: #value, durability__: ra_salsa::Durability) {
|
||||
ra_salsa::plumbing::get_query_table_mut::<#qt>(db).set_with_durability((#(#key_names),*), value__, durability__)
|
||||
}
|
||||
__shim(self, #(#key_names,)* value__ ,durability__)
|
||||
}
|
||||
@ -324,7 +324,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
|
||||
// A field for the storage struct
|
||||
storage_fields.extend(quote! {
|
||||
#fn_name: std::sync::Arc<<#qt as salsa::Query>::Storage>,
|
||||
#fn_name: std::sync::Arc<<#qt as ra_salsa::Query>::Storage>,
|
||||
});
|
||||
}
|
||||
|
||||
@ -334,8 +334,8 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
quote! {
|
||||
#(#trait_attrs)*
|
||||
#trait_vis trait #trait_name :
|
||||
salsa::Database +
|
||||
salsa::plumbing::HasQueryGroup<#group_struct> +
|
||||
ra_salsa::Database +
|
||||
ra_salsa::plumbing::HasQueryGroup<#group_struct> +
|
||||
#bounds
|
||||
{
|
||||
#query_fn_declarations
|
||||
@ -348,7 +348,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
/// Representative struct for the query group.
|
||||
#trait_vis struct #group_struct { }
|
||||
|
||||
impl salsa::plumbing::QueryGroup for #group_struct
|
||||
impl ra_salsa::plumbing::QueryGroup for #group_struct
|
||||
{
|
||||
type DynDb = #dyn_db;
|
||||
type GroupStorage = #group_storage;
|
||||
@ -362,8 +362,8 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
impl<DB> #trait_name for DB
|
||||
where
|
||||
DB: #bounds,
|
||||
DB: salsa::Database,
|
||||
DB: salsa::plumbing::HasQueryGroup<#group_struct>,
|
||||
DB: ra_salsa::Database,
|
||||
DB: ra_salsa::plumbing::HasQueryGroup<#group_struct>,
|
||||
{
|
||||
#query_fn_definitions
|
||||
}
|
||||
@ -379,18 +379,18 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
let qt = &query.query_type;
|
||||
|
||||
let storage = match &query.storage {
|
||||
QueryStorage::Memoized => quote!(salsa::plumbing::MemoizedStorage<Self>),
|
||||
QueryStorage::LruMemoized => quote!(salsa::plumbing::LruMemoizedStorage<Self>),
|
||||
QueryStorage::Memoized => quote!(ra_salsa::plumbing::MemoizedStorage<Self>),
|
||||
QueryStorage::LruMemoized => quote!(ra_salsa::plumbing::LruMemoizedStorage<Self>),
|
||||
QueryStorage::LruDependencies => {
|
||||
quote!(salsa::plumbing::LruDependencyStorage<Self>)
|
||||
quote!(ra_salsa::plumbing::LruDependencyStorage<Self>)
|
||||
}
|
||||
QueryStorage::Input if query.keys.is_empty() => {
|
||||
quote!(salsa::plumbing::UnitInputStorage<Self>)
|
||||
quote!(ra_salsa::plumbing::UnitInputStorage<Self>)
|
||||
}
|
||||
QueryStorage::Input => quote!(salsa::plumbing::InputStorage<Self>),
|
||||
QueryStorage::Interned => quote!(salsa::plumbing::InternedStorage<Self>),
|
||||
QueryStorage::Input => quote!(ra_salsa::plumbing::InputStorage<Self>),
|
||||
QueryStorage::Interned => quote!(ra_salsa::plumbing::InternedStorage<Self>),
|
||||
QueryStorage::InternedLookup { intern_query_type } => {
|
||||
quote!(salsa::plumbing::LookupInternedStorage<Self, #intern_query_type>)
|
||||
quote!(ra_salsa::plumbing::LookupInternedStorage<Self, #intern_query_type>)
|
||||
}
|
||||
QueryStorage::Transparent => panic!("should have been filtered"),
|
||||
};
|
||||
@ -408,9 +408,9 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
impl #qt {
|
||||
/// Get access to extra methods pertaining to this query.
|
||||
/// You can also use it to invoke this query.
|
||||
#trait_vis fn in_db(self, db: &#dyn_db) -> salsa::QueryTable<'_, Self>
|
||||
#trait_vis fn in_db(self, db: &#dyn_db) -> ra_salsa::QueryTable<'_, Self>
|
||||
{
|
||||
salsa::plumbing::get_query_table::<#qt>(db)
|
||||
ra_salsa::plumbing::get_query_table::<#qt>(db)
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -439,7 +439,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
/// also set a cancellation flag. This will cause any query
|
||||
/// invocations in other threads to unwind with a `Cancelled`
|
||||
/// sentinel value and eventually let the `set` succeed once all
|
||||
/// threads have unwound past the salsa invocation.
|
||||
/// threads have unwound past the ra_salsa invocation.
|
||||
///
|
||||
/// If your query implementations are performing expensive
|
||||
/// operations without invoking another query, you can also use
|
||||
@ -448,13 +448,13 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
/// thus allowing the `set` to succeed. Otherwise, long-running
|
||||
/// computations may lead to "starvation", meaning that the
|
||||
/// thread attempting to `set` has to wait a long, long time. =)
|
||||
#trait_vis fn in_db_mut(self, db: &mut #dyn_db) -> salsa::QueryTableMut<'_, Self>
|
||||
#trait_vis fn in_db_mut(self, db: &mut #dyn_db) -> ra_salsa::QueryTableMut<'_, Self>
|
||||
{
|
||||
salsa::plumbing::get_query_table_mut::<#qt>(db)
|
||||
ra_salsa::plumbing::get_query_table_mut::<#qt>(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> salsa::QueryDb<'d> for #qt
|
||||
impl<'d> ra_salsa::QueryDb<'d> for #qt
|
||||
{
|
||||
type DynDb = #dyn_db + 'd;
|
||||
type Group = #group_struct;
|
||||
@ -462,7 +462,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
}
|
||||
|
||||
// ANCHOR:Query_impl
|
||||
impl salsa::Query for #qt
|
||||
impl ra_salsa::Query for #qt
|
||||
{
|
||||
type Key = (#(#keys),*);
|
||||
type Value = #value;
|
||||
@ -473,13 +473,13 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
const QUERY_NAME: &'static str = #query_name;
|
||||
|
||||
fn query_storage<'a>(
|
||||
group_storage: &'a <Self as salsa::QueryDb<'_>>::GroupStorage,
|
||||
group_storage: &'a <Self as ra_salsa::QueryDb<'_>>::GroupStorage,
|
||||
) -> &'a std::sync::Arc<Self::Storage> {
|
||||
&group_storage.#fn_name
|
||||
}
|
||||
|
||||
fn query_storage_mut<'a>(
|
||||
group_storage: &'a <Self as salsa::QueryDb<'_>>::GroupStorage,
|
||||
group_storage: &'a <Self as ra_salsa::QueryDb<'_>>::GroupStorage,
|
||||
) -> &'a std::sync::Arc<Self::Storage> {
|
||||
&group_storage.#fn_name
|
||||
}
|
||||
@ -501,10 +501,10 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
|
||||
let recover = if let Some(cycle_recovery_fn) = &query.cycle {
|
||||
quote! {
|
||||
const CYCLE_STRATEGY: salsa::plumbing::CycleRecoveryStrategy =
|
||||
salsa::plumbing::CycleRecoveryStrategy::Fallback;
|
||||
fn cycle_fallback(db: &<Self as salsa::QueryDb<'_>>::DynDb, cycle: &salsa::Cycle, #key_pattern: &<Self as salsa::Query>::Key)
|
||||
-> <Self as salsa::Query>::Value {
|
||||
const CYCLE_STRATEGY: ra_salsa::plumbing::CycleRecoveryStrategy =
|
||||
ra_salsa::plumbing::CycleRecoveryStrategy::Fallback;
|
||||
fn cycle_fallback(db: &<Self as ra_salsa::QueryDb<'_>>::DynDb, cycle: &ra_salsa::Cycle, #key_pattern: &<Self as ra_salsa::Query>::Key)
|
||||
-> <Self as ra_salsa::Query>::Value {
|
||||
#cycle_recovery_fn(
|
||||
db,
|
||||
cycle,
|
||||
@ -514,17 +514,17 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
const CYCLE_STRATEGY: salsa::plumbing::CycleRecoveryStrategy =
|
||||
salsa::plumbing::CycleRecoveryStrategy::Panic;
|
||||
const CYCLE_STRATEGY: ra_salsa::plumbing::CycleRecoveryStrategy =
|
||||
ra_salsa::plumbing::CycleRecoveryStrategy::Panic;
|
||||
}
|
||||
};
|
||||
|
||||
output.extend(quote_spanned! {span=>
|
||||
// ANCHOR:QueryFunction_impl
|
||||
impl salsa::plumbing::QueryFunction for #qt
|
||||
impl ra_salsa::plumbing::QueryFunction for #qt
|
||||
{
|
||||
fn execute(db: &<Self as salsa::QueryDb<'_>>::DynDb, #key_pattern: <Self as salsa::Query>::Key)
|
||||
-> <Self as salsa::Query>::Value {
|
||||
fn execute(db: &<Self as ra_salsa::QueryDb<'_>>::DynDb, #key_pattern: <Self as ra_salsa::Query>::Key)
|
||||
-> <Self as ra_salsa::Query>::Value {
|
||||
#invoke(db, #(#key_names),*)
|
||||
}
|
||||
|
||||
@ -539,7 +539,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) {
|
||||
fmt_ops.extend(quote! {
|
||||
#query_index => {
|
||||
salsa::plumbing::QueryStorageOps::fmt_index(
|
||||
ra_salsa::plumbing::QueryStorageOps::fmt_index(
|
||||
&*self.#fn_name, db, input.key_index(), fmt,
|
||||
)
|
||||
}
|
||||
@ -550,7 +550,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) {
|
||||
maybe_changed_ops.extend(quote! {
|
||||
#query_index => {
|
||||
salsa::plumbing::QueryStorageOps::maybe_changed_after(
|
||||
ra_salsa::plumbing::QueryStorageOps::maybe_changed_after(
|
||||
&*self.#fn_name, db, input.key_index(), revision
|
||||
)
|
||||
}
|
||||
@ -561,7 +561,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
for (Query { fn_name, .. }, query_index) in non_transparent_queries().zip(0_u16..) {
|
||||
cycle_recovery_strategy_ops.extend(quote! {
|
||||
#query_index => {
|
||||
salsa::plumbing::QueryStorageOps::cycle_recovery_strategy(
|
||||
ra_salsa::plumbing::QueryStorageOps::cycle_recovery_strategy(
|
||||
&*self.#fn_name
|
||||
)
|
||||
}
|
||||
@ -587,7 +587,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
#group_storage {
|
||||
#(
|
||||
#queries_with_storage:
|
||||
std::sync::Arc::new(salsa::plumbing::QueryStorageOps::new(group_index)),
|
||||
std::sync::Arc::new(ra_salsa::plumbing::QueryStorageOps::new(group_index)),
|
||||
)*
|
||||
}
|
||||
}
|
||||
@ -599,42 +599,42 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
|
||||
#trait_vis fn fmt_index(
|
||||
&self,
|
||||
db: &(#dyn_db + '_),
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
fmt: &mut std::fmt::Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
match input.query_index() {
|
||||
#fmt_ops
|
||||
i => panic!("salsa: impossible query index {}", i),
|
||||
i => panic!("ra_salsa: impossible query index {}", i),
|
||||
}
|
||||
}
|
||||
|
||||
#trait_vis fn maybe_changed_after(
|
||||
&self,
|
||||
db: &(#dyn_db + '_),
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
revision: salsa::Revision,
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
revision: ra_salsa::Revision,
|
||||
) -> bool {
|
||||
match input.query_index() {
|
||||
#maybe_changed_ops
|
||||
i => panic!("salsa: impossible query index {}", i),
|
||||
i => panic!("ra_salsa: impossible query index {}", i),
|
||||
}
|
||||
}
|
||||
|
||||
#trait_vis fn cycle_recovery_strategy(
|
||||
&self,
|
||||
db: &(#dyn_db + '_),
|
||||
input: salsa::DatabaseKeyIndex,
|
||||
) -> salsa::plumbing::CycleRecoveryStrategy {
|
||||
input: ra_salsa::DatabaseKeyIndex,
|
||||
) -> ra_salsa::plumbing::CycleRecoveryStrategy {
|
||||
match input.query_index() {
|
||||
#cycle_recovery_strategy_ops
|
||||
i => panic!("salsa: impossible query index {}", i),
|
||||
i => panic!("ra_salsa: impossible query index {}", i),
|
||||
}
|
||||
}
|
||||
|
||||
#trait_vis fn for_each_query(
|
||||
&self,
|
||||
_runtime: &salsa::Runtime,
|
||||
mut op: &mut dyn FnMut(&dyn salsa::plumbing::QueryStorageMassOps),
|
||||
_runtime: &ra_salsa::Runtime,
|
||||
mut op: &mut dyn FnMut(&dyn ra_salsa::plumbing::QueryStorageMassOps),
|
||||
) {
|
||||
#for_each_ops
|
||||
}
|
||||
@ -684,23 +684,23 @@ impl TryFrom<syn::Attribute> for SalsaAttr {
|
||||
}
|
||||
|
||||
fn is_not_salsa_attr_path(path: &syn::Path) -> bool {
|
||||
path.segments.first().map(|s| s.ident != "salsa").unwrap_or(true) || path.segments.len() != 2
|
||||
path.segments.first().map(|s| s.ident != "ra_salsa").unwrap_or(true) || path.segments.len() != 2
|
||||
}
|
||||
|
||||
fn filter_attrs(attrs: Vec<Attribute>) -> (Vec<Attribute>, Vec<SalsaAttr>) {
|
||||
let mut other = vec![];
|
||||
let mut salsa = vec![];
|
||||
// Leave non-salsa attributes untouched. These are
|
||||
// attributes that don't start with `salsa::` or don't have
|
||||
let mut ra_salsa = vec![];
|
||||
// Leave non-ra_salsa attributes untouched. These are
|
||||
// attributes that don't start with `ra_salsa::` or don't have
|
||||
// exactly two segments in their path.
|
||||
// Keep the salsa attributes around.
|
||||
// Keep the ra_salsa attributes around.
|
||||
for attr in attrs {
|
||||
match SalsaAttr::try_from(attr) {
|
||||
Ok(it) => salsa.push(it),
|
||||
Ok(it) => ra_salsa.push(it),
|
||||
Err(it) => other.push(it),
|
||||
}
|
||||
}
|
||||
(other, salsa)
|
||||
(other, ra_salsa)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
@ -12,7 +12,7 @@ use std::num::NonZeroU32;
|
||||
/// which are implemented for `u32` and `usize`:
|
||||
///
|
||||
/// ```
|
||||
/// # use salsa::InternId;
|
||||
/// # use ra_salsa::InternId;
|
||||
/// let intern_id1 = InternId::from(22_u32);
|
||||
/// let intern_id2 = InternId::from(22_usize);
|
||||
/// assert_eq!(intern_id1, intern_id2);
|
||||
@ -25,7 +25,7 @@ use std::num::NonZeroU32;
|
||||
/// `usize` using the `as_u32` or `as_usize` methods or the `From` impls.
|
||||
///
|
||||
/// ```
|
||||
/// # use salsa::InternId;
|
||||
/// # use ra_salsa::InternId;;
|
||||
/// let intern_id = InternId::from(22_u32);
|
||||
/// let value = u32::from(intern_id);
|
||||
/// assert_eq!(value, 22);
|
||||
@ -41,7 +41,7 @@ use std::num::NonZeroU32;
|
||||
/// word.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use salsa::InternId;
|
||||
/// # use ra_salsa::InternId;;
|
||||
/// InternId::from(InternId::MAX);
|
||||
/// ```
|
||||
///
|
||||
@ -70,7 +70,7 @@ impl InternId {
|
||||
/// Convert this raw-id into a u32 value.
|
||||
///
|
||||
/// ```
|
||||
/// # use salsa::InternId;
|
||||
/// # use ra_salsa::InternId;
|
||||
/// let intern_id = InternId::from(22_u32);
|
||||
/// let value = intern_id.as_usize();
|
||||
/// assert_eq!(value, 22);
|
||||
@ -82,7 +82,7 @@ impl InternId {
|
||||
/// Convert this raw-id into a usize value.
|
||||
///
|
||||
/// ```
|
||||
/// # use salsa::InternId;
|
||||
/// # use ra_salsa::InternId;
|
||||
/// let intern_id = InternId::from(22_u32);
|
||||
/// let value = intern_id.as_usize();
|
||||
/// assert_eq!(value, 22);
|
@ -745,6 +745,6 @@ impl Cycle {
|
||||
// Re-export the procedural macros.
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use]
|
||||
extern crate salsa_macros;
|
||||
extern crate ra_salsa_macros;
|
||||
use plumbing::HasQueryGroup;
|
||||
pub use salsa_macros::*;
|
||||
pub use ra_salsa_macros::*;
|
@ -1,7 +1,7 @@
|
||||
use std::panic::UnwindSafe;
|
||||
|
||||
use expect_test::expect;
|
||||
use salsa::{Durability, ParallelDatabase, Snapshot};
|
||||
use ra_salsa::{Durability, ParallelDatabase, Snapshot};
|
||||
|
||||
// Axes:
|
||||
//
|
||||
@ -49,13 +49,13 @@ struct Error {
|
||||
cycle: Vec<String>,
|
||||
}
|
||||
|
||||
#[salsa::database(GroupStruct)]
|
||||
#[ra_salsa::database(GroupStruct)]
|
||||
#[derive(Default)]
|
||||
struct DatabaseImpl {
|
||||
storage: salsa::Storage<Self>,
|
||||
storage: ra_salsa::Storage<Self>,
|
||||
}
|
||||
|
||||
impl salsa::Database for DatabaseImpl {}
|
||||
impl ra_salsa::Database for DatabaseImpl {}
|
||||
|
||||
impl ParallelDatabase for DatabaseImpl {
|
||||
fn snapshot(&self) -> Snapshot<Self> {
|
||||
@ -75,37 +75,37 @@ enum CycleQuery {
|
||||
AthenC,
|
||||
}
|
||||
|
||||
#[salsa::query_group(GroupStruct)]
|
||||
trait Database: salsa::Database {
|
||||
#[ra_salsa::query_group(GroupStruct)]
|
||||
trait Database: ra_salsa::Database {
|
||||
// `a` and `b` depend on each other and form a cycle
|
||||
fn memoized_a(&self) -> ();
|
||||
fn memoized_b(&self) -> ();
|
||||
fn volatile_a(&self) -> ();
|
||||
fn volatile_b(&self) -> ();
|
||||
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn a_invokes(&self) -> CycleQuery;
|
||||
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn b_invokes(&self) -> CycleQuery;
|
||||
|
||||
#[salsa::input]
|
||||
#[ra_salsa::input]
|
||||
fn c_invokes(&self) -> CycleQuery;
|
||||
|
||||
#[salsa::cycle(recover_a)]
|
||||
#[ra_salsa::cycle(recover_a)]
|
||||
fn cycle_a(&self) -> Result<(), Error>;
|
||||
|
||||
#[salsa::cycle(recover_b)]
|
||||
#[ra_salsa::cycle(recover_b)]
|
||||
fn cycle_b(&self) -> Result<(), Error>;
|
||||
|
||||
fn cycle_c(&self) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
fn recover_a(db: &dyn Database, cycle: &salsa::Cycle) -> Result<(), Error> {
|
||||
fn recover_a(db: &dyn Database, cycle: &ra_salsa::Cycle) -> Result<(), Error> {
|
||||
Err(Error { cycle: cycle.all_participants(db) })
|
||||
}
|
||||
|
||||
fn recover_b(db: &dyn Database, cycle: &salsa::Cycle) -> Result<(), Error> {
|
||||
fn recover_b(db: &dyn Database, cycle: &ra_salsa::Cycle) -> Result<(), Error> {
|
||||
Err(Error { cycle: cycle.all_participants(db) })
|
||||
}
|
||||
|
||||
@ -155,10 +155,10 @@ fn cycle_c(db: &dyn Database) -> Result<(), Error> {
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> salsa::Cycle {
|
||||
fn extract_cycle(f: impl FnOnce() + UnwindSafe) -> ra_salsa::Cycle {
|
||||
let v = std::panic::catch_unwind(f);
|
||||
if let Err(d) = &v {
|
||||
if let Some(cycle) = d.downcast_ref::<salsa::Cycle>() {
|
||||
if let Some(cycle) = d.downcast_ref::<ra_salsa::Cycle>() {
|
||||
return cycle.clone();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user